文章目录
- 基本知识
- 设置边框和选择状态下的背景颜色
- UIbutton设置圆角
- 普通圆角按钮
- 离屏渲染
- 绘制图像上下文
- UIButtonType导致的bug
- UIButton-如何正确的设置背景图片
- 创建
- 背景图片
- 实例解析
- 为什么要设置highlighted而不是selected
基本知识
第一、UIButton的定义
UIButton *button=[[UIButton buttonWithType:(UIButtonType);
能够定义的button类型有以下6种,
typedef enum {
UIButtonTypeCustom = 0, 自定义风格UIButtonTypeRoundedRect, 圆角矩形
UIButtonTypeDetailDisclosure, 蓝色小箭头按钮,主要做详细说明用
UIButtonTypeInfoLight, 亮色感叹号
UIButtonTypeInfoDark, 暗色感叹号
UIButtonTypeContactAdd, 十字加号按钮} UIButtonType;
第二、设置frame
button1.frame = CGRectMake(20, 20, 280, 40);
[button setFrame:CGRectMake(20,20,50,50)];
第三、button背景色
button1.backgroundColor = [UIColor clearColor];
[button setBackgroundColor:[UIColor blueColor]];
第四、state状态
forState: 这个参数的作用是定义按钮的文字或图片在何种状态下才会显现
enum {
UIControlStateNormal = 0, 常规状态显现
UIControlStateHighlighted = 1 << 0, 高亮状态显现
UIControlStateDisabled = 1 << 1, 禁用的状态才会显现
UIControlStateSelected = 1 << 2, 选中状态
UIControlStateApplication = 0x00FF0000, 当应用程序标志时UIControlStateReserved = 0xFF000000 为内部框架预留,可以不管他
};@property(nonatomic,getter=isEnabled)BOOL enabled; // default is YES. if NO, ignores touch events and subclasses may draw differently
@property(nonatomic,getter=isSelected)BOOL selected; // default is NO may be used by some subclasses or by application
@property(nonatomic,getter=isHighlighted)BOOL highlighted;
第五 、设置button填充图片和背景图片
[buttonsetImage:[UIImageimageNamed:@"checkmarkControllerIcon"]forState:UIControlStateNormal];
[buttonsetBackgroundImage:[UIImageimageNamed:@"checkmarkControllerIcon"]forState:UIControlStateNormal];
第六、设置button标题和标题颜色
[button1 setTitle:@“点击” forState:UIControlStateNormal];
[buttonsetTitleColor:[UIColorredColor]forState:UIControlStateNormal];
第七、设置按钮按下会发光
button.showsTouchWhenHighlighted=NO;
第八、添加或删除事件处理
[button1 addTarget:self action:@selector(butClick:) forControlEvents:UIControlEventTouchUpInside];
[btn removeTarget:nil action:nil forControlEvents:UIControlEventTouchUpInside];
第九、 设置按钮内部图片间距和标题间距
UIEdgeInsets insets; // 设置按钮内部图片间距
insets.top = insets.bottom = insets.right = insets.left = 10;
bt.contentEdgeInsets = insets;
bt.titleEdgeInsets = insets; // 标题间距
设置边框和选择状态下的背景颜色
[self LimitedCountBtnInit];
[self LimitedTimeBtnInit];
- (void)LimitedCountBtnInit{
// self.LimitedCountBtn.layer.borderColor=[UIColor blueColor].CGColor;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGColorRef color = CGColorCreate(colorSpaceRef, (CGFloat[]){73/255,230/255,255/255,0.2});
self.LimitedCountBtn.layer.borderColor=color;
self.LimitedCountBtn.layer.borderWidth=1.0f;
// self.LimitedCountBtn.layer.cornerRadius=10.0f;
self.LimitedCountBtn.layer.masksToBounds=YES;
[self.LimitedCountBtn addTarget:self action:@selector(LimitedCountBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.LimitedCountBtn addObserver:self forKeyPath:@"selected" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)LimitedTimeBtnInit{
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGColorRef color = CGColorCreate(colorSpaceRef, (CGFloat[]){73/255,230/255,255/255,0.2});
self.LimitedTimeBtn.layer.borderColor=color;
self.LimitedTimeBtn.layer.borderWidth=1.0f;
//self.LimitedTimeBtn.layer.cornerRadius=10.0f;
self.LimitedTimeBtn.layer.masksToBounds=YES;
[self.LimitedTimeBtn addTarget:self action:@selector(LimitedTimeBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.LimitedTimeBtn addObserver:self forKeyPath:@"selected" options:NSKeyValueObservingOptionNew context:nil];
}
-(void)LimitedCountBtnClicked:(UIButton*)button{
[self.LimitedTimeBtn setSelected:NO];
[button setSelected:YES];
}
-(void)LimitedTimeBtnClicked:(UIButton*)button{
[self.LimitedCountBtn setSelected:NO];
[button setSelected:YES];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
UIButton *button = (UIButton *)object;
if ([keyPath isEqualToString:@"selected"]) {
if (button.selected) {
[button setBackgroundColor:[UIColor blueColor]];
return;
}
[button setBackgroundColor:[UIColor whiteColor]];
}
}
注:需要优化,因为button在按下时,状态是highlighted,而不是selected,所以设置selected是没有作用的。上述代码是主动置类selected
UIbutton设置圆角
普通圆角按钮
UIButton *doneBtn = [UIButton buttonWithType:UIButtonTypeCustom];
doneBtn.frame = CGRectMake(0,0,40,20);
doneBtn.backgroundColor = [UIColor redColor];
//设置圆角的大小
doneBtn.layer.cornerRadius = 3;
//此行代码必须有(UIView例外)
doneBtn.layer.masksToBounds = YES;
doneBtn.titleLabel.font = [UIFont systemFontOfSize:15];
[doneBtn setTitle:@"按钮" forState:UIControlStateNormal];
[doneBtn addTarget:self action:@selector(clickdoneWithButton:) forControlEvents:UIControlEventTouchUpInside];
离屏渲染
以上方法只适用于一个界面只有几个按钮,如果是大量的按钮,如UITableViewCell上那么就会出现卡顿,造成这个原因就是离屏渲染。
所谓离屏渲染指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。
而以下一些行为都会触发离屏渲染
shouldRasterize(光栅化)
masks(遮罩)
shadows(阴影)
edge antialiasing(抗锯齿)
group opacity(不透明)
这里我们设置了masksToBounds属性,所以会触发离屏渲染,因而卡顿。
绘制图像上下文
/// 生成纯色图片
/// @param color [UIColor redColor]
/// @param rect CGRectMake(0, 0, _editBtn.frame.size.width, _editBtn.frame.size.height)],必须0,0开始
+ (UIImage *)createImageWithColor:(UIColor *)color frame:(CGRect)rect
{
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
/// 对图片生成圆角,可用于button等的背景图片
/// @param OriginalImage 原图,可用纯色图片
/// @param sizeToFit 大小
/// @param radius 圆角弧度
+ (UIImage *)OriginalImage:(UIImage *)OriginalImage WithRoundedCornersAndSize:(CGSize)sizeToFit andCornerRadius:(CGFloat)radius
{
CGRect rect = (CGRect){0.f, 0.f, sizeToFit};
UIGraphicsBeginImageContextWithOptions(sizeToFit, NO, UIScreen.mainScreen.scale);
CGContextAddPath(UIGraphicsGetCurrentContext(),
[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:4].CGPath);
CGContextClip(UIGraphicsGetCurrentContext());
[OriginalImage drawInRect:rect];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
@end
使用
UIImage *imageColor=[DrawImage createImageWithColor:[UIColor redColor] frame: CGRectMake(0, 0, _editBtn.frame.size.width, _editBtn.frame.size.height)];
[_editBtn setBackgroundImage:[DrawImage OriginalImage: imageColor WithRoundedCornersAndSize:_editBtn.frame.size andCornerRadius:3.0 ] forState:UIControlStateNormal];
UIButtonType导致的bug
上述设置边框和选择状态下的背景颜色的例子,如果UIButtonType 是UIButtonTypeCustom,选中状态下设置背景颜色会很正常。但是UIButtonType如果是系统样式如UIButtonTypeRoundedRect,选中状态下设置背景颜色会有如下bug
UIButton-如何正确的设置背景图片
创建
xib:直接拖
code:UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
注意:xib中直接拖进去的button默认为UIButtonTypeSystem,该类型默认会对button做些一些定制化工作(包括字体,颜色等),如果我们在该类型的基础上对button做自定义背景图片,会产生错误的效果。对于我们最常用的按钮,通常设定为UIButtonTypeCustom
背景图片
设置常态下的背景图片 [self.button setBackgroundImage:[UIImage imageNamed:@“green_btn_normal”] forState:UIControlStateNormal]; 设置按下状态的背景图片 [self.button setBackgroundImage:[UIImage imageNamed:@“green_btn_selected”] forState:UIControlStateHighlighted];
注意:按下状态时,state的值是UIControlStateHighlighted,而不是selected,只有这样设置,才能让你的按钮显示出正确的颜色
实例解析
制作demo,需求如下:
创建2个按钮
SystemTypeOriginal为storyboard中直接拖上去的button,type保持system不变,设置green_btn_normal.png为normal状态的背景图片,设置green_btn_selected.png为highlighted状态的背景图片
CustomTypeOriginal为storyboard中直接拖上去的button,type设置为Custom,设置green_btn_normal.png为normal状态的背景图片,设置green_btn_selected.png为highlighted状态的背景图片
运行demo,效果图如下:
通过上图分析可知:
SystemType下字体默认为15,且字体颜色为蓝色
CustomType下字体默认为18,字体颜色为白色
普通状态下的按钮背景图片与预期相符,green_btn_normal表示的是原始图片的颜色,此时原始图片颜色与按钮背景颜色一致
此时,按下SystemTypeOriginal,效果图如下:
按下SystemTypeOriginal
上图的按下效果变得非常诡异,与预期的green_btn_selected颜色相差甚远,这就是上面说的,在systemtype下,设置背景图片会产生错误的效果,所以常用的按钮都会设置为Customtype。
那么,我们按下CustomTypeOriginal,看下效果图:
按下CustomTypeOriginal
现在按下的背景图片就对了!
为什么要设置highlighted而不是selected
因为button在按下时,状态是highlighted,而不是selected,所以设置selected是没有作用的。
参考:https://www.jianshu.com/p/8fb8ff3fed44