UIButton的几个 edgeInsets 属性

闲扯淡

很久之前就想梳理一下 UIButton 的几个 edgeInsets 属性. 最近刚好项目需要用到,顺便整理下.
我们先看看这几个属性:

open var contentEdgeInsets: UIEdgeInsets 
open var titleEdgeInsets: UIEdgeInsets
open var imageEdgeInsets: UIEdgeInsets

在需要修改系统系统的 UIButton 样式内部布局时, 最常见的场景就是将按钮 [左图右字] 的布局形式改为 [上图下字] , 或者修改 imageView 与 label 之间的间距, 以及按钮内容按照预期偏移.
之前开发中遇到过几次修改 insets 的, 虽然最后在左算右算的推测之下, 也算是完成了任务, 但下一次再遇见的时候又会忘掉. 今天来总结一下具体的数值影响对实际布局影响的方式吧.

先看 UIEdgeInsets 对 Frame 的影响吧, 先上结论!

UIEdgeInsets 对单个视图布局的影响

UIEdgeInsets(50, 50, 50, 50)
UIEdgeInsets(50, 50, 0, 0)
UIEdgeInsets(-50, -50, -50, -50)
UIEdgeInsets(-50, -50, 50, 50)

以原 frame 的边框为基准, 向内为正, 向外为负.最终的边框根据 edgeInsets 四个值的大小确定, 具体计算公式为:

  1. 对与 OrginalFrame、EdgeInset、ResultFrame 有:


    frame 随 edgeInsets 的变化
  2. 对于 OriginalPosition、EdgeInsets、ResultPosition 有:


    center 随 edgeInsets 的变化

为什么要有个 position 的位移计算? 因为 UIButton 在对 imageViewtitleLabel 进行布局的时候需要考虑 imageView.intrinsicContentSizetitleLabel.intrinsicContentSize, 这种时候情况就会变得很复杂. edgeInsets 所起的作用会由于 intrinsicContentSize 而改变. 这种时候, frame 不再靠谱, 反而是 centerposition 依旧坚守岗位. 所以在设置 imageEdgeInsetstitleEdgeInsets 时, 结果往往变得很迷惑. 就需要了解 UIButton 对子控件布局了, 请参阅UIButton 的布局 imageView 和 titleLabel 的过程. 可以稍微缓解下子控件布局的疑惑. 当然如果有更好的理解方法, 请告诉我. 我也很想知道.

contentEdgeInsets 实验

这个结论在设置 UIButton 的 contentEdgeInsets 时非常直白. 举个例子, 我们新建一个 100x100 pt 的 button, 并给它一张 100x100 pt 的图片,设置好颜色边框之后,让我们开始吧 :

let sampleBtn = UIButton(frame: CGRect(x: 40, y: 40, width: 100, height: 100));
sampleBtn.layer.borderColor = UIColor.white.cgColor
sampleBtn.layer.borderWidth = 1.0

sampleBtn.setImage(UIImage(named: "100"), for: .normal)
sampleBtn.imageView?.layer.borderWidth = 1.0
sampleBtn.imageView?.contentMode = .scaleToFill
sampleBtn.imageView?.layer.borderColor = UIColor.orange.cgColor

运行可得:


image.png

可以看到 imageView 和 UIButton 的边框完全重合. 在这种情况下, imageView的 frame 与 button.bounds 完全重合. 所以可以通过观察 imageView 的 frame 来观察具体偏移量的计算:

设置 sampleBtn 的 contentInsets 为 (-20, -20, 50, 30) , 在按下 CMD+R 之前我们先按照上述规则计算一下, 之前的 content 的 frame 为(0, 0, 100, 100)对应的 content 的 frame 应为: (-20, -20, 90, 70).
然我们来看看运行结果:

image.png

在布局之后打印 imageView 的 frame 可以得到:

image:(-20.0, -20.0, 90.0, 70.0)

与预期契合.

对仅有 imageView 的 button 设置 imageEdgeInsets 实验

