理解UIButton的各种EdgeInsets

这篇文章整理了一下UIButton的各种EdgeInsets都咋用,有啥效果。留着自己以后对此迷糊时再看一看,也希望能对你有所帮助喔😜。

达成共识

如果没有给UIButton的宽和高一个固定值,那么UIButon的大小将自动调整为正好放下titleimage。这个苹果官方文档有提到,而且在Storyboard中一试便知。此外,默认情况下图片在左,文字在右。

没有给固定宽和高,给UIButton设置了一个imagetitle,运行的结果如下:

UIControlContent Vertical/Horizontal Alignment

在开始说EdgeInsets之前,先说说UIControlContentVerticalAlignmentUIControlContentHorizontalAlignment产生的效果,因为这两个属性的设置也会对UIButton的效果有一定影响,而且跟后面EdgeInsets的计算也有关系。

UIControlContentVerticalAlignment控制的是UIButtonimagetitle在竖直方向的对齐方式,其值有topbottomcenterfill。当指定为fill时,图片会在竖直方向被拉伸填满UIButton的高度。

为了效果明显,我给上面的那个按钮设置了一个较大的宽高,当取各种值时,效果如下:

UIControlContentHorizontalAlignment控制的则是水平方向的对齐方式。其值有leftrightcenterfill。当指定为fill时,图片并没有在水平方向将UIButton充满,而是在右侧留出了一定距离,这个距离应该是title的宽度,但是title实际上也没有乖乖的跑到那段空隙去,而是和image重叠了╮(╯▽╰)╭

当取各种值时,效果如下:

UIEdgeInsets

UIButton共有3个与UIEdgeInsets相关的属性:

imageEdgeInsets调整image的上下左右边缘离开原来位置的距离,该调整并不会改变UIButton原来的大小,image为了适应调整,可能会变形或者跑出UIButton的外面。

titleEdgeInsets调整title的上下左右边缘离开原来位置的距离,该调整并不会改变UIButton原来的大小,title为了适应调整,文字可能显示不全或者跑出UIButton的外面。

contentEdgeInsets调整UIButton本身的上下左右边缘离开原来位置的距离,该调整会改变UIButton的大小。

这个3个属性的默认值都是.zero

UIEdgeInsetstopleftbottomright构成,对于imageEdgeInsetstitleEdgeInsets来说:

top为正值时,控件会相对原来所在的位置下移相应值,控件的顶部边缘会在原来位置的下方相应值。top为负值时,控件会相对原来的位置上移相应值,控件的顶部边缘会在原来位置的上方相应值。

left为正值时,控件会相对原来所在的位置右移相应值,控件的左侧边缘会在原来位置的右方相应值。left为负值时,控件会相对原来的位置左移相应值,控件的左侧边缘会在原来位置的左方相应值。

bottom为正值时,控件会相对原来所在的位置上移相应值,控件的底部边缘会在原来位置的上方相应值。bottom为负值时,控件会相对原来的位置下移相应值,控件的底部边缘会在原来位置的下方相应值。

right为正值时,控件会相对原来所在的位置左移相应值,控件的右侧边缘会在原来位置的左方相应值。right为负值时,控件会相对原来位置右移相应值,控件的右侧边缘会在原来位置的右方相应值。

对于contentEdgeInsets来说,当topleftbottomright为正值时,会使UIButton向四周扩展变大。为负值时,会使UIButton向内收缩变小。哈哈,这样好记一些😄

现在把UIButton的固定大小去掉,让它自己自适应。先来一个水平方向调整的:

1
2
3
4
yellowButton.contentHorizontalAlignment = .left
yellowButton.contentVerticalAlignment = .center
yellowButton.imageEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0)
yellowButton.titleEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0)

第一张图只设置了imageEdgeInsets,没有设置titleEdgeInsets,第三张两者都设置了。可以看到,imageEdgeInsetstitleEdgeInsets并不会互相影响,第一张图中imagetitle重合了,并没有把title往右挤了相应距离。第二张和第四张看到,imagetitle本身被压缩了。

还有一点值得注意的是,如果原来UIButton的大小能容纳下调整后的imagetitle,它们将不会被压缩。像第一张那样,image左移后还是放得下的,所以没有被压缩,title却放不下了,所以被压缩了。为什么说是原来的大小呢,因为调整contentEdgeInsets也会使UIButton变大,但是imagetitle却不会因此而不被压缩。

再来一个竖直方向调整的:

