UIButton 布局 imageView 和 titleLab

作者: ZyonPaul | 来源:发表于2017-12-08 10:57 被阅读126次

UIButton 的布局 imageViewtitleLabel 的过程

哔哔叨: 写 iOS 代码也有段时间了, 但始终不怎么用 systemUIButton, 因为每次设置 insets 的时候都会卡住好一阵啊! 各种奇怪的偏移. 趁着有时间, 整理一下.😘.

NOTE: 以下皆为伪代码

假定条件

对于一个 UIButton 的实例 button, 我们假定以下变量

let imageEdgeInsets = UIEdgeInsetsMake(top, left, bottom, right) // imageInsets
let titleEdgeInsets = UIEdgeInsetsMake(top, left, bottom, right) // titleEdgeInsets
let imageSize = CGSize(width, height) // image.size
let textSize = CGSize(width, height) // labelSize to fit he title text

一. 根据 contentEdgeInsets 确定布局内容大小

根据 button.contentEdgeInsetsbutton.frame 计算出子控件布局范围 contentRect .

let contentRect = CGRect(x, y, width, height) // button.contentRect

二. 计算 imageViewtitleLabel 的无 edgeinsets 位置

  1. 获取 image.size 结合布局范围 contentRect 的大小得出 imageView 的大小
// imageEdgetInsets = .zero 时, imageView 的 size
let defaultImgSize = CGSize(width = min(imageSize.width, contentRect.width),
                            height = min(imageSize.height, contentRect.height))
  1. 根据 imageViewsize 计算出在布局范围 contentRect 内剩余的 titleLabel 的布局大小以确定 titleLabel 的布局大小
let remainSize = CGRect(x, y, width, height) // remainSize for titleLabel
// titleEdgeInsets = .zero 时, titleLabel 的 size
let defaultTxtSize = CGSize(width = min(textSize.width, remainSize.width),
                            height = textSize.height)
  1. 根据 button.contentHorizontalAlignmentbutton.contentVerticalAlignment 决定 imageViewtitleLabel 的对齐方式, 确定在 imageEdgeInsets = .zerotitleEdgeInsets = .zero 的情况下的 imageView.frame 以及 titleLabel.frame.
let defaultImgRect = CGRect(x, y, width, height) // imageView.defaultRect
let defaultImgCenter = CGPoint(x, y)
let defaultTxtRect = CGRect(x, y, width, height) // imageView.defaultRect
let defaultTxtCenter = CGPoint(x, y)

这里 defaultImgRect 以及 defaultTxtRectbuttoncontentHorizontalAlignmentcontentVerticalAlignment 来决定:

  1. 将 imageView 与 titleLabel 按照之前算好的大小左右相接,
  2. 将两个控件作为整体按照上述两个属性, 放在 button 的左上角, 左下角, 右对齐什么的, 具体看上述属性的值.

三. 计算加入 imageEdgeInsetstitleEdgeInsets 后的 result 位置

这里 edgeInsets 在这种情况下, 仅对 center 的确定有明确作用. 对 frame 的影响同时需要考虑到 intrinsicContentSizecontentRect, 可以参考下述代码与UIButton的几个 edgeInsets 属性:

// 计算 apply imageEdgeInsets 之后 的 imageView.size
let resultImgSize = CGSize(width = min(imageSize.width, contentRect.width - imageEdgeInsets.left - imageEdgeInsets.right),
                           height = min(imageSize.height, contentRect.height - imageEdgeInsets.top - imageEdgeInsets.bottom))
// 计算 apply titleEdgeInsets 之后 的 titleLabel.size
// titleLabel.height 不会被压缩
let resultTxtSize = CGSize(width = min(textSize.width, remainSize.width - titleEdgeInsets.left - titleEdgeInsets.right), 
                           height = textSize.height) 
// 计算偏移后的 imageView 和 titleLabel 的 center
let resultImgCenter = CGPoint(x = defaultImgCenter.x + (imageEdgeInsets.left-imageEdgeInsets.right)/2, 
                              y = defaultImgCenter.y + (imageEdgeInsets.top-imageEdgeInsets.bottom)/2)
let resultImgCenter = CGPoint(x = defaultImgCenter.x + (titleEdgeInsets.left-titleEdgeInsets.right)/2, 
                              y = defaultImgCenter.y + (titleEdgeInsets.top-titleEdgeInsets.bottom)/2)
// last: 根据 resultSize 和 resultCenter 确定最终 frame
...

以上, 就是对 UIButtonbutton.titleLabelbutton.imageView 的布局方式的观察结果.仅作参考. 如有不妥之处,还请 dalao 批评指正.

相关文章

网友评论

    本文标题:UIButton 布局 imageView 和 titleLab

    本文链接:https://www.haomeiwen.com/subject/igteixtx.html