同样, 设置 contentEdgeInsets.zero, 设置 imageEdgeInsets 的值, 可以得到以下截图(这里小小的做了个弊: image.sizebutton.frame.size 相等, 这是为了更直白的看出对子控件的影响. 在两者不相等时, 布局方式会由于需要考量image.size 变得不够直白):

image.png

image.png

image.png

是的, 与预期一致.

对仅有 titleLabel 的 button 设置 titleEdgeInsets 实验

对既有 titleLabel 又有 imageView 的 button 设置 imageEdgeInsets 与 titleEdgeInsets 实验

先把 buttoncontentEdgeInsets 置回 .zero, 在本节, 我们不再修改 contentEdgeInsets, 避免对观察结果造成影响:
调整 buttonframe(40, 40, 200, 100)(当然这是由于 100x100 的大小装不下 label, 不方便我们观察), 给 buttonlabel 设置下属性:

sampleBtn.titleLabel?.layer.borderWidth = 1.0
sampleBtn.titleLabel?.layer.borderColor = UIColor.cyan.cgColor
sampleBtn.setTitle("点击", for: .normal)
sampleBtn.setTitleColor(.white, for: .normal)

运行结果如下:


image.png

先来梳理下页面上的组件属性:

  1. button: frame(40, 40, 200, 100), borderColor: .while
  2. imageView: imageSize: 100x100, borderColor: .orange
  3. label: text: "点击", borderColor: .cyan

可以看到, 默认情况下, imageViewlabel 两个控件相连居中, 布局后打印下当前 imageViewlabelframe 为:

image:(31.5, 0.0, 100.0, 100.0)
label:(131.5, 39.5, 37.0, 21.5)

我们来设置下 imageViewedgeInsets并运行:

sampleBtn.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10)
//sampleBtn.titleEdgeInsets = UIEdgeInsetsMake(10, 0, 10, 0)

image.png

再看看设置 label 的情况:

//sampleBtn.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10)
sampleBtn.titleEdgeInsets = UIEdgeInsetsMake(10, 0, 10, 0)
image.png

在这种情况下, 情况似乎变得难以捉摸. 这是由于 imageView 和 titleLabel 都是有有效intrinsicContentSize的, UIButton 需要保证最佳的显示效果, 对 imageViewtitleLabelframe 采用了更复杂的计算机制, 而不是简单的计算偏移.

但在多次验证后, 可以发现虽然 frame 的计算方式由于多重因素影响, 不太好计算, 但 center 还是非常守规矩的. 也就是上面用 ResultFrame 可以推导出来的 ResultPoition公式.

image.png

所以如果只是想简单的移动 UIButtonimageViewtitleLabelcenter, 而不改变 imageViewtitleLabel 的大小的话, 事情就变得简单了很多: 设置 edgeInsets 时只需要注意边距移动方向相同, 大小相等就可以了. 即, 两两相反, 即 top = - bottom , left = - right, 这种时候该视图就只会改变 origincenter 而不会改变 size.

例如, 如果我们想要让图片上下排列, 只需要将 imageView 向上且向右移动, 设置 imageEdgeInsets = (a, b, -a, -b), 上和右, 则 a > 0, b < 0, 具体是多少?你可以根据 titleLabel.size 来决定. 将 titleLabel 向左下移动? 同理呀!

image.png

结论

UIEdgeInset 可以设置 View偏移量, 其方向为 frame中心方向为, 而影响如定义的 topleftbottomright, 即为各个边框在向中心方向上的偏移量.
但在 UIButton 中的 imageViewtitleLabel 同时存在时布局, 由于系统在处理这里的布局时需要考量到 intrinsicContentSize , 如果希望设置edgeInsets之后不造成变形, 请在 edgeInsets 时, 不要修改 imageViewtitleLabel 的大小, 而仅进行移动位置操作.

如果对 EdgeInsets 如何影响 imageViewtitleLabelframe, 可以移步
UIButton 的布局 imageView 和 titleLabel 的过程 一起讨论下.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容