UIButton 布局 imageView 和 titleLabel 的過(guò)程

UIButton 的布局 imageViewtitleLabel 的過(guò)程

嗶嗶叨: 寫 iOS 代碼也有段時(shí)間了, 但始終不怎么用 systemUIButton, 因?yàn)槊看卧O(shè)置 insets 的時(shí)候都會(huì)卡住好一陣啊! 各種奇怪的偏移. 趁著有時(shí)間, 整理一下.??.

NOTE: 以下皆為偽代碼

假定條件

對(duì)于一個(gè) UIButton 的實(shí)例 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

一. 根據(jù) contentEdgeInsets 確定布局內(nèi)容大小

根據(jù) button.contentEdgeInsetsbutton.frame 計(jì)算出子控件布局范圍 contentRect .

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

二. 計(jì)算 imageViewtitleLabel 的無(wú) edgeinsets 位置

  1. 獲取 image.size 結(jié)合布局范圍 contentRect 的大小得出 imageView 的大小
// imageEdgetInsets = .zero 時(shí), imageView 的 size
let defaultImgSize = CGSize(width = min(imageSize.width, contentRect.width),
                            height = min(imageSize.height, contentRect.height))
  1. 根據(jù) imageViewsize 計(jì)算出在布局范圍 contentRect 內(nèi)剩余的 titleLabel 的布局大小以確定 titleLabel 的布局大小
let remainSize = CGRect(x, y, width, height) // remainSize for titleLabel
// titleEdgeInsets = .zero 時(shí), titleLabel 的 size
let defaultTxtSize = CGSize(width = min(textSize.width, remainSize.width),
                            height = textSize.height)
  1. 根據(jù) button.contentHorizontalAlignmentbutton.contentVerticalAlignment 決定 imageViewtitleLabel 的對(duì)齊方式, 確定在 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 來(lái)決定:

  1. 將 imageView 與 titleLabel 按照之前算好的大小左右相接,
  2. 將兩個(gè)控件作為整體按照上述兩個(gè)屬性, 放在 button 的左上角, 左下角, 右對(duì)齊什么的, 具體看上述屬性的值.

三. 計(jì)算加入 imageEdgeInsetstitleEdgeInsets 后的 result 位置

這里 edgeInsets 在這種情況下, 僅對(duì) center 的確定有明確作用. 對(duì) frame 的影響同時(shí)需要考慮到 intrinsicContentSizecontentRect, 可以參考下述代碼與UIButton的幾個(gè) edgeInsets 屬性:

// 計(jì)算 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))
// 計(jì)算 apply titleEdgeInsets 之后 的 titleLabel.size
// titleLabel.height 不會(huì)被壓縮
let resultTxtSize = CGSize(width = min(textSize.width, remainSize.width - titleEdgeInsets.left - titleEdgeInsets.right), 
                           height = textSize.height) 
// 計(jì)算偏移后的 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: 根據(jù) resultSize 和 resultCenter 確定最終 frame
...

以上, 就是對(duì) UIButton 對(duì) button.titleLabelbutton.imageView 的布局方式的觀察結(jié)果.僅作參考. 如有不妥之處,還請(qǐng) dalao 批評(píng)指正.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容