更改UIButton渐变颜色

时间:2014-10-21 14:33:30

标签: ios objective-c uibutton

我使用以下方法为我的IOS UIButton添加一些渐变效果。我在viewController' s viewDidLoad中调用它,效果很好,到目前为止一直很好。

现在,我想根据一些用户交互更改按钮的颜色。我所做的只是用不同颜色(fromColor, toColor)作为输入调用此方法。问题,我的按钮的外观不会改变。我试着打电话给setNeedsDisplay,但没有帮助。

你愿意帮助我吗?我想念的是什么?层应该存在一些问题,应该休息或类似的东西,但我找不到它的正确方法。

更新:使用setSubLayers而不是insertSubLayer颜色更改,但按钮标题消失。

+(void)setCustomButtonStyle:(UIButton *)button cornerRadius:(float) cornerRadius fromColor:(UIColor *)fromColor toColor:(UIColor *)toColor normalTitleColor:(UIColor *)normalTitleColor highlightedTitleColor:(UIColor *)highlightedTitleColor borderWidth:(float) borderWidth borderColor:(UIColor*)borderColor
{
    [button setTitleColor:normalTitleColor forState:UIControlStateNormal];
    [button setTitleColor:highlightedTitleColor forState:UIControlStateHighlighted];

    CAGradientLayer *btnGradient = [CAGradientLayer layer];
    btnGradient.frame = button.bounds;
    btnGradient.colors = [NSArray arrayWithObjects:
                          (id)[fromColor CGColor],
                          (id)[toColor CGColor],
                          nil];
    btnGradient.borderWidth = borderWidth;
    btnGradient.borderColor = [borderColor CGColor];
    [button.layer insertSublayer:btnGradient atIndex:0];

    CALayer *btnLayer = [button layer];
    [btnLayer setMasksToBounds:YES];
    [btnLayer setCornerRadius:cornerRadius];
}

2 个答案:

答案 0 :(得分:1)

您遇到的问题是 1。每次更改颜色时都会创建一个新图层, 2。然后放置新图层在其他一切之下,所以你无论如何都看不到它。 (想想把扑克牌放在牌组的底部)。

您需要做的是保持渐变层,然后更新,而不是创建一个新的。

您可能最好在UIButton类别中执行此操作。

像...... UIButton+GradientBackground或其他东西。

在.h文件中给它一个函数......

// Use CGFloat not float. Also user NSInteger not int.
// Always.
// Also, I have used modern Obj-C syntax. Use this too.

- (void)setCornerRadius:(CGFloat)cornerRadius
              fromColor:(UIColor *)fromColor
                toColor:(UIColor *)toColor
       normalTitleColor:(UIColor *)normalTitleColor
  highlightedTitleColor:(UIColor *)highlightedTitleColor
            borderWidth:(CGFloat)borderWidth
            borderColor:(UIColor *)borderColor;

然后在.m文件中你还需要给它一个属性......

@property (nonatomic, strong) CAGradientLayer *gradientLayer;

现在在函数中......

- (void)setCornerRadius:(CGFloat)cornerRadius
              fromColor:(UIColor *)fromColor
                toColor:(UIColor *)toColor
       normalTitleColor:(UIColor *)normalTitleColor
  highlightedTitleColor:(UIColor *)highlightedTitleColor
            borderWidth:(CGFloat)borderWidth
            borderColor:(UIColor *)borderColor
{
    [self setTitleColor:normalTitleColor forState:UIControlStateNormal];
    [self setTitleColor:highlightedTitleColor forState:UIControlStateHighlighted];

    if (!self.grandientLayer) {
        // if it doesn't exist then create it and add it (only once)
        self.gradientLayer = [CAGradientLayer layer];
        [self.layer insertSublayer:self.gradientLayer atIndex:0];
    }

    self.gradientLayer.frame = self.bounds;
    self.gradientLayer.colors = @[(id)fromColor.CGColor, (id)toColor.CGColor]; // use modern syntax
    self.gradientLayer.borderWidth = borderWidth;
    self.gradientLayer.borderColor = borderColor.CGColor;

    [self.layer setMasksToBounds:YES];
    [self.layer setCornerRadius:cornerRadius];
}

请注意,我已从函数名中删除了该按钮,因为此函数基本上是UIButton函数的一部分,因此self是您要更改的按钮。

你会这样称呼它......

[someButton setCornerRadius:5 fromColor:[UIColor redColor] toColor... and so on];

通过这样做,您只需创建一次渐变图层并保持它,以便下次可以更新它。

答案 1 :(得分:1)

首次添加渐变图层,下次替换添加的渐变图层

添加Category,因为@Fogmeister认为这只能用于类别

@interface UIButton (gradient)
   +(void)setCustomButtonStyle:(UIButton *)button cornerRadius:(float) cornerRadius fromColor:(UIColor *)fromColor toColor:(UIColor *)toColor normalTitleColor:(UIColor *)normalTitleColor highlightedTitleColor:(UIColor *)highlightedTitleColor borderWidth:(float) borderWidth borderColor:(UIColor*)borderColor;
@end

@implementation UIButton (gradient)

 +(void)setCustomButtonStyle:(UIButton *)button cornerRadius:(float) cornerRadius fromColor:(UIColor *)fromColor toColor:(UIColor *)toColor normalTitleColor:(UIColor *)normalTitleColor highlightedTitleColor:(UIColor *)highlightedTitleColor borderWidth:(float) borderWidth borderColor:(UIColor*)borderColor
 {
   //Set Title color as you want
   [button setTitleColor:normalTitleColor forState:UIControlStateNormal];
   [button setTitleColor:highlightedTitleColor forState:UIControlStateHighlighted];

   //check gradientlayer exist
   id layer = nil;
   if (button.layer.sublayers.count > 0) {
     layer = [button.layer.sublayers objectAtIndex:0];
   }
   //Find added gradient layer
   CAGradientLayer *addedGradLayer = nil;
   if (layer) {
     if ([layer isKindOfClass:[CAGradientLayer class]]) {
        addedGradLayer = (CAGradientLayer *)[button.layer.sublayers objectAtIndex:0];
     }
   }

   //check gradient layer exists
   if (!addedGradLayer) //first time
   {
      CAGradientLayer *gradientLayer = [CAGradientLayer layer];
      gradientLayer.frame = button.layer.bounds;
      gradientLayer.colors = [NSArray arrayWithObjects:
                            (id)fromColor.CGColor,
                            (id)toColor.CGColor,
                            nil];

      gradientLayer.locations = [NSArray arrayWithObjects:
                               [NSNumber numberWithFloat:0.0f],
                               [NSNumber numberWithFloat:1.0f],
                               nil];

      gradientLayer.cornerRadius = button.layer.cornerRadius;
      [button.layer insertSublayer:gradientLayer atIndex:0];
      button.clipsToBounds = YES;
   }
   else //next time
   {

      CAGradientLayer *newGradientLayer = [CAGradientLayer layer];
      newGradientLayer.frame = button.layer.bounds;
      newGradientLayer.colors = [NSArray arrayWithObjects:
                               (id)fromColor.CGColor,
                               (id)toColor.CGColor,
                               nil];

      newGradientLayer.locations = [NSArray arrayWithObjects:
                                  [NSNumber numberWithFloat:0.0f],
                                  [NSNumber numberWithFloat:1.0f],
                                  nil];

      newGradientLayer.cornerRadius = button.layer.cornerRadius;
      [button.layer replaceSublayer:addedGradLayer with:newGradientLayer];
    }
 }

@end