你有没有尝试过在旧版xcode里创建过自定义控件?不是很容易。主要是因为你在Interface Builder(以下简称IB)里看不到实时的效果,每次你要查看修改的效果,只能重新运行,这样很麻烦,你可能要花数小时来设计一个简单的控件。
Xcode6带来了一个新特性:在IB使用IBDesignable和IBInspectable自定义可以实时预览效果的控件。非常明显,将能极大的提升产品开发效率。
在这个教程里,我将给你介绍IBDesignbale和IBInspectable,同时给你们展示如果利用这些特性。没有什么办法可以举个例子更详细了。所以接下来我们一起来打造一个叫“彩虹”的自定义控件。
IBDesignable和IBInsepctable
有了IBDesignable和IBInspectable,开发者们允许在IB中构造实时渲染效果的界面(或视图),一般来讲,要使用这个新特性,你只要创建一个UIView或UIControl的子类,并在类前面加上@IBDesignable关键词(swift),如果你使用的是Object-c,请用IB_DESIGNABLE宏代替,下面是swift的列子:
@IBDesignable
classRainbow: UIView{
}
在老版本xcode中,你可以编辑用户自定义的运行时属性来改变对象的属性(如:layer.conerRadius),麻烦的是你必须在IB中精确的输入同名的属性名称,IBInspectable更加方便,你只要在类属性声明的属性前面加上@IBInspectable,这个属性自动会显示在IB中,不用手工输入,使得改变视图对象的属性更加直观了。如图
再重复一遍,如果你使用的swift开发app,你要做的只是在属性前面加上@IBInspectable,例子
@IBInspectable varfirstColor:UIColor=UIColor.blackColor(){
// Update your UI when value changes
}
还有疑问?别担心,跟着一起做完这个Demo你就完全懂了。
新建一个xcode工程
选择Single View Application模板新建一个工程,命名为RainbowDemo。使用Swift编程语言。
选中Main.storyboard,拖一个View控件到View Controller里,修改背景色为 #38334C(或随便啥颜色),同时设置大小为600x434。同时把整个容器View的背景色改成与刚拖进来的View一样的颜色。
小提示:如何设置RGB颜色?在颜色面板有Color Palette,拖动RGB色条来设置。
同时在xcode6里必须使用自动布局约束来支持各类型的ios设置,自动布局在最新版的xocde里非常的强大,简单的约束,你只要点击自动布局按钮,并选择“Add Missing Contraints”,xcode将自动给视图添加好约束。
创建自定义视图类
新建一个Swift类型的源文件件,命名为 Rainbow,替换为以下代码
importUIKit
classRainbow: UIView{
required init(coder aDecoder:NSCoder){
super.init(coder:aDecoder)
}
override init(frame:CGRect){
super.init(frame:frame)
}
}
就像之前说的,它是一个UIView的子类。为了看到实时效果,我们将窗口分割成两个视图,使用assistant editor
然后在新开的窗口选择Main.storyboard文件,记得修改下你之前拖到UIView视图的控件的类名为Rainbow,这样跟你刚创建的swift源代码是同一个类了。
实现IBDesignable控件
第一步:在类前面加上@IBDesignable前缀,如
@IBDesignable
classRainbow: UIView{
...
}
可以看出来很简单,但这个简单的关键词却使得开发变成更加轻松了。下一步,我们将要添加一些属性,来设置圆的颜色,添加以下类属性
@IBInspectable varfirstColor:UIColor=UIColor(red:(37.0/255.0),green:(252.0/255 ),blue:(244.0/255.0),alpha:1.0)
@IBInspectable varsecondColor:UIColor=UIColor(red:(171.0/255.0),green:(250.0/2 55),blue:(81.0/255.0),alpha:1.0)
@IBInspectable varthirdColor:UIColor=UIColor(red:(238.0/255.0),green:(32.0/255 ),blue:(53.0/255.0),alpha:1.0)
同时也预定义了一些默认颜色,并且当每次修改属性时重绘视图。最重要的是,我们在每个属性前面加上了关键词@IBInspectable,此时你在IB面板上,你将看到这些属性。
Cool吧,有了IBInspector做指示器,你可以在可视化视图里调整属性了。
下面是实现画一个圆的代码
func addOval(lineWidth: CGFloat, path: CGPathRef, strokeStart: CGFloat, strokeEnd: CGFloat, strokeColor: UIColor, fillColor: UIColor, shadowRadius: CGFloat, shadowOpacity: Float, shadowOffsset: CGSize) {
let arc = CAShapeLayer()
arc.lineWidth = lineWidth
arc.path = path
arc.strokeStart = strokeStart
arc.strokeEnd = strokeEnd
arc.strokeColor = strokeColor.CGColor
arc.fillColor = fillColor.CGColor
arc.shadowColor = UIColor.blackColor().CGColor
arc.shadowRadius = shadowRadius
arc.shadowOpacity = shadowOpacity
arc.shadowOffset = shadowOffsset
layer.addSublayer(arc)
}
为了更简洁和可读性,我们创建了一个画出半圆或全圆的方法,主要使用的是CAShapeLayer类,你可以使用strokeStart和strokeEnd来控制起始,调用strokeEnd的范围(0.1至1)你就可以画出一部分圆或全圆出来了。剩下的其它代码是设置颜色和线条、阴影颜色等。你可以点此此处查看CAShapeLayer的所有属性。
下面添加其它具体实现代码
override func drawRect(rect: CGRect) {
// Add ARCs
self.addCirle(80, capRadius: 20, color: self.firstColor)
self.addCirle(150, capRadius: 20, color: self.secondColor)
self.addCirle(215, capRadius: 20, color: self.thirdColor)
}
func addCirle(arcRadius: CGFloat, capRadius: CGFloat, color: UIColor) {
let X = CGRectGetMidX(self.bounds)
let Y = CGRectGetMidY(self.bounds)
// Bottom Oval
let pathBottom = UIBezierPath(ovalInRect: CGRectMake((X - (arcRadius/2)), (Y - (arcRadius/2)), arcRadius, arcRadius)).CGPath
self.addOval(20.0, path: pathBottom, strokeStart: 0, strokeEnd: 0.5, strokeColor: color, fillColor: UIColor.clearColor(), shadowRadius: 0, shadowOpacity: 0, shadowOffsset: CGSizeZero)
// Middle Cap
let pathMiddle = UIBezierPath(ovalInRect: CGRectMake((X - (capRadius/2)) - (arcRadius/2), (Y - (capRadius/2)), capRadius, capRadius)).CGPath
self.addOval(0.0, path: pathMiddle, strokeStart: 0, strokeEnd: 1.0, strokeColor: color, fillColor: color, shadowRadius: 5.0, shadowOpacity: 0.5, shadowOffsset: CGSizeZero)
// Top Oval
let pathTop = UIBezierPath(ovalInRect: CGRectMake((X - (arcRadius/2)), (Y - (arcRadius/2)), arcRadius, arcRadius)).CGPath
self.addOval(20.0, path: pathTop, strokeStart: 0.5, strokeEnd: 1.0, strokeColor: color, fillColor: UIColor.clearColor(), shadowRadius: 0, shadowOpacity: 0, shadowOffsset: CGSizeZero)
}
默认的drawRect什么也没做,为了在UIView上画一个圆,必须自己实现drawRect方法,addCircle()方法需要三个参数:arcRadius, capRadius 和 color。arcRadius是圆的半径,capRadius是彩虹上面小圆盖的半径。
addCircle()使用了UIBezierPath(贝塞尔曲线)来画弧,流程是:
- 先在下面画半个圆
- 在圆的边缘画个小盖子
- 画完上面的半个圆
在drawRect方法里,我们使用不同的颜色和半径调用了addCircle三次,下图展示了依次的效果
提示:如果你想进一上了解UIBezierPath,请点击
有了IBInspectable属性你可以自由的在IB里控制样式而不必一头扎进代码里了。
总结
做完这个练习,希望你能掌握xcode6的IBDesignable和IBInspectable使用。有了这个Interface Builder的实时效果,将提供给你一个更加有效率的自定义组件的方法。
翻译:朱淦 350050183@qq.com 2016.7.20