關(guān)于 UIButton 的 titleEdgeInsets、imageEdgeInsets 及 contentEdgeInsets

??2019-10-20

不管是什么應(yīng)用 UIButton 在項(xiàng)目中的使用都是必不可少的,很多時(shí)候我們會(huì)同時(shí)給 UIButton 添加上 imagetitle 以及在 imagetitle 間留一些間距, 再有時(shí)候可能還希望其左邊或者是右邊留有有一些間距,這樣 UI 顯得更加美觀??赡艿牟季挚雌饋?lái)像這樣:

UIButton默認(rèn)樣式

image 與 title 有間距

image 與 title 有間距 + 左側(cè)間距

image 與 title上下布局 + 中間間距 + 四周邊距

盡管這看起來(lái)很容易實(shí)現(xiàn),只要合理的設(shè)置 UIButtontitleEdgeInsetsimageEdgeInsets、contentEdgeInsets 等屬性就可以實(shí)現(xiàn)這些效果,但是不得不說(shuō)還是有很多開發(fā)者不確定如何控制這幾個(gè)屬性,而導(dǎo)致項(xiàng)目相關(guān)的地方出現(xiàn)了一些問(wèn)題,所以接下來(lái)增對(duì)個(gè)人的理解對(duì)這幾個(gè)屬性的設(shè)置進(jìn)行一些說(shuō)明。

UIButton 中 imageView 與 titleLabel 的布局

UIButton 的內(nèi)部布局中假設(shè)有個(gè)參考線imageViewtitleLabel 的布局均以該參考線為參照左右上下進(jìn)行偏移,最終實(shí)現(xiàn)在 imagetitle 間添加間距 imageTextSpacing 的布局。(注意這里的參考線很重要)

實(shí)現(xiàn)效果

開始舉例前的初始代碼如下:

let button = UIButton()
var titleInsets = button.titleEdgeInsets
var imageInsets = button.imageEdgeInsets
var contentInsets = button.contentEdgeInsets
var buttonSize = button.sizeThatFits(CGSize.zero)
let imageTextSpacing: CGFloat = 0    // image 與 title 的間距
let titleSize = button.titleLabel!.sizeThatFits(CGSize.zero)
let imageSize = button.imageView!.sizeThatFits(CGSize.zero)

func reset() {
    titleInsets = button.titleEdgeInsets
    imageInsets = button.imageEdgeInsets
    contentInsets = button.contentEdgeInsets
    buttonSize = button.sizeThatFits(CGSize.zero)
}


一、 左 imagetitle 的布局

  1. imagetitle → 居中對(duì)齊 (默認(rèn)), 參考線為中線 ━━┇━━

    布局實(shí)現(xiàn):在當(dāng)前布局上以中線為參考線那么需將 image 左移 imageTextSpacing / 2, title 右移 imageTextSpacing / 2, buttonSize.width 增加 imageTextSpacing 即可

    example(of: "(左 image 右 title) → 居中對(duì)齊 (默認(rèn)) + 間距") {
        imageInsets.left = -imageTextSpacing / 2.0
        imageInsets.right = imageTextSpacing / 2.0
        titleInsets.left = imageTextSpacing / 2.0
        titleInsets.right = -imageTextSpacing / 2.0
    
        buttonSize.width += imageTextSpacing
    }      
    


  1. imagetitle → 左對(duì)齊, 參考線在左側(cè) ┇━━━━

    在當(dāng)前布局上 image 由于默認(rèn)就是貼近左側(cè)線所以保持不變,title 右移 imageTextSpacing,buttonSize.width 增加 imageTextSpacing 即可

    example(of: "(左 image 右 title) → 左對(duì)齊 + 間距") {
        button.contentHorizontalAlignment = .left
    
        titleInsets.left = imageTextSpacing
        titleInsets.right = -imageTextSpacing
        imageInsets = UIEdgeInsets.zero
    
        buttonSize.width += imageTextSpacing
    }
    
    


  1. imagetitle → 右對(duì)齊, 參考線在右側(cè) ┇━━━━

    在當(dāng)前布局上 title 由于默認(rèn)就是貼近右側(cè)所以保持不變,image 左移 imageTextSpacing,buttonSize.width 增加 imageTextSpacing 即可

    example(of: "(左 image 右 title) → 右對(duì)齊 + 間距") {
        button.contentHorizontalAlignment = .right
    
        titleInsets = UIEdgeInsets.zero
        imageInsets.left = -imageTextSpacing
        imageInsets.right = imageTextSpacing
    
        buttonSize.width += imageTextSpacing
    }    
    


二、 左 titleimage 的布局

首先需要實(shí)現(xiàn)的是左邊 title 右邊 image的布局, 然后再添加間距

  1. titleimage → 居中對(duì)齊 (默認(rèn)) + 無(wú)間距

    在初始布局上將 title 左移 imageSize.widthimage 右移 titleSize.width 即可達(dá)到效果

    example(of: "左 title 右 image → 居中對(duì)齊 (默認(rèn)) + 無(wú)間距") {
        titleInsets.left = -imageSize.width
        titleInsets.right = imageSize.width
        imageInsets.left = titleSize.width
        imageInsets.right = titleSize.width
    }
    
