基於 UIControl 打造一個 Button

首發於公衆號git

UIKit 提供的 UIButton 在普通場景下已經很好用了,可是也有缺點,就是定製能力不強,開發者每每須要子類化定製本身的風格才能知足 UI 的需求。github

UI 對於 Button 有如下幾個需求:swift

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

不只如此,還要求圖片和文字之間還要求有必定的間隔。佈局

系統的 UIButton 默認狀況下只能支持第 1 種場景,其餘狀況都須要本身定製化,然而基於 UIButton 定製也有一些麻煩要處理,好比在自動佈局機制下能自適應大小,並且對於上面列舉的場景來講,僅僅只有顯示風格不同而已,UIButton 要是有一個接口直接設置風格就方便多了。spa

基於以上分析,我決定基於 UIControl 來從新實現一個 Button,基本使用接口保持和 UIButton 一致,並且支持定製佈局風格,只須要簡單設置一個參數就好了。code

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

public enum SFButtonDirection: Int {
    case row
    case rowReverse
    case column
    case columnReverse
}
複製代碼

橫向的排列叫 row,豎向的排列叫 column,分別對應以前提到的 4 種場景:cdn

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

圖片和文字之間還要能設置間距,再增長一個屬性:space。blog

有時候 UI 要求 Button 的大小須要由內容來決定,並且上下左右還要有必定的間距,知足這個場景只須要再增長一個屬性:contentInset。接口

有了以上 3 個關鍵屬性,就能夠知足大多數的應用場景了,並且使用起來也很是簡單: 建立一個 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)
複製代碼

如下是運行效果,完整實現代碼請到個人 github: SFButton

img

img
相關文章
相關標籤/搜索