iOS --- 为UIButton添加setBackground

作者: icetime17 | 来源:发表于2016-07-07 21:51 被阅读1032次

    有这样的一类简单需求: UIButton的背景色要与其state相关, 如未点击时显示蓝色, 点击时显示绿色.
    但是, UIButton自身并未提供setBackgroundColor:forState:方法, 因此我们不得不单独在touchDown等方法中去更新其backgroundColor属性.
    这里介绍如何为UIButton提供该扩展方法, Objective-C和Swift的版本都有.
    其中用到了runtime的关联对象, 不熟悉的同学可以先参考iOS --- 理解Runtime机制及其使用场景.

    Objective-C

    Objective-C中通过Category提供该扩展方法.
    头文件:

    #import <UIKit/UIKit.h>
    
    @interface UIButton (CS_BackgroundColor)
    
    - (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state;
    
    @end
    

    实现文件:

    #import "UIButton+CS_BackgroundColor.h"
    #import <objc/runtime.h>
    
    @interface UIButton (CS_BackgroundColor)
    
    @property (nonatomic, strong) NSMutableDictionary *cs_dictBackgroundColor;
    
    @end
    
    
    @implementation UIButton (CS_BackgroundColor)
    
    static const NSString *key_cs_backgroundColor             = @"key_cs_backgroundColor";
    
    static NSString *cs_stringForUIControlStateNormal         = @"cs_stringForUIControlStateNormal";
    static NSString *cs_stringForUIControlStateHighlighted    = @"cs_stringForUIControlStateHighlighted";
    static NSString *cs_stringForUIControlStateDisabled       = @"cs_stringForUIControlStateDisabled";
    static NSString *cs_stringForUIControlStateSelected       = @"cs_stringForUIControlStateSelected";
    
    #pragma mark - cs_dictBackgroundColor
    
    - (NSMutableDictionary *)cs_dictBackgroundColor {
        return objc_getAssociatedObject(self, &key_cs_backgroundColor);
    }
    
    - (void)setCs_dictBackgroundColor:(NSMutableDictionary *)cs_dictBackgroundColor {
        objc_setAssociatedObject(self, &key_cs_backgroundColor, cs_dictBackgroundColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state {
        if (!self.cs_dictBackgroundColor) {
            self.cs_dictBackgroundColor = [[NSMutableDictionary alloc] init];
        }
    
        [self.cs_dictBackgroundColor setObject:backgroundColor forKey:[self cs_stringForUIControlState:state]];
    }
    
    - (NSString *)cs_stringForUIControlState:(UIControlState)state {
        NSString *cs_string;
        switch (state) {
            case UIControlStateNormal:
                cs_string = cs_stringForUIControlStateNormal;
                break;
            case UIControlStateHighlighted:
                cs_string = cs_stringForUIControlStateHighlighted;
                break;
            case UIControlStateDisabled:
                cs_string = cs_stringForUIControlStateDisabled;
                break;
            case UIControlStateSelected:
                cs_string = cs_stringForUIControlStateSelected;
                break;
            default:
                cs_string = cs_stringForUIControlStateNormal;
                break;
        }
        return cs_string;
    }
    
    #pragma mark - highlighted
    
    - (void)setHighlighted:(BOOL)highlighted {
        if (highlighted) {
            self.backgroundColor = (UIColor *)[self.cs_dictBackgroundColor objectForKey:cs_stringForUIControlStateHighlighted];
        } else {
            self.backgroundColor = (UIColor *)[self.cs_dictBackgroundColor objectForKey:cs_stringForUIControlStateNormal];
        }
    }
    
    @end
    

    使用方法:

    btn1.backgroundColor = [UIColor greenColor]; // 注意, 这里的默认背景色必须设置, 仅仅通过下一行暂时不能设置初始的背景色
    [btn1 setBackgroundColor:[UIColor greenColor] forState:UIControlStateNormal];
    [btn1 setBackgroundColor:[UIColor blueColor] forState:UIControlStateHighlighted];
    

    Swift

    Swift的语法终归是要不断练习. 通过extension来提供该方法.

    public extension UIButton {
    
        private struct cs_backgroundColor {
            static var keyBackgroundColors              = "cs_keyBackgroundColors"
    
            static var keyBackgroundColor_Normal        = "cs_keyBackgroundColor_Normal"
            static var keyBackgroundColor_Highlighted   = "cs_keyBackgroundColor_Highlighted"
        }
    
        var cs_dictBackgroundColors: Dictionary<String, UIColor>! {
            get {
                if let dictBackgroundColors = objc_getAssociatedObject(self, &cs_backgroundColor.keyBackgroundColors) {
                    return dictBackgroundColors as! Dictionary<String, UIColor>
                }
    
                return nil
            }
    
            set {
                objc_setAssociatedObject(self, &cs_backgroundColor.keyBackgroundColors, newValue as Dictionary<String, UIColor>, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    
        func cs_setBackgroundColor(color: UIColor, forState: UIControlState) {
            if self.cs_dictBackgroundColors == nil {
                self.cs_dictBackgroundColors = Dictionary<String, UIColor>()
            }
    
            if let key = self.cs_stringForUIControlState(forState) {
                self.cs_dictBackgroundColors[key] = color
            }
        }
    
        private func cs_stringForUIControlState(state: UIControlState) -> String! {
            var cs_string = ""
    
            switch state {
            case UIControlState.Normal:
                cs_string = cs_backgroundColor.keyBackgroundColor_Normal
            case UIControlState.Highlighted:
                cs_string = cs_backgroundColor.keyBackgroundColor_Highlighted
            default:
                cs_string = cs_backgroundColor.keyBackgroundColor_Normal
            }
    
            return cs_string
        }
    
        override var highlighted: Bool {
            get {
                return super.highlighted
            }
    
            set {
                if newValue {
                    if let key = self.cs_stringForUIControlState(.Highlighted) {
                        self.backgroundColor = self.cs_dictBackgroundColors[key]!
                    }
                } else {
                    if let key = self.cs_stringForUIControlState(.Normal) {
                        self.backgroundColor = self.cs_dictBackgroundColors[key]!
                    }
                }
            }
        }
    
    }
    

    使用方法:

    btn.backgroundColor = UIColor.greenColor() // 这里的设置同样是必需的.
    btn.cs_setBackgroundColor(UIColor.greenColor(), forState: .Normal)
    btn.cs_setBackgroundColor(UIColor.blueColor(), forState: .Highlighted)
    

    Demo

    Objective-C版本的Demo请参考DemoRuntime.
    Swift版本的Demo请参考CSSwiftExtension.

    相关文章

      网友评论

      • 00f0453d6767:其实只要一张纯色的图片做背景就好了
        self.setBackgroundImage(UIImage.init(color: bgDisabledColor), for: .disabled)
        00f0453d6767:纯色图片方法
        public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
        let rect = CGRect(origin: .zero, size: size)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
        color.setFill()
        UIRectFill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        guard let cgImage = image?.cgImage else { return nil }
        self.init(cgImage: cgImage)
        }
      • icetime17:实践证明,使用runtime来设置UIButton的backgroundColor的方式,会出现setImage出错的情况。所以,正确设置backgroundColor的姿势请参考:https://github.com/icetime17/CSSwiftExtension

        btnTest.cs.setBackgroundColor(UIColor.blue, for: .normal) // set backgroundColor
        btnTest.cs.setBackgroundColor(UIColor.red, for: .highlighted)

      本文标题:iOS --- 为UIButton添加setBackground

      本文链接:https://www.haomeiwen.com/subject/gwvljttx.html