一、又爱又恨
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默认的样式是这样的:绿色的是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);
现在效果是这样的:可以看到, 在样式上面满足了要求,但是,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);
效果如下:可以看到,已经达到了要求, 下面再加上边距:
好啦,就写到这里了,希望小伙伴们都能爱上UIButton。欢迎一起交流、讨论!