UIButton Rounded Rect unwanted 3D effect - iphone

I had a couple of UIButtons on a nib of type RoundedRect which before iOS 6 looked nice and flat. In iOS 6 though they've acquired a 3D effect border which I cannot get rid of (I'd supply a pic but my reputation is too puny). Can anybody suggest how to get the nice flat look back?
I'm sure this will turn out to be the stupidest question I've ever asked and that the answer will be so simple I'll kick myself for a week. But I can't find it and any help would be much appreciated.

I don't know why that effect appeared , but one way to do this is to avoid Rounded Rect.
I always use custom buttons. You can customize them in code in any way you want .
For example:
button.layer.cornerRadius = 8; //this gives it rounded corners
button.layer.borderColor = [[UIColor redColor] CGColor] ; // this is how you set a border
button.layer.borderWidth = 2; //this is how you set the width of the border
The layer member of the UIButton is a CALayer and you can set shadows to it . This is a good tutorial.
You can also add a gradient background in order to make the button nicer , like this:
CAGradientLayer *layer = [CAGradientLayer layer];
layer.colors = [NSArray arrayWithObjects:
(id)[[UIColor colorWithRed:skinRed green:skinGreen blue:skinBlue alpha:0.9] CGColor],
(id)[[UIColor colorWithRed:skinRed green:skinGreen blue:skinBlue alpha:0.8] CGColor],
(id)[[UIColor colorWithRed:skinRed green:skinGreen blue:skinBlue alpha:0.7] CGColor],
(id)[[UIColor colorWithRed:skinRed green:skinGreen blue:skinBlue alpha:0.6] CGColor],
(id)[[UIColor colorWithRed:skinRed green:skinGreen blue:skinBlue alpha:0.5] CGColor],
(id)[[UIColor colorWithRed:skinRed green:skinGreen blue:skinBlue alpha:0.4] CGColor],
(id)[[UIColor colorWithRed:skinRed green:skinGreen blue:skinBlue alpha:0.3] CGColor],
(id)[[UIColor colorWithRed:skinRed green:skinGreen blue:skinBlue alpha:0.2] CGColor],
(id)[[UIColor colorWithRed:skinRed green:skinGreen blue:skinBlue alpha:0.1] CGColor],
(id)[[UIColor colorWithRed:skinRed green:skinGreen blue:skinBlue alpha:0.0] CGColor],
nil];
layer.locations = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.1],
[NSNumber numberWithFloat:0.2],
[NSNumber numberWithFloat:0.3],
[NSNumber numberWithFloat:0.4],
[NSNumber numberWithFloat:0.5],
[NSNumber numberWithFloat:0.6],
[NSNumber numberWithFloat:0.7],
[NSNumber numberWithFloat:0.8],
[NSNumber numberWithFloat:0.9],
[NSNumber numberWithFloat:1.0],
nil];
layer.startPoint = CGPointMake(0, 0);
layer.frame = button.layer.bounds;
layer.endPoint = CGPointMake(0, 1);
layer.contentsGravity = kCAGravityResize;
[button.layer insertSublayer:layer below:button.titleLabel.layer];
button.layer.masksToBounds = TRUE;
As you can see , a nice touch would be to have some global int vars that define the RGB of the app's skin. This way you can modify it in seconds.
So , by using this way you are imune to the changes that Apple makes over SDK versions.
And you can customize it in any way that you want , achieving much more than you could ever get in IB.
Hope this helps.
Cheers!

Related

Problems with CAGradientLayer

