基于 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
相关文章
相关标签/搜索