UIControl是UIView的子类,将用户的触摸事件转换为特殊的控件事件.例如通过UIControl对象处理后,按下按钮的事件就被封装成一个控件事件,而不用去判断触摸屏幕的整个操作过程。
本文将参照系统相机实现一个简单的相机模式的标签切换功能.实现效果如下图:
实现步骤:
创建项目
创建一个名为CameraModel
的Swift项目,新建CameraModeView
类继承自UIControl
,主要代码将在这个文件中编写.
打开Main.storyboard
,在ViewController的View底部添加一个UIView,设置其与父视图的Leading,Trailing,Bottom约束为0,高度约束为110,并修改类名为CameraModeView
.
打开CameraModeView.swift
添加如下代码:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setupView()
}
func setupView() -> Void {
self.backgroundColor = UIColor(white: 0, alpha: 0.5)
}
编译运行程序,可以看到屏幕底部出现了我们所期望的颜色.
添加文本标签
这里我们使用CATextLayer
实现Vedio和Photo两个文本标签,并将这两个CATextLayer放到一个专门的labelContainerView容器中.
在CameraModeView
类中增加下面几个属性:
var labelContainerView:UIView!
var videoTextLayer:CATextLayer!
var photoTextLayer:CATextLayer!
var foregroundColor:UIColor!
并在setupView()
方法中添加下面的代码:
//1. 文本容器
self.labelContainerView = UIView(frame: CGRect(x: 0, y: 0, width: 120, height: 20))
self.addSubview(self.labelContainerView)
//2. 选中态的颜色
self.foregroundColor = UIColor(colorLiteralRed: 1, green: 0.734, blue: 0.006, alpha: 1)
//3. 生成文本
self.videoTextLayer = self.textLayerWithTitle("Vedio")
self.videoTextLayer.frame = CGRect(x: 0, y: 0, width: 60, height: 20)
self.videoTextLayer.foregroundColor = self.foregroundColor.CGColor
self.labelContainerView.layer.addSublayer(self.videoTextLayer)
self.photoTextLayer = self.textLayerWithTitle("Photo")
self.photoTextLayer.frame = CGRect(x: 60, y: 0, width: 60, height: 20)
self.labelContainerView.layer.addSublayer(self.photoTextLayer)
其中textLayerWithTitle()
方法实现如下:
func textLayerWithTitle(title:String) -> CATextLayer {
let layer = CATextLayer()
let font = UIFont(name: "AvenirNextCondensed-DemiBold", size: 17)
layer.font = font?.fontName
layer.fontSize = 17
layer.string = title
layer.alignmentMode = "center"
layer.contentsScale = UIScreen.mainScreen().scale
return layer
}
设置labelContainerView
的显示位置:
override func layoutSubviews() {
super.layoutSubviews()
self.labelContainerView.center.x = self.center.x + 30
self.labelContainerView.frame.origin.y = 8
}
添加表明选中的标记圆点
override func drawRect(rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, self.foregroundColor.CGColor)
let circleRect = CGRect(x: rect.midX - 3, y: 2, width: 6, height: 6)
CGContextFillEllipseInRect(context, circleRect)
}
添加状态属性
首先通过定义一个枚举表明CameraModeView当前的选中状态:
enum CameraModel {
case Photo
case Video
}
在CameraModeView类中增加一个表明状态的属性:
var cameraModel:CameraModel? = .Video{
didSet{
self.sendActionsForControlEvents(.ValueChanged)
}
}
didSet中的代码负责当自身的cameraModel
状态改变时,向外界监听者发送ValueChanged
事件.
添加滑动手势
在setupView()
方法中添加下面的代码:
//4. 增加滑动手势
let right = UISwipeGestureRecognizer(target: self, action: #selector(switchModel(_:)))
let left = UISwipeGestureRecognizer(target: self, action: #selector(switchModel(_:)))
left.direction = .Left
self.addGestureRecognizer(right)
self.addGestureRecognizer(left)
其中switchModel(_:)
方法实现如下:
func switchModel(recognizer:UISwipeGestureRecognizer) -> Void {
//1. 判断手势滑动方向
if recognizer.direction == .Left {
UIView.animateWithDuration(0.28, animations: {
//2. 动画切换文本位置
self.labelContainerView.center.x = self.center.x - 30
}, completion: { (flag) in
//3. 更新状态及展示
if self.cameraModel != .Photo{
self.cameraModel = .Photo
self.photoTextLayer.foregroundColor = self.foregroundColor.CGColor
self.videoTextLayer.foregroundColor = UIColor.whiteColor().CGColor
}
})
}else{
UIView.animateWithDuration(0.28, animations: {
self.labelContainerView.center.x = self.center.x + 30
}, completion: { (flag) in
if self.cameraModel != .Video{
self.cameraModel = .Video
self.videoTextLayer.foregroundColor = self.foregroundColor.CGColor
self.photoTextLayer.foregroundColor = UIColor.whiteColor().CGColor
}
})
}
}
测试
通过@IBAction
在ViewController.swift中监听CameraModeView的ValueChanged方法如下:
@IBAction func cameraModelChanged(sender: CameraModeView) {
print("\(sender.cameraModel)")
}
运行程序,滑动文本标签或CameraModeView的其他位置,观察切换动画及打印信息.