Im using the code
NSArray *buttons = [NSArray arrayWithObjects: self.rollBtn,nil];
for(UIButton *btn in buttons)
{
btn.layer.shadowRadius = 3.0;
btn.layer.shadowOffset = CGSizeMake(-2.0, -3.0);
btn.layer.shadowOpacity = 0.5;
btn.layer.shadowColor = [UIColor blackColor].CGColor;
CAGradientLayer *btnGradient = [CAGradientLayer layer];
btnGradient.frame = btn.bounds;
btnGradient.colors = [NSArray arrayWithObjects:
(id)[[UIColor colorWithRed:102.0f / 255.0f green:102.0f / 255.0f blue:102.0f / 255.0f alpha:1.0f] CGColor],
(id)[[UIColor colorWithRed:51.0f / 255.0f green:51.0f / 255.0f blue:51.0f / 255.0f alpha:1.0f] CGColor],
nil];
[btn.layer insertSublayer:btnGradient atIndex:0];
}
But all i get is a button with a drop shadow. I've linked the quartz core library, ive imported it, i've linked the buttons, ive tried using different types of buttons; i'm Stumped.
Any Ideas whats going wrong?
Thanks in advance.
I faced same problem. It seems you are building for iOS6 as I do. I found that Autolayout for storyboards, introduced in iOS6, is causing such problems. Just disable it if you don't use this feature:
Open storyboard in Xcode
Open properties of storyboard (right pane with properties)
Uncheck "Use Autolayout" in "Interface Builder Document" section.
Did you try setting the locations and the start/end points for your gradient ?
btnGradient.locations = #[#(0.), #(1.)];
btnGradient.startPoint = (CGPoint){0., 0.};
btnGradient.endPoint = (CGPoint){0., 1.};
I think you could try to remove any previously existing CAGradientLayer in your button:
for(CALayer* layer in btn.layer.sublayers)
if ([layer isKindOfClass:[CAGradientLayer class]])
[layer removeFromSuperlayer];
and then adding your own.

Create a shadow in iphone

i have a layer ,i need the top half red shadow
my code is
Shadow.colors = [NSArray arrayWithObjects:
(id)[[[UIColor redColor] colorWithAlphaComponent:0.6] CGColor],
(id)[[UIColor clearColor] CGColor],
nil];
Shadow.startPoint = CGPointMake(0,0.5);
Shadow.endPoint = CGPointMake(1,0.5);
this gives me a left half shadow.
What i have to do to have a top half red shadow
Shadow.startPoint = CGPointMake(0.5,0);
Shadow.endPoint = CGPointMake(0.5,1);
This solved my problem.Thanks borrrden

UITableViewCell doesn't pickup UITableViewCellSelectionStyleBlue when adding CAGradientLayer sublayer

I have a UITableViewCell that I've added a gradient to by using CAGradientLayer. This works fine, but the table cell doesn't turn blue when selected, even after setting it's selectionStyle to UITableViewCellSelectionStyleBlue. If I don't add the gradient layer, it works fine.
Is there a way to make these items work together?
Here's my code inside of cellForRowAtIndexPath:
//cell gradient
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = CGRectMake(10, 0, 300, 50);
gradient.colors = [NSArray arrayWithObjects:
(id)[[UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1] CGColor],
(id)[[UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1] CGColor],
(id)[[UIColor colorWithRed:245/255.0 green:245/255.0 blue:245/255.0 alpha:1] CGColor],
(id)[[UIColor colorWithRed:247/255.0 green:247/255.0 blue:247/255.0 alpha:1] CGColor],
nil];
gradient.locations = [NSArray arrayWithObjects:
(id)[NSNumber numberWithFloat:0.00],
(id)[NSNumber numberWithFloat:0.50],
(id)[NSNumber numberWithFloat:0.51],
(id)[NSNumber numberWithFloat:1.0],
nil];
[cell.layer insertSublayer:gradient atIndex:0];
//bring back rounded corners by creating a masklayer
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:gradient.bounds byRoundingCorners:UIRectCornerBottomRight|UIRectCornerBottomLeft cornerRadii:CGSizeMake(8, 8)];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = gradient.bounds;
maskLayer.path = maskPath.CGPath;
gradient.mask = maskLayer;
//add the cell shadow
cell.layer.shadowColor = [[UIColor blackColor] CGColor];
cell.layer.shadowRadius = 3;
cell.layer.shadowOpacity = 0.5;
cell.layer.shadowOffset = CGSizeMake(0, 0);
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
It looks like you might be putting the gradient over the view that changes when it is selected- the UITableViewCellSelectionStyleBlue view may be appearing, but you just cannot see it (a way to test it out is only have the gradient cover part of your cell- if the other part changes color when it is selected, then this is the issue).
If this is the issue, then you could do your own custom drawing for the cell when it is selected by subclassing UITableViewCell, or you could have the gradient disappear whenever the cell is selected (and reappear when the cell is deselected).