左 title 右 image → 居中對(duì)齊 (默認(rèn)) + 無(wú)間距


  1. titleimage → 居中對(duì)齊 (默認(rèn)) + 間距, 參考線在中間 ━━┇━━

    在左 titleimage 基礎(chǔ)上,title 左移 imageTextSpacing / 2.0, image 右移 imageTextSpacing / 2.0,buttonSize.width 增加 imageTextSpacing 即可

    example(of: "(左 title 右 image) → 居中對(duì)齊 (默認(rèn)) + 間距") {
        titleInsets.left -= imageTextSpacing / 2.0
        titleInsets.right += imageTextSpacing / 2.0
        imageInsets.left += imageTextSpacing / 2.0
        imageInsets.right -= imageTextSpacing / 2.0
    }
    
(左 title 右 image) → 居中對(duì)齊 (默認(rèn)) + 間距


  1. titleimage → 左對(duì)齊 + 間距, 參考線在左側(cè) ┇━━━━

    在左 titleimage 基礎(chǔ)上,title 貼近左側(cè)所以保持不變, image 右移 imageTextSpacing,buttonSize.width 增加 imageTextSpacing 即可,效果圖與之前相同

    example(of: "(左 title 右 image) → 左對(duì)齊 + 間距") {
        imageInsets.left += imageTextSpacing
        imageInsets.right -= imageTextSpacing
    
        buttonSize.width += imageTextSpacing
    }
    


  1. titleimage → 右對(duì)齊 + 間距, 參考線在右側(cè) ━━━━┇

    在左 titleimage 基礎(chǔ)上,image 貼近右側(cè)所以保持不變, title 左移 imageTextSpacing,buttonSize.width 增加 imageTextSpacing 即可,效果圖與之前相同

    example(of: "(左 title 右 image) → 右對(duì)齊 + 間距") {
        titleInsets.left -= imageTextSpacing
        titleInsets.right += imageTextSpacing
    
        buttonSize.width += imageTextSpacing
    }
    


三、上 imagetitle

首先需要實(shí)現(xiàn)的是上 imagetitle 的布局,然后再添加間距。

  1. imagetitle → 居中對(duì)齊 (默認(rèn)), 參考線在橫中線 ━╋━

    再初始布局的基礎(chǔ)上首先需要將 image 右移 titleSize.width / 2,title 左移 imageSize.width 實(shí)現(xiàn)左右居中,因?yàn)槭巧舷虏季謪⒖季€為中間的橫線,所以需將 image 上移 titleSize.height / 2, title 下移 imageSize.height / 2 實(shí)現(xiàn)上下居中,修改高度為 titleSize.height + imageSize.height 最終達(dá)到目的。

    reset()
    example(of: "(上 image 下 title)→ 居中對(duì)齊 (默認(rèn)) + 無(wú)間距") {
    
        let titleHOffset = imageSize.width / 2.0
        let imageHOffset = titleSize.width / 2.0
        let titleVOffset = imageSize.height / 2.0
        let imageVOffset = titleSize.height / 2.0
    
        titleInsets = UIEdgeInsets(top: titleVOffset, left: -titleHOffset, bottom: -titleVOffset, right: titleHOffset)
        imageInsets = UIEdgeInsets(top: -imageVOffset, left: imageHOffset, bottom: imageVOffset, right: -imageHOffset)
    
        buttonSize.height = imageSize.height + titleSize.height
    }
    
上 image 下 title
  1. imagetitle → 居中對(duì)齊 (默認(rèn)) + 間距, 參考線在橫中線 ━╋━

    在當(dāng)前布局基礎(chǔ)上將 image 上移 mageTextSpacing / 2,title 下移 mageTextSpacing / 2, buttonSize.height 增加 imageTextSpacing 即可

    example(of: "(上 image 下 title) → 居中對(duì)齊 (默認(rèn)) + 間距") {
        imageInsets.top -= imageTextSpacing / 2.0
        imageInsets.bottom += imageTextSpacing / 2.0
        titleInsets.top += imageTextSpacing / 2.0
        titleInsets.bottom -= imageTextSpacing / 2.0
    
        buttonSize.height += imageTextSpacing
    }
    
