让人又爱又恨,欲罢不能的控件——UIButton

一、又爱又恨

UIButton是iOS开发中十分常用的控件,使用它有很多优势:

1、它继承自UIControl,支持多种事件,能够很灵活的根据不同的事件作出不同的响应;

2、它支持多种状态,可以设置不同状态的相关属性,尤其是对高亮的支持,能够让用户感觉到按钮被按到了,极大提升了用户的体验;

3、它可以同时支持文本和图片。

但是,它对图片和文本排列样式的支持不太友好。

它默认的样式是image在左,title在右, 中间没有间距,如果使用自动布局,它返回的固有大小刚好包裹内容,没有边框。

而在实际开发中,我们常常需要一个其他样式的button, 例如,image在上,title在下,中间需要10个像素的间距。

UIButton提供了 contentEdgeInsets、titleEdgeInsets、imageEdgeInsets几个属性,用来调整title和image的位置,从而支持其他的样式。

很多小伙伴的痛处就在于,找不到contentEdgeInsets、titleEdgeInsets、imageEdgeInsets对image和title位置影响的规律,不知道如何设置这几个属性来达到想要的效果,有时候可能费了九牛二虎之力,终于调到了想要的样式,却发现点击按钮靠边缘的的放无法响应点击事件。

二、欲罢不能

对于上面的需求,很多小伙伴可能会放弃UIButton, 自己通过一个UIImageView和一个UILabel加上一个UITapGestureRecognizer写一个Button,这样在功能上满足了需求,但是按下没有高亮效果,用户体验差,要实现对多种状态的支持,也是一件相当麻烦的事情。对于我这种特别懒的人,果断抛弃这样的想法。

三、爱上UIButton,不再嫌弃

UIButton默认的样式是这样的:
屏幕快照 2017-12-04 20.11.43.png

绿色的是Button的边框,橘红色的是image的边框, 蓝色的是title的边框。

contentEdgeInsets、titleEdgeInsets、imageEdgeInsets这三个属性都是相对于默认位置(即上图中的位置)而言的,向内为正,向外为负。

1、imageEdgeInsets:根据上面的理论, imageEdgeInsets的top分量是相对于image顶部的偏移量,向下为正,向上为负数;left分量是相对于image左边的偏移量,向右为正,向左为负;bottom是相对于image底部的偏移量,向上为正,向下为负;right是相对于image右边的偏移量,向左为正,向右为负;

2、titleEdgeInsets:与imageEdgeInsets一样

3、contentEdgeInset:与imageEdgeInsets一样, UIButton的intrinsicContentSize会根据contentEdgeInset返回。

举个栗子:

现在要实现上面的:image在上, title在下, 中间10个点的距离

// 图片在竖直方向的偏移量(总高度 - 图片的高度)/ 2
CGFloat imageOffsetY = (titleSize.height + space) / 2;
// 图片在水平方向的偏移量(总宽度 - 图片的宽度)/ 2
CGFloat imageOffsetX = titleSize.width / 2;
self.imageEdgeInsets = UIEdgeInsetsMake(-imageOffsetY, imageOffsetX, imageOffsetY, -imageOffsetX);
            
CGFloat titleOffsetY = (imageSize.height + space) / 2;
CGFloat titleOffsetX = imageSize.width / 2;
self.titleEdgeInsets = UIEdgeInsetsMake(titleOffsetY, -titleOffsetX, -titleOffsetY, titleOffsetX);

现在效果是这样的:
屏幕快照 2017-12-04 20.55.22.png

可以看到, 在样式上面满足了要求,但是,button的frame不对,image和title超出了button的范围, 这也是上面提到的,点击边缘无法响应的原因。
下面我们调整contentEdgeInsets:

// contentInsets是设置的内容边框,现在都设为了0
CGFloat contentOffsetY = (titleSize.height + imageSize.height + space - MAX(titleSize.height, imageSize.height))  / 2;
            CGFloat contentOffsetX = (titleSize.width + imageSize.width - MAX(titleSize.width, imageSize.width)) / 2;
            self.contentEdgeInsets = UIEdgeInsetsMake(contentOffsetY + self.contentInsets.top, -contentOffsetX + self.contentInsets.left, contentOffsetY + self.contentInsets.bottom, -contentOffsetX + self.contentInsets.right);

效果如下:
屏幕快照 2017-12-04 21.00.11.png

可以看到,已经达到了要求, 下面再加上边距:
屏幕快照 2017-12-04 21.01.45.png

好啦,就写到这里了,希望小伙伴们都能爱上UIButton。欢迎一起交流、讨论!

你可能感兴趣的:(让人又爱又恨,欲罢不能的控件——UIButton)