UIButton added border color rounded corner state support;
No inheritance, no intrusion;
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) }Copy the code
// // 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 { button? .removeObserver(self, forKeyPath: "selected") button? .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" } /// Associated UITableView object 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) } }Copy the code
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)); }Copy the code
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
Copy the code
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
Copy the code