一,概述
UIButton在日常开发中经常用到UI控件,它是继承自UIControl,并且集成UIImageview和UIlabel封装而成的。 日常开发中我们经常需要做一些定制,这些定制很简单,就是改变image和title的位置而已.
二,涉及的相关属性
* UIButton的属性
@property(nonatomic) UIEdgeInsets contentEdgeInsets UI_APPEARANCE_SELECTOR(UI_APPEARANCE_SELECTOR 表示可以外观定制);
@property(nonatomic) UIEdgeInsets titleEdgeInsets;
@property(nonatomic) UIEdgeInsets imageEdgeInsets;
* UIControl的属性
@property(nonatomic) UIControlContentVerticalAlignment contentVerticalAlignment;
@property(nonatomic) UIControlContentHorizontalAlignment contentHorizontalAlignment;
三,相关的简单测试
UIButton * abutton =({
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame =CGRectMake(0, 0, 200, 200);
button.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/2);
[button setTitle:@"我好怕怕!" forState:UIControlStateNormal];
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:@"small"] forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor orangeColor]];
button;
});
[self.view addSubview:abutton];
//测试
//button 内部imageView的frame
NSLog(@"%@",NSStringFromCGRect(abutton.imageView.frame));
//button 内部label 的frame
NSLog(@"%@",NSStringFromCGRect(abutton.titleLabel.frame));
1>仅有文字
打印结果:
2016-09-14 10:56:06.213 撒打发士大夫撒旦法[2948:48347] {{0, 0}, {0, 0}}
2016-09-14 10:56:06.213 撒打发士大夫撒旦法[2948:48347] {{61.333333333333336, 89.333333333333329}, {77.333333333333329, 21.666666666666668}}
分析结果:控件本身的大小是(200,200),此时label的大小是{77.333333333333329, 21.666666666666668} 位置为居中.
2>仅有图片
打印结果:
2016-09-14 10:59:47.868撒打发士大夫撒旦法[3140:52538] {{72, 71}, {56, 58}}
2016-09-14 10:59:47.870撒打发士大夫撒旦法[3140:52538] {{0, 0}, {0, 0}}
分析结果 : 此时控件本身的大小是(200,200),此时imageView的大小是{56, 58} 位置居中. 而此时我们查看图片的尺寸大小,它的大小也是{56,58}
这样似乎看来,button控件内部对ImageView的设置是以图片本身尺寸的大小进行创建的.
3>文字和图片共存
1> 图片尺寸小于(200 ,200)
打印结果:
2016-09-14 11:12:21.496 撒打发士大夫撒旦法[3543:59053] {{33.333333333333336, 71}, {56, 58}}
2016-09-14 11:12:21.496 撒打发士大夫撒旦法[3543:59053] {{89.333333333333343, 89.333333333333329}, {77.333333333333329, 21.666666666666668}}
2>图片尺寸大于(200,200)
打印结果:
2016-09-14 11:14:29.573撒打发士大夫撒旦法[3608:60400] {{0, 0}, {200, 200}}
2016-09-14 11:14:29.573撒打发士大夫撒旦法[3608:60400] {{200, 89.333333333333329}, {0, 21.666666666666668}}
分析结果:
当文字和图片同时存在是,当图片本身的尺寸大于button控件的尺寸时,即使设置了文字,仍然只显示图片,不显示文字. 并且图片做伸缩处理铺满整个控件.
四, 相关问题总结
1> 关于Button图片自适应和文本自适应问题
*图片自适应*
我们在上面的测试中,发现当我们的图片尺寸小于button控件本身的尺寸时, 图片是以图片的尺寸来创建ImageView的,且居中显示. 如果我们想让小图片铺满整个Button控件怎么办呢?
* 不成功方法:
1)用ImageView本身自适应的方法可行吗? 显然不行,因为ImageView的大小本身就是依据图片的尺寸进行创建的, 所以当然没有效果.
2)用Button自身的ContentMode设置,也是没效果的.
* 成功的方法:
1)
button.contentHorizontalAlignment= UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
2)继承UIButton,重写 imageRectForContentRect 方法返回button的bounds
- (CGRect)imageRectForContentRect:(CGRect)bounds{
return CGRectMake(0.0, 0.0, self.size.width, self.size.height);
}
*文本自适应*
同理图片,titleLabel的大小,是根据传入的文字来进行计算创建的, 那么当文字的宽度高于控件的宽度怎么办呢?
* 不成功的方法
1)用titleLabel自身的sizeToFit来自适应可行吗?显然也是不行的,因为titleLabel的大小就是根据文字来创建的,所以当然没有效果.
* 成功的方法
1)使用Button的sizeToFit 方法, 不过button的本身的形状会变形, 假如不影响你的需求可以尝试.
2)使用titleLabel的
numberOfLines的自动换行.
3)使用titleLabel的
adjustsFontSizeToFitWidth的方法, 不过titlLabel的字体会变小,来适应UIButton,假如不影响需求可以尝试.
2>UIButton上的imageEdgeInsets,titleEdgeInsets与contentEdgeInsets的属性使用
相关含义:
imageEdgeInsets 设置UIButton的实例变量的图片位于四个边框的间的间距(这里边框,是指图片本身的初始状态来作参考的)
titleEdgeInsets 设置UIButton的实例变量的标题位于四个边框的间的间距(这里边框,是指标题本身的初始状态来作参考的)
contentEdgeInsets UIButton中包含的所有内容与它本身的frame间的边距
举个例子:
初始状态:
UIButton * abutton =({
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame =CGRectMake(0, 0, 200, 200);
button.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/2);
[button setTitle:@"我好怕怕!" forState:UIControlStateNormal];
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:@"small"] forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor orangeColor]];
button.titleLabel.adjustsFontSizeToFitWidth =YES;
button;
});
[self.view addSubview:abutton];
效果图:
改变状态
UIButton * abutton =({
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame =CGRectMake(0, 0, 200, 200);
button.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/2);
[button setTitle:@"我好怕怕!" forState:UIControlStateNormal];
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:@"small"] forState:UIControlStateNormal];
button.titleEdgeInsets=UIEdgeInsetsMake(0,-button.imageView.bounds.size.width, 0, button.imageView.bounds.size.width);
button.imageEdgeInsets =UIEdgeInsetsMake(0,button.titleLabel.bounds.size.width, 0, -button.titleLabel.bounds.size.width);
[button setBackgroundColor:[UIColor orangeColor]];
button.titleLabel.adjustsFontSizeToFitWidth =YES;
button;
});
[self.view addSubview:abutton];
效果图:
怎么理解呢?
button.titleEdgeInsets=UIEdgeInsetsMake(0,-button.imageView.bounds.size.width, 0, button.imageView.bounds.size.width);
button.imageEdgeInsets =UIEdgeInsetsMake(0,button.titleLabel.bounds.size.width, 0, -button.titleLabel.bounds.size.width);
titleLabel左边相对于原来的位置向左移动了ImageView的宽度(-)
titleLabel右边相对于原来的位置向左移动了ImageView的宽度(+)
同是向左移动为什么左边是"-"的,而右边的是"+"的呢? 这是因为UIEdgeInset本身就是相对于内部边界而言的,左边相对于原来的位置已经超出了内部边界, 而右边向左却仍然在内部边界之内.
3>关于contentVerticalAlignment 和 contentHorizontalAlignment;
contentVerticalAlignment和contentHorizontalAlignment 是UIControl的两个属性,用于排列内部元素. typedef NS_ENUM(NSInteger, UIControlContentVerticalAlignment) {
UIControlContentVerticalAlignmentCenter = 0,
UIControlContentVerticalAlignmentTop = 1,
UIControlContentVerticalAlignmentBottom = 2,
UIControlContentVerticalAlignmentFill = 3,
};
typedef NS_ENUM(NSInteger, UIControlContentHorizontalAlignment) {
UIControlContentHorizontalAlignmentCenter = 0,
UIControlContentHorizontalAlignmentLeft = 1,
UIControlContentHorizontalAlignmentRight = 2,
UIControlContentHorizontalAlignmentFill = 3,
};
共有16种选择, 其中默认的是居中选择
列举其它的部分选择方式
注意:
在V:fill H:fill 选择中,title并没有在水平方向铺满全屏,仍然保持titleLab的原始宽度. 这说明TitleLabel的宽度,不能被拉伸,却能被压缩.