美文网首页
进阶:UIButton 样式扩展

进阶:UIButton 样式扩展

作者: SoaringHeart | 来源:发表于2021-01-23 00:00 被阅读0次

UIButton 添加边框颜色圆角 state 支持;

不继承无侵入;

边框效果图.gif

Swift

🌰🌰:
        let sender = UIButton(type:.custom);
        sender.setBorderColor(.lightGray, for: .normal)
        sender.setBorderColor(.systemBlue, for: .selected)
        sender.setCornerRadius(4, for: .normal)
        sender.setCornerRadius(14, for: .selected)
        sender.addTarget(self, action: #selector(handActionBtn(_:)), for: .touchUpInside)

    @objc func handActionBtn(_ sender: NNButton) {
        sender.isSelected = !sender.isSelected
        DDLog(sender.frame, sender.titleLabel?.frame)
        
    }
//
//  UIButton+Layer.swift
//  SwiftTemplet
//
//  Created by Bin Shang on 2021/1/23.
//  Copyright © 2021 BN. All rights reserved.
//

import UIKit

class NNButtonLayerTarget: NSObject {
    
    public weak var button: UIButton?
    
    ///addObserver(self, forKeyPath: "selected", options: .new, context: nil)
    var observerBlock:((String?, UIButton?, [NSKeyValueChangeKey: Any]?)->Void)?
    
    var borderColorDic = [UIControl.State.RawValue: UIColor]()
    var borderWidthDic = [UIControl.State.RawValue: CGFloat]()
    var cornerRadiusDic = [UIControl.State.RawValue: CGFloat]()
    
    // MARK: -lifecycle
    deinit {
        removeObserver(self, forKeyPath: "selected")
        removeObserver(self, forKeyPath: "highlighted")
    }
    
    // MARK: -observe
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if let sender = object as? UIButton {
            if keyPath == "selected" || keyPath == "highlighted" {
                changeLayerBorderColor(sender)
                changeLayerBorderWidth(sender)
                changeLayerCornerRadius(sender)
                observerBlock?(keyPath, sender, change)
            }
        } else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }

    // MARK: -public
    func setBorderColor(_ color: UIColor?, for state: UIControl.State){
        guard let color = color else { return }
        borderColorDic[state.rawValue] = color
        changeLayerBorderColor(button)
    }
    func borderColor(for state: UIControl.State) -> UIColor?{
        return borderColorDic[state.rawValue]
    }
    
    func setBorderWidth(_ value: CGFloat, for state: UIControl.State){
        borderWidthDic[state.rawValue] = value
        changeLayerBorderWidth(button)
    }
    func borderWidth(for state: UIControl.State) -> CGFloat{
        return borderWidthDic[state.rawValue] ?? 0
    }
    
    func setCornerRadius(_ value: CGFloat, for state: UIControl.State){
        cornerRadiusDic[state.rawValue] = value
        changeLayerCornerRadius(button)
    }
    func cornerRadius(for state: UIControl.State) -> CGFloat{
        return cornerRadiusDic[state.rawValue] ?? 0
    }

    // MARK: -private
    private func changeLayerBorderColor(_ sender: UIButton?) {
        guard let sender = sender,
              let normalColor = borderColorDic[UIControl.State.normal.rawValue] else { return }
        let color = borderColorDic[sender.state.rawValue] ?? normalColor
        sender.layer.borderColor = color.cgColor

        if sender.layer.borderWidth == 0 {
            sender.layer.borderWidth = 1
        }
    }
    
    private func changeLayerBorderWidth(_ sender: UIButton?) {
        guard let sender = sender,
              let normalValue = borderWidthDic[UIControl.State.normal.rawValue] else { return }
        let value = borderWidthDic[sender.state.rawValue] ?? normalValue
        sender.layer.borderWidth = value
        
        if sender.layer.borderWidth == 0 {
            sender.layer.borderWidth = 1
        }
    }
    
    private func changeLayerCornerRadius(_ sender: UIButton?) {
        guard let sender = sender,
              let normalValue = cornerRadiusDic[UIControl.State.normal.rawValue] else { return }
        let value = cornerRadiusDic[sender.state.rawValue] ?? normalValue
        sender.layer.cornerRadius = value

        if sender.layer.borderWidth == 0 {
            sender.layer.borderWidth = 1
        }
    }

}


public extension UIButton{
    private struct AssociateKeys {
        static var layerTarget   = "UIButton" + "layerTarget"
    }
    /// 关联UITableView视图对象
    private var layerTarget: NNButtonLayerTarget {
        get {
            if let obj = objc_getAssociatedObject(self, &AssociateKeys.layerTarget) as? NNButtonLayerTarget {
                return obj
            }

            let target = NNButtonLayerTarget()
            target.button = self
            
            target.button?.addObserver(target, forKeyPath: "selected", options: .new, context: nil)
            target.button?.addObserver(target, forKeyPath: "highlighted", options: .new, context: nil)

            objc_setAssociatedObject(self, &AssociateKeys.layerTarget, target, .OBJC_ASSOCIATION_RETAIN_NONATOMIC);
            return target
        }
    }
    
