基于 UIControl 打造一個 Button

首發(fā)于公眾號

UIKit 提供的 UIButton 在普通場景下已經(jīng)很好用了,但是也有缺點(diǎn),就是定制能力不強(qiáng),開發(fā)者往往需要子類化定制自己的風(fēng)格才能滿足 UI 的需求。

UI 對于 Button 有以下幾個需求:

  1. 左邊圖片,右邊文字
  2. 左邊文字,右邊圖片
  3. 上面圖片,下面文字
  4. 上面文字,下面圖片

不僅如此,還要求圖片和文字之間還要求有一定的間隔。

系統(tǒng)的 UIButton 默認(rèn)情況下只能支持第 1 種場景,其他情況都需要自己定制化,然而基于 UIButton 定制也有一些麻煩要處理,比如在自動布局機(jī)制下能自適應(yīng)大小,而且對于上面列舉的場景來說,僅僅只有顯示風(fēng)格不一樣而已,UIButton 要是有一個接口直接設(shè)置風(fēng)格就方便多了。

基于以上分析,我決定基于 UIControl 來重新實(shí)現(xiàn)一個 Button,基本使用接口保持和 UIButton 一致,而且支持定制布局風(fēng)格,只需要簡單設(shè)置一個參數(shù)就行了。

圖片和文字的排列組合一共有 4 種,兩種橫行排列,兩種豎向排列,通過一個枚舉類型定義如下:

public enum SFButtonDirection: Int {
    case row
    case rowReverse
    case column
    case columnReverse
}

橫向的排列叫 row,豎向的排列叫 column,分別對應(yīng)之前提到的 4 種場景:

  1. 左邊圖片,右邊文字 (row)
  2. 左邊文字,右邊圖片 (rowReverse)
  3. 上面圖片,下面文字 (column)
  4. 上面文字,下面圖片 (columnReverse)

圖片和文字之間還要能設(shè)置間距,再增加一個屬性:space。

有時候 UI 要求 Button 的大小需要由內(nèi)容來決定,而且上下左右還要有一定的間距,滿足這個場景只需要再增加一個屬性:contentInset。

有了以上 3 個關(guān)鍵屬性,就可以滿足大多數(shù)的應(yīng)用場景了,而且使用起來也非常簡單:
創(chuàng)建一個 Button

func makeButton() -> SFButton {
    let btnNormalBGImage = UIImage(named: "button_normal")!.resizableImage(withCapInsets: UIEdgeInsets(top: 15, left: 15, bottom: 15, right: 15))
    let btnHighlightedBGImage = UIImage(named: "button_highlighted")!.resizableImage(withCapInsets: UIEdgeInsets(top: 15, left: 15, bottom: 15, right: 15))

    let button = SFButton(frame: .zero)
    button.setImage(UIImage(named: "icon-test"), for: .normal)
    button.setBackgroundImage(btnNormalBGImage, for: .normal)
    button.setBackgroundImage(btnHighlightedBGImage, for: .highlighted)

    return button
}
  • 圖片左,文字右
let button = makeButton()
button.space = 10
button.contentInset = UIEdgeInsets(top: 10, left: 5, bottom: 10, right: 5)
button.setTitle("direction: row", for: .normal)
  • 文字左,圖片右
let button2 = makeButton()
button2.space = 10
button2.contentInset = UIEdgeInsets(top: 10, left: 5, bottom: 10, right: 5)
button2.direction = .rowReverse
button2.setTitle("direction: rowReverse", for: .normal)
  • 圖片上,文字下
let button3 = makeButton()
button3.space = 5
button3.contentInset = UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10)
button3.direction = .column
button3.setTitle("direction: column", for: .normal)
  • 文字上,圖片下
let button4 = makeButton()
button4.space = 5
button4.contentInset = UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10)
button4.direction = .columnReverse
button4.setTitle("direction: columnReverse", for: .normal)

以下是運(yùn)行效果,完整實(shí)現(xiàn)代碼請到我的 github:
SFButton

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

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