0%

仿系统相机模式标签切换的实现

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的其他位置,观察切换动画及打印信息.