例子代码:https://github.com/andyRon/LearniOSByProject/tree/master/P077-FancyButton
理解IBInspectable 和 IBDesignable
简单地说,IBInspectable 就是允许开发者在IB的属性检查器中添加额外的选项。IBDesignable 能够让 IBInspectable 添加的额外选项产生的变化在IB中实时显示。以Button的圆角为例说明。
- 正常情况下,Button的圆角需要代码:
1
2button.layer.cornerRadius = 10.0
button.layer.masksToBounds = true
或者直接在IB的Identity检查器的 user defined runtime attributes中添加:
注意到,这种修改不是实时,在IB中Button还是直角,只有运行后才是圆角。
- 以IBInspectable的方式。定义个继承至
UIButton
的类。1
2
3
4
5
6
7
8class RoundedCornerButton: UIButton {
@IBInspectable var cornerRadius: CGFloat = 0.0 {
didSet {
layer.cornerRadius = cornerRadius
layer.masksToBounds = cornerRadius > 0
}
}
}
然后把button的class
属性修改成RoundedCornerButton
:
发现这个button的属性检查器中多了Corner Radius。
注意:
cornerRadius
属性变成了Corner Radius,RoundedCornerButton
类变成了 Rounded Corner Button,这是Xcode自动转变的,开发者只需要依照swift的命名规范就可以了(类名是大写开头的驼峰命名规则,属性名是小写开头的驼峰命名规则)
cornerRadius
的类型是CGFloat
,在属性检查器中就对应数字的选择。当然不是所有类型都可以添加属性检查器中的,IBInspectable支持如下类型:1
2
3
4
5
6
7
8
9
10Int
CGFloat
Double
String
Bool
CGPoint
CGSize
CGRect
UIColor
UIImage
如果在类RoundedCornerButton
前添加@IBDesignable
,那在属性检查器中自定义的属性变化就可以在IB中实时显示了。1
2
3
4
5
6
7
8class RoundedCornerButton: UIButton {
var cornerRadius: CGFloat = 0.0 {
didSet {
layer.cornerRadius = cornerRadius
layer.masksToBounds = cornerRadius > 0
}
}
}
创建Fancy Button
创建Fancy Button来更加深入的了解IBInspectable 和 IBDesignable
- 创建新项目FancyButton
- 下载图标,也可以随意图标,拖进asset catalog
- 新建类
FancyButton
,继承至UIButton
- 圆角,边宽,边的颜色。 更新
FancyButton
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19@IBDesignable
class FancyButton: UIButton {
@IBInspectable var cornerRadius: CGFloat = 0.0 {
didSet {
layer.cornerRadius = cornerRadius
layer.masksToBounds = cornerRadius > 0
}
}
@IBInspectable var borderWidth: CGFloat = 0.0 {
didSet {
layer.borderWidth = borderWidth
}
}
@IBInspectable var borderColor: UIColor = .black {
didSet {
layer.borderColor = borderColor.cgColor
}
}
}
- Title
在FancyButton
继续添加属性:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20@IBInspectable var titleLeftPadding: CGFloat = 0.0 {
didSet {
titleEdgeInsets.left = titleLeftPadding
}
}
@IBInspectable var titleRightPadding: CGFloat = 0.0 {
didSet {
titleEdgeInsets.right = titleRightPadding
}
}
@IBInspectable var titleTopPadding: CGFloat = 0.0 {
didSet {
titleEdgeInsets.top = titleTopPadding
}
}
@IBInspectable var titleBottomPadding: CGFloat = 0.0 {
didSet {
titleEdgeInsets.bottom = titleBottomPadding
}
}
- 通过圆角可创建圆形button
- Image Padding
添加图片边距的属性:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21@IBInspectable var imageLeftPadding: CGFloat = 0.0 {
didSet {
imageEdgeInsets.left = imageLeftPadding
}
}
@IBInspectable var imageRightPadding: CGFloat = 0.0 {
didSet {
imageEdgeInsets.right = imageRightPadding
}
}
@IBInspectable var imageTopPadding: CGFloat = 0.0 {
didSet {
imageEdgeInsets.top = imageTopPadding
}
}
@IBInspectable var imageBottomPadding: CGFloat = 0.0 {
didSet {
imageEdgeInsets.bottom = imageBottomPadding
}
}
- 图片靠右对齐
根据下图关系,应有imageEdgeInsets.left = self.bounds.width - imageView.bounds.width - imageRightPadding
。
在FancyButton
中添加如下代码:
1
2
3
4
5
6
7
8
9var enableImageRightAligned: Bool = false
override func layoutSubviews() {
super.layoutSubviews()
if enableImageRightAligned, let imageView = imageView {
imageEdgeInsets.left = self.bounds.width - imageView.bounds.width - imageRightPadding
}
}
+ `enableImageRightAligned`属性又来自动计算 `imageEdgeInsets.left`
- 颜色渐变
添加三个@IBInspectable
属性,并更新layoutSubviews
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20@IBInspectable var enableGradientBackground: Bool = false
@IBInspectable var gradientColor1: UIColor = UIColor.black
@IBInspectable var gradientColor2: UIColor = UIColor.white
override func layoutSubviews() {
super.layoutSubviews()
if enableImageRightAligned, let imageView = imageView {
imageEdgeInsets.left = self.bounds.width - imageView.bounds.width - imageRightPadding
}
if enableGradientBackground {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = self.bounds
gradientLayer.colors = [gradientColor1.cgColor, gradientColor2.cgColor]
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
self.layer.insertSublayer(gradientLayer, at: 0)
}
}
渐变色需要运行后才能看到
参考:appcode网站的书《Intermediate iOS Programming with Swift》 的Chapter 36