    func setBorderColor(_ color: UIColor?, for state: UIControl.State){
        layerTarget.setBorderColor(color, for: state)
    }

    func borderColor(for state: UIControl.State) -> UIColor?{
        return layerTarget.borderColor(for: state)
    }
    
    func setBorderWidth(_ value: CGFloat, for state: UIControl.State){
        layerTarget.setBorderWidth(value, for: state)
    }

    func borderWidth(for state: UIControl.State) -> CGFloat?{
        return layerTarget.borderWidth(for: state)
    }
    
    func setCornerRadius(_ value: CGFloat, for state: UIControl.State){
        layerTarget.setCornerRadius(value, for: state)
    }

    func cornerRadius(for state: UIControl.State) -> CGFloat?{
        return layerTarget.cornerRadius(for: state)
    }
}

OC

🌰🌰:
//@property (nonatomic, strong) UIButton *button1;

- (UIButton *)button1{
    if (!_button1) {
        _button1 = ({
            UIButton *sender = [UIButton buttonWithType:UIButtonTypeCustom];
            [sender setTitle:@"Normal" forState:UIControlStateNormal];
            [sender setTitle:@"Selected" forState:UIControlStateSelected];

            [sender setTitleColor:UIColor.systemGrayColor forState:UIControlStateNormal];
            [sender setTitleColor:UIColor.systemBlueColor forState:UIControlStateSelected];
            sender.titleLabel.font = [UIFont systemFontOfSize:15];
            
//            sender.titleLabel.adjustsFontSizeToFitWidth = YES;
            sender.imageView.contentMode = UIViewContentModeScaleAspectFit;
            sender;
        });
        
        [_button1 setBorderColor:UIColor.lightGrayColor forState:UIControlStateNormal];
        [_button1 setBorderColor:UIColor.systemBlueColor forState:UIControlStateSelected];
        [_button1 setCornerRadius:4 forState:UIControlStateNormal];
        [_button1 setCornerRadius:14 forState:UIControlStateSelected];

        [_button1 addTarget:self action:@selector(handleAction:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _button1;
}

#pragma mark -funtions
- (void)handleAction:(UIButton *)sender{
    sender.selected = !sender.selected;
//    DDLog(@"isSelected_%@", @(sender.isSelected));
}

UIButton+Border.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIButton (BorderColor)

- (void)setBorderColor:(nullable UIColor *)color forState:(UIControlState)state;
- (nullable UIColor *)borderColorForState:(UIControlState)state;

- (void)setBorderWidth:(CGFloat)value forState:(UIControlState)state;
- (CGFloat)borderWidthForState:(UIControlState)state;
    
- (void)setCornerRadius:(CGFloat)value forState:(UIControlState)state;
- (CGFloat)cornerRadiusForState:(UIControlState)state;

@end

NS_ASSUME_NONNULL_END

UIButton+Border.m

#import "UIButton+Border.h"
#import <objc/runtime.h>

@interface NNBorderTarget : NSObject

@property (nonatomic, weak) UIButton *button;

@property (nonatomic, strong) NSMutableDictionary<NSNumber *, UIColor *> *borderColorDic;
@property (nonatomic, strong) NSMutableDictionary<NSNumber *, NSNumber *> *borderWidthDic;
@property (nonatomic, strong) NSMutableDictionary<NSNumber *, NSNumber *> *cornerRadiusDic;

- (void)setBorderColor:(nullable UIColor *)color forState:(UIControlState)state;
- (nullable UIColor *)borderColorForState:(UIControlState)state;

- (void)setBorderWidth:(CGFloat)value forState:(UIControlState)state;
- (CGFloat)borderWidthForState:(UIControlState)state;
    
- (void)setCornerRadius:(CGFloat)value forState:(UIControlState)state;
- (CGFloat)cornerRadiusForState:(UIControlState)state;

@end


@implementation NNBorderTarget

- (void)dealloc{
    [self.button removeObserver:self forKeyPath:@"selected"];
    [self.button removeObserver:self forKeyPath:@"highlighted"];
}

#pragma mark -observe
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if ([object isKindOfClass:[UIButton class]]) {
        UIButton *sender = (UIButton *)object;
        if ([keyPath isEqualToString:@"selected"] || [keyPath isEqualToString:@"highlighted"]) {
            [self changeLayerBorderColor: sender];
            [self changeLayerBorderWidth: sender];
            [self changeLayerCornerRadius: sender];
        }
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}


#pragma mark -set,get
- (NSMutableDictionary<NSNumber *,UIColor *> *)borderColorDic{
    if (!_borderColorDic) {
        _borderColorDic = @{
            
        }.mutableCopy;
    }
    return _borderColorDic;
}

- (NSMutableDictionary<NSNumber *, NSNumber *> *)borderWidthDic{
    if (!_borderWidthDic) {
        _borderWidthDic = @{
            
        }.mutableCopy;
    }
    return _borderWidthDic;
}

- (NSMutableDictionary<NSNumber *, NSNumber *> *)cornerRadiusDic{
    if (!_cornerRadiusDic) {
        _cornerRadiusDic = @{
            
        }.mutableCopy;
    }
    return _cornerRadiusDic;
}

#pragma mark -public

- (void)setBorderColor:(nullable UIColor *)color forState:(UIControlState)state{
    if (!color) {
        return;
    }
    self.borderColorDic[@(state)] = color;
    [self changeLayerBorderColor: self.button];
}

- (nullable UIColor *)borderColorForState:(UIControlState)state{
    return self.borderColorDic[@(state)];
}

- (void)setBorderWidth:(CGFloat)value forState:(UIControlState)state{
    self.borderWidthDic[@(state)] = @(value);
    [self changeLayerBorderWidth: self.button];
}

- (CGFloat)borderWidthForState:(UIControlState)state{
    return self.borderWidthDic[@(state)].floatValue;
}

- (void)setCornerRadius:(CGFloat)value forState:(UIControlState)state{
    self.cornerRadiusDic[@(state)] = @(value);
    [self changeLayerCornerRadius: self.button];
}

- (CGFloat)cornerRadiusForState:(UIControlState)state{
    return self.cornerRadiusDic[@(state)].floatValue;
}

#pragma mark -private
- (void)changeLayerBorderColor:(UIButton *)sender{
    UIColor *normalColor = self.borderColorDic[@(UIControlStateNormal)];
    if (!normalColor) {
        return;
    }

    UIColor *color = self.borderColorDic[@(sender.state)] ? : normalColor;
    sender.layer.borderColor = color.CGColor;
    
    if (sender.layer.borderWidth == 0) {
        sender.layer.borderWidth = 1;
    }
}

- (void)changeLayerBorderWidth:(UIButton *)sender{
    NSNumber *normalValue = self.borderWidthDic[@(UIControlStateNormal)];
    if (!normalValue) {
        return;
    }
    
    NSNumber *numer = self.borderWidthDic[@(sender.state)] ? : normalValue;
    sender.layer.borderWidth = numer.floatValue;
    
    if (sender.layer.borderWidth == 0) {
        sender.layer.borderWidth = 1;
    }
}

- (void)changeLayerCornerRadius:(UIButton *)sender{
    NSNumber *normalValue = self.cornerRadiusDic[@(UIControlStateNormal)];
    if (!normalValue) {
        return;
    }
    
    NSNumber *numer = self.cornerRadiusDic[@(sender.state)] ? : normalValue;
    sender.layer.cornerRadius = numer.floatValue;
    
    if (sender.layer.borderWidth == 0) {
        sender.layer.borderWidth = 1;
    }
}

@end



@implementation UIButton (Border)

- (NNBorderTarget *)borderTarget{
    id obj = objc_getAssociatedObject(self, _cmd);
    if (obj) {
        return obj;
    }
    NNBorderTarget *target = [[NNBorderTarget alloc]init];
    target.button = self;
    
    [target.button addObserver:target forKeyPath:@"selected" options:NSKeyValueObservingOptionNew context:nil];
    [target.button addObserver:target forKeyPath:@"highlighted" options:NSKeyValueObservingOptionNew context:nil];

    objc_setAssociatedObject(self, @selector(borderTarget), target, OBJC_ASSOCIATION_RETAIN);
    return target;
}

- (void)setBorderColor:(nullable UIColor *)color forState:(UIControlState)state{
    [self.borderTarget setBorderColor:color forState:state];
}

- (nullable UIColor *)borderColorForState:(UIControlState)state{
    return [self.borderTarget borderColorForState:state];
}

- (void)setBorderWidth:(CGFloat)value forState:(UIControlState)state{
    [self.borderTarget setBorderWidth:value forState:state];
}

- (CGFloat)borderWidthForState:(UIControlState)state{
    return [self.borderTarget borderWidthForState:state];
}

- (void)setCornerRadius:(CGFloat)value forState:(UIControlState)state{
    [self.borderTarget setCornerRadius:value forState:state];
}

- (CGFloat)cornerRadiusForState:(UIControlState)state{
    return [self.borderTarget cornerRadiusForState:state];
}

@end

相关文章

网友评论

      本文标题:进阶:UIButton 样式扩展

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