一、简介
<<UIButton(按钮) : 既能显示文字,又能显示图片,还能随时调整内部图片和文字的位置,实现了监听用户的点击事件,在用户点击后做出响应的功能.在App中UIButton是出现频率最高的控件之一.
<<继承关系:UIButton-->UIControl-->UIView-->UIResponder-->NSObject
<<UIButton的类是一个UIControl子类,它实现了在触摸屏上的按钮。触摸一个按钮拦截事件和动作消息发送到目标对象时,它的挖掘。设定的目标和行动方法都继承自UIControl。这个类提供了方法来设置标题,图像,按钮等外观属性。通过使用set方法,你可以指定一个不同的外观为每个按钮状态
格式为
1-->初始化(作用)
ypedef NS_ENUM(NSInteger, UIButtonType) {
UIButtonTypeCustom = 0, // no button type
UIButtonTypeSystem NS_ENUM_AVAILABLE_IOS(7_0), // standard system button
UIButtonTypeDetailDisclosure,
UIButtonTypeInfoLight,
UIButtonTypeInfoDark,
UIButtonTypeContactAdd,
UIButtonTypePlain API_AVAILABLE(tvos(11.0)) __IOS_PROHIBITED __WATCHOS_PROHIBITED, // standard system button without the blurred background view
UIButtonTypeRoundedRect = UIButtonTypeSystem // Deprecated, use UIButtonTypeSystem instead
};(如果属性有枚举类型的话,这里会有枚举类型说明)
UIButton *button=[UIButton buttonWithType:UIButtonTypeSystem]; (这是具体的例子)
+ (instancetype)buttonWithType:(UIButtonType)buttonType;// UIButton 有自己的初始化方式 (这是说明)
二、UIButton的创建(属性的顺序与苹果API一致)
1-->常规的 initWithFrame
UIButton *btn1 = [[UIButton alloc]initWithFrame:CGRectMake(10, 10, 80, 44)];
- (instancetype)initWithFrame:(CGRect)frame;// 父类UIView的初始化方法
2-->UIButton 的一个类方法(也可以说是静态方法)buttonWithType
typedef enum{
UIButtonTypeCustom = 0,// 自定义,无风格
UIButtonTypeRoundedRect,// 白色圆角矩形,类似偏好设置表格单元或者地址簿卡片
UIButtonTypeDetailDisclosure,//蓝色的披露按钮,可放在任何文字旁
UIButtonTypeInfoLight,//微件(widget)使用的小圆圈信息按钮,可以放在任何文字旁
UIButtonTypeInfoDark,//白色背景下使用的深色圆圈信息按钮
UIButtonTypeContactAdd,//蓝色加号(+)按钮,可以放在任何文字旁
} UIButtonType;
UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom];
UIButton *button = [[UIButton alloc]init];// 和上面一行代码等价
+ (instancetype)buttonWithType:(UIButtonType)buttonType;//创建并返回一个指定类型的新按钮。
注意:
按钮创建好之后,按钮的类型是不可以被修改
button.buttonType = UIButtonTypeCustom ; // 错误写法,系统会报错
三、UIButton的EdgeInsets内边距设置
1-->内边距设置
按钮内容整体向右下分别移动10像素
Button.contentEdgeInsets = UIEdgeInsetsMake(10, 10, -10, -10);
@property(nonatomic) UIEdgeInsets contentEdgeInsets; //默认是UIEdgeInsetsZero。在tvOS 10或稍后,除了定制按钮之外,默认值为非0
注意:
UIButton按钮可以只设置一个UILabel或者一个UIImageView,还可以同时具有UILabel和UIImageView;如果给按钮设置contentEdgeInsets属性,就是按钮的内容整体(包含UILabel和UIImageView)进行偏移。
2-->设置titleLabel的边界
self.pureButton.titleEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 10);
@property(nonatomic) UIEdgeInsets titleEdgeInsets; //默认是UIEdgeInsetsZero
3-->设置imageView的边界
self.pureButton.imageEdgeInsets= UIEdgeInsetsMake(0, -10, 0,10);
@property(nonatomic) UIEdgeInsets imageEdgeInsets; //默认是UIEdgeInsetsZero
具体效果参看关于UIButton的UIEdgeInsets属性
四、UIButton的设置各种状态的效果
1-->设置高亮状态 是否改变阴影
btn. reversesTitleShadowWhenHighlighted = YES; // 默认为NO
@property(nonatomic) BOOL reversesTitleShadowWhenHighlighted; //默认为NO.如果为YES,当按钮的状态进行切换时,文本的影子会反转
2-->设置高亮状态 加深图片颜色
btn.adjustsImageWhenHighlighted = NO; // 默认为YES 设置为NO取消效果
@property(nonatomic) BOOL adjustsImageWhenHighlighted; //默认为YES ,如果为YES,当按钮状态为高亮时,图像变暗.设置为NO取消效果
3-->设置失效状态 加深图片颜色
btn.adjustsImageWhenDisabled = NO; // 默认为YES 设置NO取消效果
@property(nonatomic) BOOL adjustsImageWhenDisabled;//默认为YES.如果为YES,当按钮状态为禁用时,图像变暗
4-->设置高亮状态 按钮发光
btn.showsTouchWhenHighlighted = YES; // 默认为NO
@property(nonatomic) BOOL showsTouchWhenHighlighted;//默认为NO.如果为YES, 当按钮状态为高亮时,显示一个简单的反馈(类似于光环)
五、UIButton的继承父类属性tintColor
1-->色彩,痕迹,相当于是一个描述一个视图中的线条的颜色
btn.tintColor=[UIColor redColor];
@property(null_resettable, nonatomic,strong) UIColor *tintColor ; //tintColor是通过superview层次结构继承的
注意:
(1).tintColor是描述线条轮廓的一种颜色,该颜色默认具有传递性,默认状态下最底部的视图的tintcolor会一直往上面的视图传递
(2).如果子视图改变了tintcolor那么将会和父视图的tintColor不一样;传递链从此处断开
(3).navagation的item的 tintColor和controller自带的View不是在同一层次上;改变controller的view的tintColor对navagation的tintColor没有颜色;
(4).由于,tintColor的特性,我们可以对镂空的图片(如tabbar的image和 BarButtonItem的image)进行设置tintColor就可以设置改变镂空图片的颜色
具体效果参看关于UIButton的tintColor属性
六、UIButton的按钮样式
1-->按钮的样式
typedef NS_ENUM(NSInteger, UIButtonType) {
UIButtonTypeCustom = 0, //无样式
UIButtonTypeSystem NS_ENUM_AVAILABLE_IOS(7_0), //设置为系统样式
UIButtonTypeDetailDisclosure,//蓝色小箭头按钮,主要做详细说明用
UIButtonTypeInfoLight,//亮色感叹号(微件(widget)使用的小圆圈信息按钮)
UIButtonTypeInfoDark,//暗色感叹号(白色背景下使用的深色圆圈信息按钮)
UIButtonTypeContactAdd,//十字加号按钮(蓝色加号(+)按钮)
UIButtonTypePlain API_AVAILABLE(tvos(11.0)) __IOS_PROHIBITED __WATCHOS_PROHIBITED, //没有模糊背景视图的标准系统按钮,TVOS 使用,IOS和WATCHOS禁止使用
UIButtonTypeRoundedRect = UIButtonTypeSystem //已过时,用UIButtonTypeSystem代替
};
UIButtonType buttonType=self.btn.buttonType ;
@property(nonatomic,readonly) UIButtonType buttonType;//按钮的样式,只读属性
七、设置UIButton的文本或者图片的展示
1-->设置button 某状态下 的标题
[btn setTitle:@"按钮" forState:UIControlStateNormal]; // 正常状态显示时候的文本
- (void)setTitle:(nullable NSString *)title forState:(UIControlState)state; // 设置UIButton的标题字,forState设置的是按钮的当前状态
2-->设置button 某状态下 的富文本标题
NSMutableAttributedString*attriString = [[NSMutableAttributedStringalloc]initWithString:@"123"];
[attriStringaddAttribute:NSForegroundColorAttributeName
value:[UIColorredColor]
range:NSMakeRange(4,2)];
[stateBtnsetAttributedTitle:attriStringforState:UIControlStateNormal];
//正常状态显示时候的富文本
- (void)setAttributedTitle:(nullable NSAttributedString *)title forState:(UIControlState)state; // 设置UIButton的标题字,forState设置的是按钮的当前状态
注意:
在同一个UIButton上根据条件先后设置不带属性的title,即用setTitle来设置标题,后来条件变化需要显示带属性的标题(例如下划线,或者字体多种颜色等等)使用setAttributedTitle,后来条件再次改变需要显示不带属性的标题
3-->设置button 某状态下 的文本颜色
[btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; // 正常状态显示时候的颜色,此时为红色
- (void)setTitleColor:(nullable UIColor *)color forState:(UIControlState)state; //设置标题使用指定的状态的颜色。默认黑色
注意:
//设置文字颜色
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
//设置背景颜色--前提是button的type不能为白色圆角矩形,因为太大,button都被白色覆盖了
[btn setBackgroundColor:[UIColor redColor]];
//设置按钮颜色方法
[button setTintColor:[UIColor blueColor]];
4-->设置某状态下标题的阴影颜色
[button setTitleShadowColor:[UIColor blueColor] forState:UIControlStateNormal];
- (void)setTitleShadowColor:(nullable UIColor *)color forState:(UIControlState)state; // 默认为nil
5-->设置某状态下的标题图片
[btn setImage:[UIImage imageNamed:@"btnIcon"] forState:UIControlStateNormal]; // 不会被拉伸,原比例显示
- (void)setImage:(nullable UIImage *)image forState:(UIControlState)state; // 默认为nil
6-->设置某状态下的背景图片
[btn setBackgroundImage:[UIImage imageNamed:@"btnBgImg"] forState:UIControlStateNormal]; // 会被拉伸,充满整个btn
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;//默认为nil
注意:
[btn setImage:[UIImage imageNamed:@"btnIcon"] forState:UIControlStateNormal]; // 不会被拉伸,原比例显示
[btn setBackgroundImage:[UIImage imageNamed:@"btnBgImg"] forState:UIControlStateNormal]; // 会被拉伸,充满整个btn
八、获取指定状态下的UIButton属性
1-->获取指定状态下的文本
NSString *title=[btn titleForState:UIControlStateNormal];
- (NSString *)titleForState:(UIControlState)state;//获取指定状态的文本,不一定是当前状态
//获取按钮指定状态下的文字
NSString *text= [sender titleForState:UIControlStateNormal];
//获取当前状态下的文字
NSString *text=sender.currentTitle;
2-->获取指定状态下的富文本
NSAttributedString *title=[btn attributedTitleForState:UIControlStateNormal];
- (nullable NSAttributedString *)attributedTitleForState:(UIControlState)state;//获取指定状态的富文本,不一定是当前状态
//获取按钮指定状态下的文字
NSAttributedString *text= [sender attributedTitleForState:UIControlStateNormal];
//获取当前状态下的文字
NSAttributedString *text=sender.currentAttributedTitle;
3-->获取指定状态下的标题颜色
UIColor *color=[btn titleColorForState:UIControlStateNormal];
- (nullable UIColor *)titleColorForState:(UIControlState)state;//获取指定状态的标题颜色,不一定是当前状态
//获取按钮指定状态下的标题颜色
UIColor *color=[btn titleColorForState:UIControlStateNormal];
//获取当前状态下的标题颜色
UIColor *color=sender.currentTitleColor;
4-->获取指定状态下的标题阴影颜色
UIColor *color=[btn titleShadowColorForState:UIControlStateNormal];
- (nullable UIColor *)titleShadowColorForState:(UIControlState)state;//获取指定状态的标题阴影颜色,不一定是当前状态
//获取按钮指定状态下的标题颜色
UIColor *color=[btn titleShadowColorForState:UIControlStateNormal];
//获取当前状态下的标题颜色
UIColor *color=sender.currentTitleShadowColor;
5-->获取指定状态下的标题图片
UIImage *image=[btn imageForState:UIControlStateNormal];
- (nullable UIImage *)imageForState:(UIControlState)state;//获取指定状态的标题图片,不一定是当前状态
//获取按钮指定状态下的标题图片
UIImage *image=[btn imageForState:UIControlStateNormal];
//获取当前状态下的标题图片
UIColor *color=sender.currentImage;
6-->获取指定状态下的背景图片
UIImage *image=[btn backgroundImageForState:UIControlStateNormal];
- (nullable UIImage *)backgroundImageForState:(UIControlState)state;//获取指定状态的背景图片,不一定是当前状态
//获取按钮指定状态下的背景图片
UIImage *image=[btn backgroundImageForState:UIControlStateNormal];
//获取当前状态下的背景图片
UIColor *color=sender.currentBackgroundImage;
九、获取当前状态下的UIButton属性
1-->获取当前状态下的文本
NSString *text=sender.currentTitle;
@property(nullable, nonatomic,readonly,strong) NSString *currentTitle;//只读属性
2-->获取当前状态下的富文本
NSAttributedString *text=sender.currentAttributedTitle;
@property(nullable, nonatomic,readonly,strong) NSAttributedString *currentAttributedTitle; //只读属性
3-->获取当前状态下的标题颜色
UIColor *color=sender.currentTitleColor;
@property(nonatomic,readonly,strong) UIColor *currentTitleColor;//只读属性
4-->获取当前状态下的标题阴影颜色
UIColor *color=sender.currentTitleShadowColor;
@property(nullable, nonatomic,readonly,strong) UIColor *currentTitleShadowColor;//只读属性
5-->获取当前状态下的标题图片
UIImage *currentImage=sender.currentImage;
@property(nullable, nonatomic,readonly,strong) UIImage *currentImage; //只读属性
6-->获取当前状态下的背景图片
UIColor *color=sender.currentBackgroundImage;
@property(nullable, nonatomic,readonly,strong) UIImage *currentBackgroundImage; //只读属性
十、UIButton的titleLabel属性(只读)
1-->按钮中显示的label显示的内容,此属性与currentTitle有很大不同
button.titleLabel.font = [UIFont fontWithName:@"STHeitiTC-Light" size:18];
@property(nullable, nonatomic,readonly,strong) UILabel *titleLabel NS_AVAILABLE_IOS(3_0)//只读属性
只读属性,不要用以下方法赋值:
button.titleLabel.text=@"只读";
详见
iOS 中UIButton的 settitle 和 titlelabel的使用误区
十一、UIButton的imageView属性(只读)
1-->按钮中显示的imageView ,此属性与currentImage有很大不同
UIImage *imageView=button.imageView;
@property(nullable, nonatomic,readonly,strong) UIImageView *imageView NS_AVAILABLE_IOS(3_0);
只读属性,不要用以下方法赋值:
button.imageView.image = [UIImage imageNamed:[UIImage imageNamed:@"1"]];
详见
UIButton设置Image和Label时,setImage和UIButton.ImageView.image的区别
十二、获取UIButton的属性边界
你可以通过子类化按钮来定制属于你自己的按钮类。在子类化的时候你可以重载下面这些方法,这些方法返回CGRect结构,指明了按钮每一组成部分的边界。
注意:不要直接调用这些方法, 这些方法是你写给系统调用的。
1-->指定背景边界(请勿直接调用)
- (CGRect)backgroundRectForBounds(CGRect)bounds{
return CGRectMake(0.0,0.0,44,44);
}
- (CGRect)backgroundRectForBounds:(CGRect)bounds;
2-->指定内容边界(请勿直接调用)
- (CGRect)contentRectForBounds(CGRect)bounds{
return CGRectMake(0.0,0.0,44,44);
}
- (CGRect)contentRectForBounds:(CGRect)bounds;
3-->指定文字标题边界(请勿直接调用)
- (CGRect)titleRectForContentRect(CGRect)bounds{
return CGRectMake(0.0,0.0,44,44);
}
- (CGRect)titleRectForContentRect:(CGRect)bounds;
4-->titleRectForContentRect(请勿直接调用)
- (CGRect)imageRectForContentRect(CGRect)bounds{
return CGRectMake(0.0,0.0,44,44);
}
- (CGRect)imageRectForContentRect:(CGRect)bounds;
十三、UIButton的废弃属性
@property(nonatomic,strong) UIFont *font NS_DEPRECATED_IOS(2_0, 3_0) __TVOS_PROHIBITED;
@property(nonatomic) NSLineBreakMode lineBreakMode NS_DEPRECATED_IOS(2_0, 3_0) __TVOS_PROHIBITED;
@property(nonatomic) CGSize titleShadowOffset NS_DEPRECATED_IOS(2_0, 3_0) __TVOS_PROHIBITED;
十四、UIButton的状态
1. normal(普通状态)
默认情况(Default)
对应的枚举常量:UIControlStateNormal
除开UIControlStateHighlighted、UIControlStateDisabled、UIControlStateSelected以外的其他情况,都是normal状态
这种状态下的按钮【可以】接收点击事件
如果前后连着设置按钮同时处于多种状态, 则表现出来的也是 normal 状态, 除去如果有 设置为 enabled = NO; 则会进入UIControlStateDisabled状态(包括颜色), 不能点击
//下面两种杂交在一起(就不是 normal 后面三种 ), 会显示为 Normal 状态的颜色,
//但是 设置了 Enabled == NO, 所以这里也是不能点击的,
self.button.selected=YES;self.button.enabled=NO;
2. highlighted(高亮状态)
对应的枚举常量:UIControlStateHighlighted
【当按住按钮不松开】或者【highlighted = YES】时就能达到这种状态
这种状态下的按钮【可以】接收点击事件
3.selected (选中状态)
对应的枚举常量:UIControlStateSelected
【button.selected = YES】时就能达到这种状态
这种状态下的按钮【可以】接收点击事件
4. disabled(失效状态,不可用状态)
如果enabled属性为NO,就是处于disable状态,代表按钮不可以被点击
对应的枚举常量:UIControlStateDisabled
【button.enabled = NO】时就能达到这种状态
这种状态下的按钮【无法】接收点击事件
5. 让按钮无法点击的2种方法
button.enabled = NO;
【会】进入UIControlStateDisabled状态
button.userInteractionEnabled = NO;
【不会】进入UIControlStateDisabled状态,继续保持当前状态
十五、UIButton的事件处理
UIButton继承了UIControl,所以可以使用UIControl提供的事件处理方法,常用的有如下:
1- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents //给目标添加事件,使用该方法实现Target-action模式
2- (void)removeTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents //移除目标上的事件
1-->添加事件
typedef NS_OPTIONS(NSUInteger, UIControlEvents) {
UIControlEventTouchDown = 1 << 0,
单点触摸按下事件:用户点触屏幕,或者又有新手指落下的时候。
UIControlEventTouchDownRepeat = 1 << 1,
多点触摸按下事件,点触计数大于1:用户按下第二、三、或第四根手指的时候。
UIControlEventTouchDragInside = 1 << 2,
当一次触摸在控件窗口内拖动时。
UIControlEventTouchDragOutside = 1 << 3,
当一次触摸在控件窗口之外拖动时。
UIControlEventTouchDragEnter = 1 << 4,
当一次触摸从控件窗口之外拖动到内部时。
UIControlEventTouchDragExit = 1 << 5,
当一次触摸从控件窗口内部拖动到外部时。
UIControlEventTouchUpInside = 1 << 6,
所有在控件之内触摸抬起事件。
UIControlEventTouchUpOutside = 1 << 7,
所有在控件之外触摸抬起事件(点触必须开始与控件内部才会发送通知)。
UIControlEventTouchCancel = 1 << 8,
所有触摸取消事件,即一次触摸因为放上了太多手指而被取消,或者被上锁或者电话呼叫打断。
UIControlEventValueChanged = 1 << 12,
当控件的值发生改变时,发送通知。用于滑块、分段控件、以及其他取值的控件。你可以配置滑块控件何时发送通知,在滑块被放下时发送,或者在被拖动时发送。UIControlEventEditingDidBegin = 1 << 16,
当文本控件中开始编辑时发送通知。
UIControlEventEditingChanged = 1 << 17,
当文本控件中的文本被改变时发送通知。
UIControlEventEditingDidEnd = 1 << 18,
当文本控件中编辑结束时发送通知。
UIControlEventEditingDidEndOnExit = 1 << 19,
当文本控件内通过按下回车键(或等价行为)结束编辑时,发送通知。
UIControlEventAllTouchEvents = 0x00000FFF,
通知所有触摸事件。
UIControlEventAllEditingEvents = 0x000F0000,
通知所有关于文本编辑的事件。
UIControlEventApplicationReserved = 0x0F000000,
预留给application(应用)使用的事件。
UIControlEventSystemReserved = 0xF0000000,
预留给internal framework(内部框架)使用的事件。
UIControlEventAllEvents = 0xFFFFFFFF
通知所有事件。
};
[button addTarget:self action:@selector(text:) forControlEvents:UIControlEventTouchUpInside];
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
1、self 指目标对象为当前对象
2、action 即 在目标对象上的点击方法;
action方法有以下几种形式:
- (void)doSomething;
- (void)doSomething:(id)sender;
- (IBAction)doSomething:(id)sender;
- (IBAction)doSomething:(UIButton *) sender;
3、何时调用该方法,UIControlEventTouchUpInside即单击时。
UIButton的几种触发条件
1、UIControlEventTouchDown
指鼠标左键按下(注:只是“按下”)的动作
2、UIControlEventTouchDownRepeat
指鼠标左键连续多次重复按下(注:只是“按下”)的动作,比如,鼠标连续双击、三击、……、多次连击。
说明:多次重复按下时,事件序列是这样的:
UIControlEventTouchDown ->
(UIControlEventTouchUpInside) ->
UIControlEventTouchDown ->
UIControlEventTouchDownRepeat ->
(UIControlEventTouchUpInside) ->
UIControlEventTouchDown ->
UIControlEventTouchDownRepeat ->
(UIControlEventTouchUpInside) ->
......
除了第一次按下外,后面每次摁下都是一个UIControlEventTouchDown事件,然后紧跟一个UIControlEventTouchDownRepeat事件。
3、UIControlEventTouchDragInside
指按下鼠标,然后在控件边界范围内拖动。
4、UIControlEventTouchDragOutside
与UIControlEventTouchDragInside不同的是,拖动时,鼠标位于控件边界范围之外。
但首先得有个UIControlEventTouchDown事件,然后接一个UIControlEventTouchDragInside事件,再接一个UIControlEventTouchDragExit事件,这时,鼠标已经位于控件外了,继续拖动就是UIControlEventTouchDragOutside事件了。
具体操作是:在控件里面按下鼠标,然后拖动到控件之外。
5、UIControlEventTouchDragEnter
指拖动动作中,从控件边界外到内时产生的事件。
6、UIControlEventTouchDragExit
指拖动动作中,从控件边界内到外时产生的事件。
7、UIControlEventTouchUpInside
指鼠标在控件范围内抬起,前提先得按下,即UIControlEventTouchDown或UIControlEventTouchDownRepeat事件。
8、UIControlEventTouchUpOutside
指鼠标在控件边界范围外抬起,前提先得按下,然后拖动到控件外,即
UIControlEventTouchDown ->
UIControlEventTouchDragInside(n 个) ->
UIControlEventTouchDragExit ->
UIControlEventTouchDragOutside(n 个)
时间序列,再然后就是抬起鼠标,产生UIControlEventTouchUpOutside事件
2-->添加事件
[self.camaraBtn removeTarget:self action:@selector(clicked:) forControlEvents:UIControlEventTouchUpInside];//与以上同理
- (void)removeTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents //移除目标上的事件