iOS tutorial 8:使用IBInspectable 和 IBDesignable定制UI

参考:appcode网站的书《Intermediate iOS Programming with Swift》 的Chapter 36

例子代码:https://github.com/andyRon/LearniOSByProject/tree/master/P077-FancyButton

理解IBInspectable 和 IBDesignable

简单地说,IBInspectable 就是允许开发者在IB的属性检查器中添加额外的选项。IBDesignable 能够让* IBInspectable* 添加的额外选项产生的变化在IB中实时显示。以Button的圆角为例说明。

  • 正常情况下,Button的圆角需要代码:
button.layer.cornerRadius = 10.0
button.layer.masksToBounds = true

或者直接在IB的Identity检查器user defined runtime attributes中添加:

注意到,这种修改不是实时,在IB中Button还是直角,只有运行后才是圆角。

  • IBInspectable的方式。定义个继承至UIButton的类。
class RoundedCornerButton: UIButton {
    @IBInspectable var cornerRadius: CGFloat = 0.0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
}

然后把button的class属性修改成RoundedCornerButton:

发现这个button的属性检查器中多了Corner Radius

注意: cornerRadius属性变成了Corner RadiusRoundedCornerButton类变成了 Rounded Corner Button,这是Xcode自动转变的,开发者只需要依照swift的命名规范就可以了(类名是大写开头的驼峰命名规则,属性名是小写开头的驼峰命名规则)

cornerRadius的类型是CGFloat,在属性检查器中就对应数字的选择。当然不是所有类型都可以添加属性检查器中的,IBInspectable支持如下类型:

Int
CGFloat 
Double 
String 
Bool 
CGPoint 
CGSize 
CGRect 
UIColor 
UIImage

如果在类RoundedCornerButton前添加@IBDesignable,那在属性检查器中自定义的属性变化就可以在IB中实时显示了。

@IBDesignable class RoundedCornerButton: UIButton {
    @IBInspectable 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
      @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继续添加属性:
      @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
    添加图片边距的属性:
      @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中添加如下代码:

  @IBInspectable var 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:
      @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)
          }
      }
    

渐变色需要运行后才能看到

本文标题: iOS tutorial 8:使用IBInspectable 和 IBDesignable定制UI
本文作者: AndyRon
本文链接: http://andyron.com/2017/ios-tutorial-8-ibinspectable-ibdesignable.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!

推荐阅读更多精彩内容