(上 image 下 title) → 居中對(duì)齊 (默認(rèn)) + 間距
  1. imagetitle → 上對(duì)齊 + 間距, 參考線在頂部橫線 ┳

    由于是頂部對(duì)齊所以默認(rèn) imagetitle 都是貼近頂部,所以設(shè)置 image 距離頂部在0, title 在當(dāng)前布局基礎(chǔ)上下移 imageSize.height 實(shí)現(xiàn)上(image 下 title) ,然后再將 title 下移 imageTextSpacing 實(shí)現(xiàn)間距,最后 設(shè)置 buttonSize.heightimageSize.height + titleSize.height + imageTextSpacing 即可。效果圖與之前相同

    example(of: "(上 image 下 title) → 上對(duì)齊 + 間距") {
    
        button.contentVerticalAlignment = .top
    
        imageInsets.top = 0
        imageInsets.bottom = 0
        titleInsets.top = imageSize.height
        titleInsets.bottom = -imageSize.height
    
        titleInsets.top += imageTextSpacing
        titleInsets.bottom -= imageTextSpacing
    
        buttonSize.height = imageSize.height + titleSize.height + imageTextSpacing
    }
    
  2. imagetitle → 下對(duì)齊 + 間距, 參考線在底部橫線 ┻

    由于是底部對(duì)齊所以默認(rèn) imagetitle 都是貼近底部,所以設(shè)置 title 距離底部在0, image 在當(dāng)前布局基礎(chǔ)上上移 titleSize.height 實(shí)現(xiàn)上(image 下 title) ,然后再將 image 上移 imageTextSpacing 實(shí)現(xiàn)間距,最后 設(shè)置 buttonSize.heightimageSize.height + titleSize.height + imageTextSpacing 即可, 效果圖與之前相同

    example(of: "(上 image 下 title) → 上對(duì)齊 + 間距") {
    
        button.contentVerticalAlignment = .top
    
        titleInsets.top = 0
        titleInsets.bottom = 0
        imageInsets.top = -titleSize.height
        imageInsets.bottom = titleSize.height
    
        imageInsets.top -= imageTextSpacing
        imageInsets.bottom += imageTextSpacing
    
        buttonSize.height = imageSize.height + titleSize.height + imageTextSpacing
    }
    


四、上下左右的邊距

到目前為止我們僅僅是在不同的布局條件下增加了 imagetitle 的間距,那么我們?nèi)绻诖嘶A(chǔ)上還需要設(shè)置 上下左右的邊距 該怎么處理呢,這里我們只需要調(diào)整之前一直沒提到的 contentEdgeInsets 屬性就可以了。這里通過(guò)設(shè)置 contentEdgeInsetsUIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) 效果如下:

image 與 title 間距 + 四周邊距

對(duì)以上進(jìn)行小結(jié)

  • 我們應(yīng)該始終保持 titleEdgeInsets、 imageEdgeInsets 中的 leftright 同時(shí)設(shè)置,或者是 topbottom 同時(shí)設(shè)置,而且是一正一負(fù),left+, right 就為 -top+, bottom 就為 -,反過(guò)來(lái)亦之。

  • 應(yīng)該始終以參考線為基準(zhǔn)進(jìn)行變偏移,如果是 居中對(duì)齊 那么參考線就是 水平方向的中線 或者是 垂直方向的中線, 如果對(duì)齊方向是 左右上下對(duì)齊 中的一個(gè),那么參考線就是對(duì)應(yīng) 左右上下 的一側(cè)。

  • 從上面的例子里可以看出,對(duì) titleEdgeInsets、 imageEdgeInsets 的調(diào)整不會(huì)影響 UIButtonsize,所以在例子中我們需要調(diào)整其 size 到合適。但是對(duì) contentEdgeInsets 的調(diào)整會(huì)影響 UIButtonsize,也正因?yàn)槿绱宋覀儾趴梢酝ㄟ^(guò) contentEdgeInsets 來(lái)設(shè)置 左右上下 某一側(cè)的邊距。

最后

示例代碼中 UIButton 在初始化的時(shí)候 size 使用約束進(jìn)行了固定,以及 UIButtonImageViewtitleLabelsize 也是進(jìn)過(guò)測(cè)量后寫死了,在真正項(xiàng)目應(yīng)用中應(yīng)該通過(guò)以下的方法來(lái)獲取正確的 size。

    let textSize = previewButton.titleLabel?.sizeThatFits(CGSize.zero)
    let imageSize = previewButton.imageView?.sizeThatFits(CGSize.zero)


示例代碼 xcode11.2

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 各種純css圖標(biāo) CSS3可以實(shí)現(xiàn)很多漂亮的圖形,我收集了32種圖形,在下面列出。直接用CSS3畫出這些圖形,要比...
    劍殘閱讀 9,977評(píng)論 0 8
  • 學(xué)習(xí)CSS的最佳網(wǎng)站沒有之一 http://www.w3school.com.cn/tags/index.asp ...
    Amyyy_閱讀 1,172評(píng)論 0 1
  • 一、CSS入門 1、css選擇器 選擇器的作用是“用于確定(選定)要進(jìn)行樣式設(shè)定的標(biāo)簽(元素)”。 有若干種形式的...
    寵辱不驚丶?xì)q月靜好閱讀 1,708評(píng)論 0 6
  • 供需定理:8月25日 成本決定價(jià)格?你太天真了 經(jīng)濟(jì)學(xué)告訴我們,產(chǎn)品有價(jià),不是因?yàn)橹圃飚a(chǎn)品有成本,而是因?yàn)槭袌?chǎng)對(duì)產(chǎn)...
    一一休閱讀 845評(píng)論 0 0
  • 一直覺得,雨聲有讓世界變小的魔力。 車輪軸在雨中閃出光,夏夜蓊蓊郁郁的行道樹向前延伸,一派陰郁幽深。暗淡天光下,風(fēng)...
    顥川的臨世之窗閱讀 166評(píng)論 0 0

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