I've seen similar questions asked before but the solutions I tried not working very well.
Here is part of the code. First, a label is defined.
UILabel* _label;
...
Below is the animation code inside touchesBegan of the label. So basically, when the label is clicked, I would like to gradually fade in background image and change the text color.
_label.backgroundColor = [UIColor clearColor];
_label.textColor = [UIColor blackColor];
UIImage* image = [UIImage imageNamed:#"tile.png"];
CGSize imageSize = _label.frame.size;
UIGraphicsBeginImageContext(imageSize);
[image drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[UIView animateWithDuration:2.0
animations:^{
_label.backgroundColor = [UIColor colorWithPatternImage:newImage];
_label.textColor = [UIColor whiteColor];
[UIView setAnimationDidStopSelector:#selector(highlightEnded:finished:context:)];
}
completion:^(BOOL finished){
NSLog(#"stoped");
}];
The image background and text color change correctly, but no animation; both of them changes rapidly.
Thanks for the tip.
You should use transitionWithView:duration:options:animations:completion: instead of animateWithDuration: when animating text.
After trying half a dozen or so suggestions, I found one way that guarantees to work is to add an extra UIImageView as the background (set the background color of label as clearColor), then animate through its alpha. This is as good as I can solve.
You can't animate text color changes or background image changes.
What you can do is
image1.alpha = 0;
image2.alpha = 1;
[UIView animateWithDuration:.3 animations:^{
image1.alpha = 1;
image2.alpha = 0;
}];
This would give you a fade effect.
You could manually insert image1 and image2 as subViews of the label.
CATransition *animation = CATransition.animation;
animation.duration = 1.0;
animation.type = kCATransitionFade;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[viewToFade.layer addAnimation:animation forKey:#"fade"];
Should work with both image views and labels.
Related
Facing problem when adding rounded corners to imageview.
here is my code
CALayer * lay = [imageview layer];
[lay setMasksToBounds:YES];
[lay setCornerRadius:10.0];
[lay setBorderWidth:5.0];
[lay setBorderColor:[[UIColor clearColor] CGColor]];
imageview.layer.rasterizationScale = [UIScreen mainScreen].scale;
imageview.layer.shouldRasterize = YES;
And its working fine but if I am resizing the imageview, its not making corners round.
Here is my resizing code:
[UIView animateWithDuration:0.2 animations:^ {
[imageview setTransform:CGAffineTransformMakeScale(1.1, 1.1)];
CALayer * l = [imageview layer];
[l setMasksToBounds:YES];
[l setCornerRadius:10.0];
[l setBorderWidth:5.0];
[l setBorderColor:[[UIColor clearColor] CGColor]];
imageview.layer.rasterizationScale = [UIScreen mainScreen].scale;
imageview.layer.shouldRasterize = YES;
newimage = imageview.image;
[[NSUserDefaults standardUserDefaults] setValue:UIImageJPEGRepresentation(newimage,1.1) forKey:#"newimage"];
}];
Any help would be appreciated.
You can set corner radius from storyboard or XIB hope it will work, Please check This.
Plz import the QuartzCore/QuartzCore.h
and then write the code ...
yourImageView.layer.cornerRadius = yourRadius;
yourImageView.clipsToBounds = YES;
Why to write the clipsToBounds property
A Boolean value that determines whether subviews are confined to the bounds of the view.
Discussion
Setting this value to YES causes subviews to be clipped to the bounds of the receiver. If set to NO, subviews whose frames extend beyond the visible bounds of the receiver are not clipped. The default value is NO.
Try
[UIView animateWithDuration:0.2
delay:0.1
options: UIViewAnimationOptionCurveEaseOut
animations:^
{
[imageview setTransform:CGAffineTransformMakeScale(1.1, 1.1)];
}
completion:^(BOOL finished)
{
[imageview.layer setCornerRadius:10.0];
imageview.clipsToBounds = YES;
imageview.layer.masksToBounds = YES;
[imageview.layer setBorderWidth:5.0];
[imageview.layer setBorderColor:[[UIColor clearColor] CGColor]];
newimage = imageview.image;
[[NSUserDefaults standardUserDefaults] setValue:UIImageJPEGRepresentation(newimage,1.1) forKey:#"newimage"];
}];
You have to round corners after animation complete. You may get animation completion as above.
I'm trying to making a kind of color pulse effect animating background color of a UIButton to make it change continously from a color (WhiteColor) to another one (RedColor).
I'm trying to use CABasicAnimation for changing Opacity but I can't make it work with color too.
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:#"opacity"];
theAnimation.duration=1.0;
theAnimation.repeatCount=HUGE_VALF;
theAnimation.autoreverses=YES;
theAnimation.fromValue=[NSNumber numberWithFloat:1.0];
theAnimation.toValue=[NSNumber numberWithFloat:0.0];
[BigButton.layer addAnimation:theAnimation forKey:#"animateOpacity"];
Every suggestion would be appreciated.
Thanks
I found the right way. You need to remember about CGColor. This was my mistake. Compiler didn't help here.
Objective C
CABasicAnimation *theAnimation=[CABasicAnimation animationWithKeyPath:#"backgroundColor"];
theAnimation.duration=1.0;
theAnimation.repeatCount=HUGE_VALF;
theAnimation.autoreverses=YES;
theAnimation.fromValue= [[UIColor redColor] CGColor];
theAnimation.toValue= [[UIColor blueColor] CGColor];
[BigButton.layer addAnimation:theAnimation forKey:#"ColorPulse"];
Swift
let colorAnimation = CABasicAnimation(keyPath: "backgroundColor")
colorAnimation.fromValue = UIColor.redColor().CGColor
colorAnimation.toValue = UIColor.blueColor().CGColor
colorAnimation.duration = 1
colorAnimation.autoreverses = true
colorAnimation.repeatCount = FLT_MAX
self.layer.addAnimation(colorAnimation, forKey: "ColorPulse")
I finally found out solution:
I made a two frames animation in which I first change background color to Red and in the second frame I turn it white. I can also manipulate relative durations
[UIView animateKeyframesWithDuration:2.0 delay:0.0 options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 animations:^{
someView.backgroundColor = [UIColor redColor];
}];
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.5 animations:^{
someView.backgroundColor = [UIColor whiteColor];
}];
} completion:nil];
Swift 4 - Animate any change on a button (backgroundColor, title, titleColor):
UIView.transition(with: yourButton, duration: 0.3, options: .curveEaseInOut, animations: {
self.yourButton.backgroundColor = UIColor.red
self.yourButton.setTitle("new title", for: .normal)
self.yourButton.setTitleColor(.white, for: .normal)
})
I want to achieve the text appearance like in the pictures below:
Now I'm working on shadow around the letters and I can't figure out how to do that.
What I've tried so far:
- The solution with:
label.shadowColor = [UIColor blackColor];
label.shadowOffset = CGSizeMake(1, 2);
gives a nice sharp shadow, but it doesn't fit my needs by two reasons:
It gives a shadow only from one side, set up by shadowOffset, whereas I need a "wrapping" shadow;
This solution doesn't give the soft part of the shadow (gradient) as there is in the pictures;
-The solution with:
label.layer.shadowOffset = CGSizeMake(0, 0);
label.layer.shadowRadius = 5.0;
label.layer.shouldRasterize = YES;
label.layer.shadowOpacity = 1;
label.layer.shadowColor = [UIColor blackColor].CGColor;
label.layer.masksToBounds = NO;
Works great, but it gives too soft shadow even though the shadowOpacity is set to 1 and the shadowColor is set to black:
Obviously it's not enough and I already think about drawing in labels' context. But it is not clear to me how would I achieve the goal even through context drawing.
Any idea would be much appreciated.
Try this
Create a Custom UILabel SubClass and Override the following method
- (void)drawTextInRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetShadow(context, CGSizeMake(0.0, 0.0), 10);
CGContextSetShadowWithColor(context, CGSizeMake(0.0, 0.0), 10, [UIColor blackColor].CGColor);
[super drawTextInRect:rect];
CGContextRestoreGState(context);
}
and this bottomColorLayer to the Label
CALayer *bottomColorLayer = [CALayer layer];
bottomColorLayer.frame = CGRectMake(0, labelRect.size.height/2, labelRect.size.width, labelRect.size.height/2);
bottomColorLayer.backgroundColor = [[UIColor colorWithWhite:0 alpha:.5] CGColor];
[label.layer insertSublayer:bottomColorLayer above:(CALayer *)label.layer];
or If you want Gradient
CAGradientLayer *bottomGradient = [CAGradientLayer layer];
bottomGradient.frame = CGRectMake(0, labelRect.size.height/2, labelRect.size.width, labelRect.size.height/2);
bottomGradient.cornerRadius = 0.0f;
bottomGradient.colors = #[(id)[[UIColor colorWithWhite:1 alpha:.5] CGColor], (id)[[UIColor colorWithWhite:0 alpha:.5] CGColor]];
[label.layer insertSublayer:bottomGradient above:(CALayer *)label.layer];
Use an explicit shadow path that's the shape you want. It sounds like you want a shadow the same shape as your text, but larger, with each shadow-letter centered on its corresponding letter. Once you have that, use the shadow radius to soften the edges of the shadow to whatever degree you want.
The code you have relies on the shadow radius alone to make the shadow larger than the text, which removes your ability to control the softness.
Try with the code below :-
[_testLable setText:#"TION ERRO"];
[_testLable setTextColor:[UIColor whiteColor]];
[_testLable setFont:[UIFont boldSystemFontOfSize:22] ];
_testLable.layer.shadowOffset = CGSizeMake(0, 0);
_testLable.layer.shadowRadius = 10.0;
_testLable.layer.shouldRasterize = YES;
_testLable.layer.shadowOpacity = 1;
_testLable.layer.shadowColor = [UIColor blackColor].CGColor;
_testLable.layer.masksToBounds = NO;
CGPathRef shadowPath = CGPathCreateWithRect(_testLable.bounds, NULL);
_testLable.layer.shadowPath = shadowPath;
CGPathRelease(shadowPath);
Its output is like this:-
I have a UIViewController with a UITableView. The sits inside the view controller's view with some padding on all sides. I am trying to draw a drop shadow from the table view as well as rounded corners, but I am unable to achieve both at the same time. I have tried with the following code and turned masksToBounds on and off, but setting it to NO create a really weird effect with the shadow scrolling and the calls are not clipping inside the table.
[self.tableView.layer setShadowColor:[UIColor blackColor].CGColor];
[self.tableView.layer setShadowOffset:CGSizeMake(0, 3)];
[self.tableView.layer setShadowOpacity:0.4];
[self.tableView.layer setShadowRadius:3.0f];
[self.tableView.layer setCornerRadius:5.0f];
[self.tableView.layer setShadowPath:[[UIBezierPath bezierPathWithRoundedRect:self.tableView.bounds cornerRadius:5.0f] CGPath]];
I am just drawing a UITableView with plain style too. The effect I am trying to achieve can be seen in the free app Transit App and here's a movie where you can see the shadow stays and the table even has a mask that scrolls up and down.
I have searched and searched and haven't been able to put together a solution based on other SO answers or online articles. Help appreciated.
Try the below links, some of them are old but you can get some pointer.
Custom Table Effects
Dropshadow 2
Cool Table Views
DropShadow
Okay!! I attempted once again and got an effect, it is again a work around only (instead of using images), the below is what i tried
Create a CALayer, with the same frame as your tableview, give the same curve and all, add the table view on top of this layer, thats it.
CALayer *sublayer = [CALayer layer];
sublayer.backgroundColor = [UIColor blueColor].CGColor; // If you dont give this, shadow will not come, dont know why
sublayer.shadowOffset = CGSizeMake(0, 3);
sublayer.shadowRadius = 5.0;
sublayer.shadowColor = [UIColor blackColor].CGColor;
sublayer.shadowOpacity = 1.0;
sublayer.cornerRadius = 5.0;
sublayer.frame = CGRectMake(myTable.frame.origin.x, myTable.frame.origin.y, myTable.frame.size.width, myTable.frame.size.height);
[self.view.layer addSublayer:sublayer];
[self.view.layer addSublayer:myTable.layer];
Ah!! due to some reason I am unable to upload the screenshot from my machine, firewall ;-). I will try from my home.
-anoop
It is recommended to use images for drop shadows with large tableviews, all that drawing has the ability to slow down performance, which can result in bad user experience, just a word of advice
I know this is a rather old question, but I recently had the same problem and the solutions here were good examples, but not full enough. So here it is the method I'm using to create shadow of a table view. It can be used also for any other view.
-(void)makeShadowToView:(UIView*) view withHeight:(CGFloat)shadowHeight
{
CGRect bounds = view.frame;
bounds.size.height = shadowHeight;
view.clipsToBounds = NO; // Without this row it doesn't display any shadow, at least for a table view
view.layer.shadowColor = [UIColor blackColor].CGColor;
view.layer.shadowOpacity = 0.9f;
view.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
view.layer.shadowRadius = 5.0f;
view.layer.shadowPath = [UIBezierPath bezierPathWithRect:bounds].CGPath;
}
Example usage: [self makeShadowToView:self.view withHeight:height];
where height is added in case you want to recalculate the shadow's height according to the table content's height.
(void)shadowForView{
CALayer *layer = self.viewActionMenu.layer;
layer.shadowOffset = CGSizeMake(-2, 0);
layer.shadowColor = [[UIColor blackColor] CGColor];
layer.shadowRadius = 2.0f;
layer.shadowOpacity = 0.80f;
// [self.view bringSubviewToFront:self.actionView];
}
And Call:
[self shadowForView];
Try this
UITableView * objTableview=[[UITableView alloc]initWithFrame:CGRectMake(x, y, w, h)];
UIView * objViewShadow=[[UIView alloc]initWithFrame:objTableview.bounds];
objTableview.layer.cornerRadius=5;
// add shadow
objViewShadow.layer.shadowOffset = CGSizeMake(0, 3);
objViewShadow.layer.shadowRadius = 5.0;
objViewShadow.layer.shadowColor = [UIColor blackColor].CGColor;
objViewShadow.layer.shadowOpacity = 0.8;
[objViewShadow addSubview:objTableview];
[self.view addSubview:objViewShadow];
You need to set this two properties
self.tableView.clipsToBounds = NO;
self.tableView.layer.masksToBounds = NO;
I have a somewhat unusual problem. In my app, I am shadowing a UIImageView using basic Quartz2d layer shadowing. Here's my code:
imageView.layer.shadowOpacity = 1.0; // Pretty self explanatory
imageView.layer.shadowRadius = 8.0; // My softness
imageView.layer.shadowColor = [UIColor blackColor].CGColor; // Color of the shadow
imageView.layer.shadowOffset = CGSizeMake(0.0, 0.0); // Offset of the shadow
This produces a nice blur behind the image view. However, I am doing some animation with this view, and the constant recalculation of the shadowing during the transitions causes a very choppy transition. What I'd like to be able to do is create a UIImage or .png file out of the image view with the blur and its alpha intact. Here's what I've already tried:
UIGraphicsBeginImageContext(CGSizeMake(320, 396));
[imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
Since I have a shadow which "grows outside" of the image view, I can't just pass his size in the UIGraphicsBeginImageContext function. I set the correct size, but the resulting image doesn't save my alpha, instead it places a white background behind the shadow, which won't work for me because my real background is a wood texture. Also, the view isn't centered in the resulting file.
I'm pretty good with UIKit, but I'm a real noobie with Quartz 2d graphics, so if there's an obvious answer to this, send it anyway. :)
Try setting your UIImageView's backgroundColor to [UIColor clearColor] - this may enable your current solution to work.
imageView.backgroundColor = [UIColor clearColor];
UIGraphicsBeginImageContext(CGSizeMake(320, 396));
[imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Source: Converting a CGLayer to a *transparent* UIImage and PNG file in CoreGraphics iphone
I've had this issue before too. My solution was not to do an image, but instead to set the shadow path to just the outline of the view you are animating.
[imageView setContentMode:UIViewContentModeScaleAspectFit];
imageView.layer.masksToBounds = NO;
imageView.layer.shadowOffset = CGSizeMake(5, 5);
imageView.layer.shadowRadius = 200;
imageView.layer.shadowOpacity = 0.5;
CGRect rect = [self rectFromImageView:imageView];
imageView.layer.shadowPath = [UIBezierPath bezierPathWithRect:rect].CGPath;
Which uses the following function which assumes the image is set to content mode aspect fit:
-(CGRect)rectFromImageView:(UIImageView *)iv {
CGRect rect = (CGRect){{0,0},iv.frame.size};
if (iv.image.size.width/iv.frame.size.width > iv.image.size.height/iv.frame.size.height) {
//rect.origin.x == 0
CGFloat sf = iv.frame.size.width/iv.image.size.width;
rect.size.height = sf*iv.image.size.height;
rect.origin.y = floor((iv.frame.size.height - rect.size.height)/2);
} else {
//rect.origin.y == 0;
CGFloat sf = iv.frame.size.height/iv.image.size.height;
rect.size.width = sf*iv.image.size.width;
rect.origin.x = floor((iv.frame.size.width - rect.size.width)/2);
}
return rect;
}
If your image is just set to fill then just using the imageView.bounds should be sufficient
Add shadow path to view like this
[view.layer setShadowPath:[[UIBezierPath bezierPathWithRect:view.bounds] CGPath]]; //add path
view.layer.shadowColor = [[UIColor blackColor] CGColor];
view.layer.shadowOffset = CGSizeMake(x, y);
view.layer.shadowRadius = rad;
view.layer.shadowOpacity = 0.2f;