CALayer w/ Animation as UIViews layer

I have a UIView & I want that view's layer to be a continuously looping animation but I'm having some trouble getting started. I have the following in my view subclass:
+ (Class)layerClass {
return [CALayer class];
}
Then in my viewController I have:
CAGradientLayer *gradient = [CAGradientLayer layer];
[gradient setColors:[NSArray arrayWithObjects:[UIColor redColor],[UIColor blueColor],nil]];
[[[self view] layer] addSublayer:gradient];
This crashes my app. What exactly am I doing wrong? The app crashes w/ EXC_BAD_ACCESS.
Actually the crash you are having isn't related to not setting locations. The issue has to do with the fact that you're passing the wrong types in your setColors array. A CGColorRef is the types that is expected. Your code should look like this:
CAGradientLayer *gradient = [CAGradientLayer layer];
[gradient setColors:[NSArray arrayWithObjects:(id)[[UIColor redColor] CGColor],
(id)[[UIColor blueColor] CGColor],nil]];
[[[self view] layer] addSublayer:gradient];
The locations parameter of a CAGradientLayer is optional.
Best regards.
You forget to specify the locations for colors. By default, the location is nil.
CAGradientLayer *gradient = [CAGradientLayer layer];
[gradient setColors:[NSArray arrayWithObjects:
[[UIColor redColor] CGColor],
[[UIColor blueColor] CGColor],
nil]];
[gradient setLocations:
[NSNumber numberWithFloat:0.0], // for redColor
[NSNumber numberWithFloat:1.0], // for blueColor
nil]];
[[[self view] layer] addSublayer:gradient];

CABasicAnimation in a CAGradientLayer not working - what am I doing wrong?

I have a custom UITableView cell which has a button and a label. I fire a method when someone taps on the button, and then color that row. It's all working fine.
What I want to actually do is
user taps button, the row is colored in a gradient (it works now)
The gradient fades away
My code is below (BackView is the view in my custom cell)
CAGradientLayer *layer = [CAGradientLayer layer];
layer.frame = BackView.bounds;
UIColor *cOne = [UIColor paleYellowColor];
UIColor *cTwo = [UIColor whiteColor];
NSArray *colors = [NSArray arrayWithObjects:(id)cOne.CGColor,
cTwo.CGColor, nil];
layer.colors = colors;
NSNumber *stopOne = [NSNumber numberWithFloat:0.00];
NSNumber *stopTwo = [NSNumber numberWithFloat:0.8];
NSArray *locations = [NSArray arrayWithObjects:stopOne, stopTwo, nil];
layer.locations = locations;
CABasicAnimation *animateLayer = [CABasicAnimation animationWithKeyPath:#"colors"];
animateLayer.fromValue = [UIColor paleYellowColor];
animateLayer.toValue = [UIColor whiteColor];
animateLayer.duration = 3.0;
animateLayer.removedOnCompletion = YES;
animateLayer.fillMode = kCAFillModeBoth;
animateLayer.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[layer addAnimation:animateLayer forKey:#"animation"];
[BackView.layer insertSublayer:layer atIndex:0];
With this code, when I touch the button on the row, the background gets a gradient, but it never fades away, there's no animation - nothing. What am I doing wrong? I tried a few permutations and saw some examples, but none that helped me get this working.
Thanks!
When you animate a property with an explicit animation, you have provide the type that property is expecting. The colors property is animatable, however, you are giving it a UIColor for the from and to values. It's expecting an NSArray. Also, you need CGColorRefs for the colors themselves. I haven't tried it, but I'm thinking you need to change your to and from lines to:
animateLayer.fromValue = [NSArray arrayWithObjects:
(id)[[UIColor paleYellowColor] CGColor],
(id)[[UIColor whiteColor] CGColor], nil];
animateLayer.toValue = [NSArray arrayWithObjects:
(id)[[UIColor whiteColor] CGColor],
(id)[[UIColor whiteColor] CGColor], nil];
In theory, this should fade from your yellow/white gradient to white/white which should give the effect of fading out.
Best regards.