iOS自定义控件二
发布日期:2022-03-18 08:27:41
浏览次数:28
分类:技术文章
本文共 10986 字,大约阅读时间需要 36 分钟。
iOS自定义控件二
Drawing with Layers
本文内容,来自
本例子是使用Layer来创建一个RingLayer
,最终的效果如下:
大致思路是:
1.后面的灰色背景backgroundLayer
2.前面的foregroundLayer
,foregroundLayer
上添加一个gradientLayer
,相当于是一个渐变的layer。
3.给foregroundLayer
设置Mask为foregroundMask
,foregroundMask
为CAShapeLayer
4.旋转gradientLayer
5.如上图,渐变开始的部分还有突变,在foregroundLayer
,再添加上一个ringTipLayer
6.旋转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
内容来自
创建RingTip
,RingTip
是一个带有阴影的layer
CAShapeLayer
2.添加shadowLayer
,阴影layer
3.给shadowLayer
设置遮罩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
效果如下:完整代码如下:
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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
第一次来,支持一个
[***.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
云麦小米华为体脂秤怎么样_云康宝和华为智能体脂秤对比评测,实际体验告诉你哪款更好...
2019-04-21
linux 条件判断 取非_Linux awk 系列文章之 awk 多重条件判断
2019-04-21
c语言中如何将字符串的元素一个一个取出_C语言中常用的字符串操作函数
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