1
2
3
4
yellowButton.contentHorizontalAlignment = .center
yellowButton.contentVerticalAlignment = .top
yellowButton.imageEdgeInsets = UIEdgeInsetsMake(20, 0, 0, 0)
yellowButton.titleEdgeInsets = UIEdgeInsetsMake(20, 0, 0, 0)

第一张图仍然是只调整了imageEdgeInsets的效果。

从上面的结果可以看到调整imageEdgeInsetstitleEdgeInsets并不会改变UIButton的大小,而导致有时图片被压缩,或者文字显示不下。这时就要接着用UIButton的另一个属性contentEdgeInsets来调整了。

1
2
3
4
5
yellowButton.contentHorizontalAlignment = .left
yellowButton.contentVerticalAlignment = .center
yellowButton.imageEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0)
yellowButton.titleEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0)
yellowButton.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 20)

好吧,结果并不如我们想象的一样,UIButton是变大了,但是imagetitle并没有自己调整,还是一个压缩的状态。验证了上面值得注意的那一点~ 这时候要再调整一下它们的right值了,将其设置为-20,如愿得到了下面的结果。

需要注意 当设置contentHorizontalAlignment.left时,再设置imageEdgeInsetstitleEdgeInsets.right为负值时,如果imagetitle原来是压缩状态,会对其调整。如果原来是正常状态,则不会产生任何影响。也就是说,imageEdgeInsetstitleEdgeInsets的设置并不会让imagetitle被拉伸!其他方向亦如此~

所以,为了保证imagetitle始终不被压缩,.left设置了多少正值,.right就设置多少负值。上下方向也一样。

实战

上面做了这么多铺垫,现在通过设置UIButton的3个EdgeInsets属性来实现一些我们想要的效果吧😉

在做水平方向的调整时,最好将contentHorizontalAlignment设置为.left,这样改动就从左开始。在做竖直方向的调整时,最好将contentVerticalAlignment设置为.top,这样改动就从上面开始。对于自己在设置时,比较容易在脑子想象每个值设置完的样子😁

例1:设置一个四周间隔20,image和title之间间隔20的button。

计算过程如下:

1
2
3
4
5
6
7
8
9
//水平方向的调整,设为靠左对齐
yellowButton.contentHorizontalAlignment = .left
yellowButton.contentVerticalAlignment = .center
//image左移20
yellowButton.imageEdgeInsets = UIEdgeInsetsMake(0, 20, 0, -20)
//title左移20,并且与image之间间隔20
yellowButton.titleEdgeInsets = UIEdgeInsetsMake(0, 40, 0, -40)
//image左移20,已经使button左侧的间隔是20了
yellowButton.contentEdgeInsets = UIEdgeInsetsMake(20, 0, 20, 60)

最后,完美😂

例2:设置一个image在上居中,title在下居中,两者之间间距20,四周间距20的button。

这个看起来复杂一些,但也只是计算复杂一些~ 计算过程如下,求出标记问号的距离就行了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//设置水平和竖直的对齐方式
yellowButton.contentHorizontalAlignment = .left
yellowButton.contentVerticalAlignment = .top

let imageRect = yellowButton.imageView!.frame
let titleRect = yellowButton.titleLabel!.frame
let buttonRect = yellowButton.frame

//图中?1的值
let image_l = (buttonRect.size.width-imageRect.size.width)/2
//确定image的位置
yellowButton.imageEdgeInsets = UIEdgeInsetsMake(20, image_l, -20, -image_l)
//图中?2的值
let title_l = imageRect.size.width-(buttonRect.size.width-titleRect.size.width)/2
//图中?3的值
let title_t = imageRect.size.height+40
//title的位置可以确定了
yellowButton.titleEdgeInsets = UIEdgeInsetsMake(title_t, -title_l, -title_t, title_l)
//图中?4的值
let button_b = titleRect.size.height+60
//计算图中?5的值
let max_w = max(titleRect.size.width, imageRect.size.width)
let button_l = -(buttonRect.size.width-(max_w+20*2))/2
//button要调整的大小确定了
yellowButton.contentEdgeInsets = UIEdgeInsetsMake(0, button_l, button_b, button_l)

运行后的结果:

了解imageEdgeInsetstitleEdgeInsetscontentEdgeInsets后,就可以随心所欲的来设置自己的button了。

至此,总结完毕😆

本文作者:意林
本文链接:http://shinancao.github.io/2016/12/15/iOS-UIButton-EdgeInsets/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!