iOS自定义控件二
发布日期:2022-03-18 08:27:41 浏览次数:28 分类:技术文章

本文共 10986 字,大约阅读时间需要 36 分钟。

iOS自定义控件二

Drawing with Layers

本文内容,来自

本例子是使用Layer来创建一个RingLayer,最终的效果如下:

RingLayer

大致思路是:

1.后面的灰色背景backgroundLayer

backgroundLayer

2.前面的foregroundLayerforegroundLayer上添加一个gradientLayer,相当于是一个渐变的layer。

foregroundLayer

3.给foregroundLayer设置Mask为foregroundMaskforegroundMaskCAShapeLayer

设置Mask后

4.旋转gradientLayer

旋转gradientLayer

5.如上图,渐变开始的部分还有突变,在foregroundLayer,再添加上一个ringTipLayer

ringTipLayer

6.旋转ringTipLayer

ringTipLayer

RingLayer的代码如下:

public class RingLayer : CALayer {    private let angleOffsetForZero = CGFloat(-M_PI_2)    private lazy var gradientLayer : CircularGradientLayer = {        let gradLayer = CircularGradientLayer()        gradLayer.colors = self.ringColors        return gradLayer    }()    private lazy var backgroundLayer : CAShapeLayer = {        let layer = CAShapeLayer()        layer.strokeColor = self.ringBackgroundColor        layer.lineWidth = self.ringWidth        layer.fillColor = nil        return layer    }()    private lazy var foregroundLayer : CALayer = {        let layer = CALayer()        layer.addSublayer(self.gradientLayer)        layer.addSublayer(self.ringTipLayer)        layer.mask = self.foregroundMask        return layer    }()    private lazy var ringTipLayer : CAShapeLayer = {        let layer = CAShapeLayer()        layer.strokeColor = self.ringColors.0        layer.lineWidth = self.ringWidth        layer.fillColor = nil        layer.lineCap = kCALineCapRound        return layer    }()    //mask遮罩    private lazy var foregroundMask : CAShapeLayer = {        let layer = CAShapeLayer()        layer.strokeColor = UIColor.blackColor().CGColor        layer.fillColor = UIColor.clearColor().CGColor        layer.lineWidth = self.ringWidth        layer.lineCap = kCALineCapRound        return layer    }()    //:- Public API    var ringWidth: CGFloat = 40.0 {        didSet {            backgroundLayer.lineWidth = ringWidth            ringTipLayer.lineWidth = ringWidth            foregroundMask.lineWidth = ringWidth            preparePaths()        }    }    var value: CGFloat = 0.0 {        didSet {            preparePaths()            //旋转            ringTipLayer.setValue(angleForValue(value), forKeyPath: "transform.rotation.z")            gradientLayer.setValue(angleForValue(value), forKeyPath: "transform.rotation.z")        }    }    //颜色    var ringColors: (CGColorRef, CGColorRef) = (UIColor.redColor().CGColor, UIColor.redColor().darkerColor.CGColor) {        didSet {            gradientLayer.colors = ringColors            ringTipLayer.strokeColor = ringColors.0        }    }    var ringBackgroundColor: CGColorRef = UIColor.darkGrayColor().CGColor {        didSet {            backgroundLayer.strokeColor = ringBackgroundColor        }    }    //:- Initialisation    public override init() {        super.init()        sharedInitialization()    }    required public init?(coder aDecoder: NSCoder) {        super.init(coder: aDecoder)        sharedInitialization()    }}extension RingLayer {    private func sharedInitialization() {        backgroundColor = UIColor.blackColor().CGColor        //添加sublayer        [backgroundLayer, foregroundLayer].forEach { self.addSublayer($0) }        self.value = 0.8    }    //重写方法    public override func layoutSublayers() {        super.layoutSublayers()        if backgroundLayer.bounds != bounds {            for layer in [backgroundLayer, foregroundLayer, foregroundMask, gradientLayer, ringTipLayer] {                layer.bounds = bounds                layer.position = center            }            preparePaths()        }    }}extension RingLayer {    //半径    private var radius : CGFloat {        return (min(bounds.width, bounds.height) - ringWidth) / 2.0    }    //路径    private func preparePaths() {        backgroundLayer.path = backgroundPath        foregroundMask.path = maskPathForValue(value)        ringTipLayer.path = UIBezierPath(arcCenter: center, radius: radius, startAngle: -0.01, endAngle: 0, clockwise: true).CGPath    }    private var backgroundPath : CGPathRef {        return UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: 2 * CGFloat(M_PI), clockwise: true).CGPath    }    private func maskPathForValue(value: CGFloat) -> CGPathRef {        return UIBezierPath(arcCenter: center, radius: radius, startAngle: angleOffsetForZero, endAngle: angleForValue(value), clockwise: true).CGPath    }    //value对应角度    private func angleForValue(value: CGFloat) -> CGFloat {        return value * 2 * CGFloat(M_PI) + angleOffsetForZero    }}

Advanced Layers

内容来自

创建RingTipRingTip是一个带有阴影的layer

大致思路如下:
1.tipLayer是个CAShapeLayer
tipLayer

2.添加shadowLayer,阴影layer

shadowLayer

3.给shadowLayer设置遮罩shadowMaskLayer

shadowMaskLayer

RingTip的完整代码如下:

import UIKitpublic class RingTip : CALayer {    //MARK:- Constituent Layers    private lazy var tipLayer : CAShapeLayer = {        let layer = CAShapeLayer()        layer.lineCap = kCALineCapRound        layer.lineWidth = self.ringWidth        return layer    }()    private lazy var shadowLayer : CAShapeLayer = {        let layer = CAShapeLayer()        layer.lineCap = kCALineCapRound        layer.lineWidth = self.ringWidth        layer.strokeColor = UIColor.blackColor().CGColor        layer.shadowColor = UIColor.blackColor().CGColor        layer.shadowOffset = .zero        layer.shadowRadius = 12.0        layer.shadowOpacity = 1.0        layer.mask = self.shadowMaskLayer        return layer    }()    private lazy var shadowMaskLayer : CAShapeLayer = {        let layer = CAShapeLayer()        layer.strokeColor = UIColor.blackColor().CGColor        layer.lineCap = kCALineCapButt        layer.lineWidth = self.ringWidth        return layer    }()    //MARK:- Utility Properties    private var radius : CGFloat {        return (min(bounds.width, bounds.height) - ringWidth) / 2.0    }    private var tipPath : CGPathRef {        return UIBezierPath(arcCenter: center, radius: radius, startAngle: -0.01, endAngle: 0, clockwise: true).CGPath    }    private var shadowMaskPath : CGPathRef {        return UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: CGFloat(M_PI_2), clockwise: true).CGPath    }    //MARK:- API Properties    public var color: CGColorRef = UIColor.redColor().CGColor {        didSet {            tipLayer.strokeColor = color        }    }    public var ringWidth: CGFloat = 40.0 {        didSet {            tipLayer.lineWidth = ringWidth            shadowLayer.lineWidth = ringWidth            shadowMaskLayer.lineWidth = ringWidth            preparePaths()        }    }    //MARK:- Initialisation    public override init() {        super.init()        sharedInitialisation()    }    public required init?(coder aDecoder: NSCoder) {        super.init(coder: aDecoder)        sharedInitialisation()    }    private func sharedInitialisation() {        addSublayer(shadowLayer)        addSublayer(tipLayer)        color = UIColor.redColor().CGColor        preparePaths()    }    //MARK:- Lifecycle Overrides    override public func layoutSublayers() {        for layer in [tipLayer, shadowLayer, shadowMaskLayer] {            layer.bounds = bounds            layer.position = center        }        preparePaths()    }    //MARK:- Utility methods    private func preparePaths() {        tipLayer.path = tipPath        shadowLayer.path = tipPath        shadowMaskLayer.path = shadowMaskPath    }}

然后用RingTip替换ringTipLayer

private lazy var ringTipLayer : RingTip = {    let layer = RingTip()    layer.color = self.ringColors.0    layer.ringWidth = self.ringWidth    return layer    }()

之后效果如下:

效果


最后创建3个ring

效果如下:

3个ring

完整代码如下:

import UIKitimport XCPlaygroundclass ThreeRingView : UIView {    //枚举    private enum RingIndex : Int {        case Inner  = 0        case Middle = 1        case Outer  = 2    }    private let rings : [RingIndex : RingLayer] = [.Inner : RingLayer(), .Middle : RingLayer(), .Outer : RingLayer()]    override init(frame: CGRect) {        super.init(frame: frame)        sharedInitialization()    }    required init?(coder aDecoder: NSCoder) {        super.init(coder: aDecoder)        sharedInitialization()    }    //重写layoutSubviews    override func layoutSubviews() {        super.layoutSubviews()        drawLayers()    }    private func sharedInitialization() {        backgroundColor = UIColor.blackColor()        for (_, ring) in rings {            //添加layer            layer.addSublayer(ring)            ring.backgroundColor = UIColor.clearColor().CGColor            ring.ringBackgroundColor = ringBackgroundColor.CGColor            ring.ringWidth = ringWidth        }        // Set the default values        for (color, (index, ring)) in zip([UIColor.hrPinkColor, UIColor.hrGreenColor, UIColor.hrBlueColor], rings) {            //设置颜色            setColorForRing(index, color: color)            ring.value = 0.0        }    }    private func drawLayers() {        let size = min(bounds.width, bounds.height)        for (index, ring) in rings {            //大小和位置            let curSize = size - CGFloat(index.rawValue) * ( ringWidth + ringPadding ) * 2.0            ring.bounds = CGRect(x: 0, y: 0, width: curSize, height: curSize)            ring.position = layer.position        }    }    //: API Properties    var ringWidth : CGFloat = 20.0 {        didSet {            drawLayers()            for (_, ring) in rings {                ring.ringWidth = ringWidth            }        }    }    var ringPadding : CGFloat = 1.0 {        didSet {            drawLayers()        }    }    var ringBackgroundColor : UIColor = UIColor.darkGrayColor() {        didSet {            for (_, ring) in rings {                ring.ringBackgroundColor = ringBackgroundColor.CGColor            }        }    }}//: Valuesextension ThreeRingView {    var innerRingValue : CGFloat {        get {            return rings[.Inner]?.value ?? 0        }        set(newValue) {            rings[.Inner]?.value = newValue        }    }    var middleRingValue : CGFloat {        get {            return rings[.Middle]?.value ?? 0        }        set(newValue) {            rings[.Middle]?.value = newValue        }    }    var outerRingValue : CGFloat {        get {            return rings[.Outer]?.value ?? 0        }        set(newValue) {            rings[.Outer]?.value = newValue        }    }}//: Colorsextension ThreeRingView {    var innerRingColor : UIColor {        get {            return colorForRing(.Inner)        }        set(newColor) {            setColorForRing(.Inner, color: newColor)        }    }    var middleRingColor : UIColor {        get {            return UIColor.clearColor()        }        set(newColor) {            setColorForRing(.Middle, color: newColor)        }    }    var outerRingColor : UIColor {        get {            return UIColor.clearColor()        }        set(newColor) {            setColorForRing(.Outer, color: newColor)        }    }    private func colorForRing(index: RingIndex) -> UIColor {        return UIColor(CGColor: rings[index]!.ringColors.0)    }    private func setColorForRing(index: RingIndex, color: UIColor) {        rings[index]?.ringColors = (color.CGColor, color.darkerColor.CGColor)    }}

转载地址:https://windzen.blog.csdn.net/article/details/53435252 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:CALayer基础
下一篇:UILabel&UITextView文本嵌入图片处理

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年03月23日 08时08分22秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

php8安全,PHP八大安全函数解析 2019-04-21
php基础语法了解和熟悉的表现,PHP第二课 了解PHP的基本语法以及目录结构 2019-04-21
matlab中lag函数用法,MATLAB movavg函数用法 2019-04-21
matlab变形监测,基于matlab的变形监测数据处理与分析_毕业设计论文 2019-04-21
opencv matlab编程,在Matlab中调用OpenCV函数 | 学步园 2019-04-21
c语言文件wt,c语言,wt和rt中的t是什么意思 2019-04-21
c语言运行几进制,【C语言】求已知等式在几进制条件下成立 2019-04-21
电梯运行仿真c语言代码,电梯调度算法模拟(示例代码) 2019-04-21
android组件动态接收数据库,Android开发——fragment中数据传递与刷新UI(更改控件)... 2019-04-21
云麦小米华为体脂秤怎么样_云康宝和华为智能体脂秤对比评测,实际体验告诉你哪款更好... 2019-04-21
linux 条件判断 取非_Linux awk 系列文章之 awk 多重条件判断 2019-04-21
c语言中如何将字符串的元素一个一个取出_C语言中常用的字符串操作函数 2019-04-21
2d游戏地图编辑器_王者荣耀:新版本爆料!地图编辑器“天工”即将开测,游戏怎么玩由你定!... 2019-04-21
.net framework服务启动后停止_dos命令net图文教程,start启动系统服务stop停止服务批处理脚本... 2019-04-21
8k分辨率需要多大带宽_超乎想象!用RTX3080显卡连索尼8K电视玩游戏感受如何?... 2019-04-21
win10怎么开启aptx_Win10未来的黑科技?微软SurfaceFleet大曝光 2019-04-21
creo视图管理器使用方法_学以致用之中望3D—浅谈使用中望3D的初步感受 2019-04-21
周育如的音标口诀大全_花鸟画口诀大全,实用! 2019-04-21
心电图计算心率公式_医学常用的计算公式口诀(内外妇儿),赶快收藏! 2019-04-21
select 移动端 第一个无法选中_Python爬虫微博(移动端)评论 2019-04-21