views:

501

answers:

3

I want to create "rounded" "semi-transparent" UIView (or anything does similar) my code below results in animation effects, gradually change transparent density. What I want is to avoid this effects and draw the resulting image straight from the beginning.

Can anyone know how to do? Thank you.

- (id)initWithFrame:(CGRect)frame 
{
    if (self = [super initWithFrame:frame]) 
    {
        // Initialization code
        super.opaque = NO;
        self.alpha = 1.0f;
        self.strokeColor = kDefaultStrokeColor;
        super.backgroundColor = [UIColor clearColor];
        self.rectColor = kDefaultRectColor;
        self.strokeWidth = kDefaultStrokeWidth;
        self.cornerRadius = kDefaultCornerRadius;
        self.contentMode = UIViewContentModeRedraw;
        self.clearsContextBeforeDrawing = NO;
    }
    return self;
}
- (void)setBackgroundColor:(UIColor *)newBGColor
{
    // Ignore attempt to set backgroundColor
}
- (void)setOpaque:(BOOL)newIsOpaque
{
    // Ignore attempt to set opaque to YES.
}
- (void)drawRect:(CGRect)rect {
    BOOL areEnabled = [UIView areAnimationsEnabled];

    // with or without setAnimationsEnabled:NO gives me the same result
    [UIView setAnimationsEnabled:NO];

        // with or without beginAnimations and commitAnimations gives me the same result
    [UIView beginAnimations:@"test" context:nil];

    [UIView setAnimationRepeatCount:1];
//  [UIView setAnimationBeginsFromCurrentState:YES];

    // With or without setAnimationDelay gives me the same result
    //[UIView setAnimationDelay:0.0f];
        // With or without setAnimationDuration gives me the same result
        // passing 0.0f the same
    //[UIView setAnimationDuration:0.1f];


    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextBeginPath(context);

    CGContextSetLineWidth(context, strokeWidth);
    CGContextSetStrokeColorWithColor(context, self.strokeColor.CGColor);
    CGContextSetFillColorWithColor(context, self.rectColor.CGColor);

    CGRect rrect = self.bounds;

    CGFloat radius = cornerRadius;
    CGFloat width = CGRectGetWidth(rrect);
    CGFloat height = CGRectGetHeight(rrect);

    // Make sure corner radius isn't larger than half the shorter side
    if (radius > width/2.0)
        radius = width/2.0;
    if (radius > height/2.0)
        radius = height/2.0;    

    CGFloat minx = CGRectGetMinX(rrect);
    CGFloat midx = CGRectGetMidX(rrect);
    CGFloat maxx = CGRectGetMaxX(rrect);
    CGFloat miny = CGRectGetMinY(rrect);
    CGFloat midy = CGRectGetMidY(rrect);
    CGFloat maxy = CGRectGetMaxY(rrect);
    CGContextMoveToPoint(context, minx, midy);
    CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
    CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
    CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
    CGContextClosePath(context);
    CGContextDrawPath(context, kCGPathFillStroke);
    CGContextClip(context); 

   [UIView commitAnimations];

   [UIView setAnimationsEnabled:areEnabled];

   // I am stacked...   
}
+2  A: 

Here's how I've done it in a Cocoa Touch application that I've been working on:

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
// Change opacity (or whatever) here.
[CATransaction commit];

Not sure if this is the best way to do it (or if it'll even work outside the iPhone environment), as I'm a bit of a Cocoa novice myself. Could be worth a try, though.

David
still gives me animated effects (gradually change transparency)The point is that I don't change alpha(or opacity) value, the effects do...Is this because I use CG functions to draw rectangle?
Katsumi
David, it was my mistake in other class, the class which does Open GL things (I needed to have dashed lines with width smaller than UIKit provides)then in that draw method I created this UIView (I was experimenting how I can add "semi-transparent" "rounded" UIView subclass...didn't think too much where to put experimenting codes...)Anyway, thank you for your comment.I know know CATransaction basicsThank you again!
Katsumi
+1  A: 

Using UIView animations from within drawRect is pointless. Also, it's not possible to disable animations by overwriting UIView properties since CoreAnimation animates layer—not view—properties. If the alpha fades when using one of you views, the problem is not in your classe's implementation, but from where it is called. Some surrounding code did [UIView beginAnimations] before setting your view's or superview's alpha.

Do disable all animations, you can use the method proposed by David.

Nikolai Ruhe
David, thank you for your comment.I got your point.Now, I see many "Calendar applications" showing event(or todo) showing with some transparency (and even with shadow)I wonder how those are done, setting up animation disable and only set up animation when needed would cause the same problem right?Katsumi (if I ask too primitive questions, excuse me I'm first year objective-c programmer)
Katsumi
Ops, the message above is for "Nikolai"Thank you both!
Katsumi
NikolaiI finally got it.It was very simple mistakes I had in other class, the class which draw OpenGL ES codes.As I experimenting the way to draw "semi-transparent, rounded view" I put the code in that draw method...so each time adding new semi-transparent UIView inifinitly...Thank you very much anyway, I'll remember your point as I will need those techs in the future.
Katsumi
+1  A: 

As of 3.0, you can have any view round corners easily:

1) Set clipsToBounds to YES.

2) set view.layer.cornerRadius to some value (5.0 is pretty good, but you can play with values). This also requires you to #import <QuartzCore/QuartzCore.h> in the file where you are setting this property.

All done!

If you are using IB to define views, you can set the subview clipping in IB but you can't modify the layer properties, so you'll have to add that part in viewDidLoad or somewhere similar.

Kendall Helmstetter Gelner
Kendall,Thank you for your comment!I couldn't find "clipsSubviews" but did find "clipsToBounds"So instead of doing overwriting drawRect, in initialization method of my UIView subclass, I did the followings: self.clipsToBounds = YES; self.layer.cornerRadius = 5.0f;I got rounded view!Thank you!
Katsumi
I think it's "Clip Subviews" in IB, but the actual property (that you found) is clipsToBounds. I corrected my code here so that others would not have to hunt for it... thanks for the response.
Kendall Helmstetter Gelner