【问题标题】:How to tint the background images of an UIButton programmatically and dynamically?如何以编程方式和动态地为 UIButton 的背景图像着色?
【发布时间】:2013-01-08 19:36:07
【问题描述】:

我正在开发一个应用程序 - 或者更确切地说是一些可重复使用的“框架”,一旦它工作,我很乐意分享。在这个应用程序中,用户应该能够从颜色主题列表中进行选择。因此,应用程序必须能够以某种相当动态的方式为其 UI 元素着色。

对于按钮,所有着色都不起作用。必须在此处提供适当着色的背景图像。但是为每个人准备一组背景图像只是第二好的。它不够动态和灵活。

最终,解决方案可能归结为为选定的正常状态提供一个单色(灰色)渐变图像,并使用 CoreGraphics 或 OpenGL 以编程方式为该图像着色。但坦率地说,我不知道从哪里开始。渐变应该是什么样子,然后我将如何以任何给定的颜色以编程方式对其进行着色?

几乎适用于 UISegmentedControls,只是稍微复杂一些。 :) 任何涵盖 UISegementedControls 的通用解决方案都受到高度赞赏。

【问题讨论】:

  • 看看GMButton。它允许您为所有按钮状态设置颜色,并提供斜角和光泽渐变。
  • 你在那里做的看起来不错。看来我只需要将此应用于 ARC,然后它就应该做我想做的一切。谢谢。

标签: ios objective-c cocoa uibutton uisegmentedcontrol


【解决方案1】:

我正在向您推荐一个 SO 问题,该问题似乎是您正在寻找的并且有答案。

How to tint a transparent PNG image in iPhone?

【讨论】:

  • 这不是我希望的答案,但这似乎是可行的。谢谢。我会试一试,可能在周末。
【解决方案2】:

在 iOS7 中,您可以将方法 imagedWithRenderingMode: 与方法 setTintColor: 结合使用

但是,请务必使用UIImageRenderingModeAlwaysTemplate,因为它会将UIImage 上的所有非透明颜色替换为淡色。默认为UIImageRenderingModeAutomatic

UIImageRenderingModeAlwaysTemplate

Always draw the image as a template image, ignoring its color information.

目标-C:

UIImage * image = [myButton.currentImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[myButton setImage:image forState:UIControlStateNormal];

斯威夫特:

let image = myButton.currentImage?.withRenderingMode(.alwaysTemplate)
myButton.setImage(image, for: .normal)

【讨论】:

  • 小心 - UIImage __weak 在 ios 9 发布模式构建中的按钮上没有显示图像
  • 为 SetImage 工作而不是为 SetBackgroudIamge 工作
【解决方案3】:

我从“horsejockey”中修改了一些东西:

+(UIImage *)getTintedImage:(UIImage*)image withColor:(UIColor *)tintColor
{
    UIGraphicsBeginImageContextWithOptions(image.size, NO, [[UIScreen mainScreen] scale]);
    CGContextRef context = UIGraphicsGetCurrentContext();


    CGContextTranslateCTM(context, 0, image.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);

    // draw alpha-mask
    CGContextSetBlendMode(context, kCGBlendModeNormal);
    CGContextDrawImage(context, rect, image.CGImage);

    // draw tint color, preserving alpha values of original image
    CGContextSetBlendMode(context, kCGBlendModeSourceIn);
    [tintColor setFill];
    CGContextFillRect(context, rect);

    UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return coloredImage;
}

【讨论】:

    【解决方案4】:

    我使用 horsejockey 的代码创建了一个 UIButton 类别: https://github.com/filipstefansson/UITintedButton

    以下是新方法:

    -(void)setImageTintColor:(UIColor *)color;
    -(void)setBackgroundTintColor:(UIColor *)color forState:(UIControlState)state;
    +(void)tintButtonImages:(NSArray *)buttons withColor:(UIColor *)color;
    +(void)tintButtonBackgrounds:(NSArray *)buttons withColor:(UIColor *)color forState:(UIControlState)state;
    

    【讨论】:

      【解决方案5】:

      我在另一个我找不到的帖子之后创建了一个 UIImage 类别,该帖子采用图像并将其着色如下:

      - (UIImage *)tintedImageWithColor:(UIColor *)tintColor {
          UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
          CGContextRef context = UIGraphicsGetCurrentContext();
      
      
          CGContextTranslateCTM(context, 0, self.size.height);
          CGContextScaleCTM(context, 1.0, -1.0);
      
          CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
      
          // draw alpha-mask
          CGContextSetBlendMode(context, kCGBlendModeNormal);
          CGContextDrawImage(context, rect, self.CGImage);
      
          // draw tint color, preserving alpha values of original image
          CGContextSetBlendMode(context, kCGBlendModeSourceIn);
          [tintColor setFill];
          CGContextFillRect(context, rect);
      
          UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext();
          UIGraphicsEndImageContext();
          return coloredImage;
      }
      

      这将获取图像并使用给定颜色的 alpha 值填充所有区域。

      【讨论】:

      • 像个骗子一样工作!
      【解决方案6】:

      这是您问题的部分答案。这是我编写的一个辅助方法,可以为灰度图像着色:

      // baseImage is the grey scale image. color is the desired tint color
      + (UIImage *)tintImage:(UIImage *)baseImage withColor:(UIColor *)color {
          UIGraphicsBeginImageContextWithOptions(baseImage.size, NO, baseImage.scale);
      
          CGContextRef ctx = UIGraphicsGetCurrentContext();
          CGRect area = CGRectMake(0, 0, baseImage.size.width, baseImage.size.height);
      
          CGContextScaleCTM(ctx, 1, -1);
          CGContextTranslateCTM(ctx, 0, -area.size.height);
      
          CGContextSaveGState(ctx);
          CGContextClipToMask(ctx, area, baseImage.CGImage);
      
          [color set];
          CGContextFillRect(ctx, area);
          CGContextRestoreGState(ctx);
      
          CGContextSetBlendMode(ctx, kCGBlendModeOverlay);
      
          CGContextDrawImage(ctx, area, baseImage.CGImage);
      
          UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
      
          UIGraphicsEndImageContext();
      
          // If the original image was stretchable, make the new image stretchable
          if (baseImage.leftCapWidth || baseImage.topCapHeight) {
              newImage = [newImage stretchableImageWithLeftCapWidth:baseImage.leftCapWidth topCapHeight:baseImage.topCapHeight];
          }
      
          return newImage;
      }
      

      【讨论】:

      • 谢谢。我会在周末或下周初试一试。它看起来有点类似于@OnlyYou 所链接的核心。虽然我对 CG Graphics jet 不太熟悉,但它是非常自我解释的。就一个问题。这个 CGContextScalTCM 和 ContextTranslateTCM 是用于坐标变换的,因为 UIKit 和 CGGraphics 在 y 轴上有不同的原点和不同的方向?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-18
      • 2016-12-18
      • 1970-01-01
      • 1970-01-01
      • 2017-02-18
      相关资源
      最近更新 更多