Swift - 实现自定义的Slider滑块组件(轨道上带有刻度标记)
作者:hangge | 2017-07-05 08:10
我之前过一篇关于 UISlider 的文章:Swift - 滑块(UISlider)的用法,介绍了 UISlider 的使用方法以及样式的修改。但如果我们想在背景轨道上标注一些刻度线,这个功能 UISlider 原生是没有提供的。
本文演示如何通过继承 UISlider,实现一个支持显示刻度线的滑块组件。比如我们可以在轨道的 1/4、1/2、3/4 处做个标记,方便用户定位。又比如使用 slider 作为播放进度条时,可以在进度上面标注出关键帧的位置。
1,效果图
这个自定义的滑块组件可以自由设置样式和刻度位置:
- 第1个样例使用默认样式,左侧轨道为深灰色,右侧轨道为浅灰色。同时轨道默认为每隔 10% 的位置都有一条刻度。
- 第2个样例我们修改了左右两侧轨道的颜色和高度,刻度的颜色和宽度。同时修改刻度出现的位置。
- 第3个样例还修改了轨道上控制器按钮的颜色。
- 第4个样例使用图片来代替轨道上的控制按钮。
2,自定义的组件代码(MarkSlider.swift)
其实现原理是通过继承 UISlider,在 draw 方法中生成带刻度的轨道图片(UIImage),再通过 setMinimumTrackImage 和 setMaximumTrackImage 方法设置到 Slider上。
这里要特别注意左侧轨道的 UIImage,为了避免拖动滑块时出现拉伸情况,我们还要通过 .resizableImage(withCapInsets: .zero) 方法将左侧轨道设置为不拉伸。
import UIKit //带有刻度的自定义滑块 class MarkSlider: UISlider { //刻度位置集合 var markPositions:[CGFloat] = [] //刻度颜色 var markColor: UIColor? //刻度宽度 var markWidth: CGFloat? //左侧轨道的颜色 var leftBarColor: UIColor? //右侧轨道的颜色 var rightBarColor:UIColor? //轨道高度 var barHeight: CGFloat? //初始化 override init(frame: CGRect) { super.init(frame: frame) //设置样式的默认值 self.markColor = UIColor(red: 106/255.0, green: 106/255.0, blue: 124/255.0, alpha: 0.7) self.markPositions = [10,20,30,40,50,60,70,80,90] self.markWidth = 1.0 self.leftBarColor = UIColor(red: 55/255.0, green: 55/255.0, blue: 94/255.0, alpha: 0.8) self.rightBarColor = UIColor(red: 179/255.0, green: 179/255.0, blue: 193/255.0, alpha: 0.8) self.barHeight = 12 } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func draw(_ rect: CGRect) { super.draw(rect) //得到左侧带有刻度的轨道图片(注意:图片不拉伸) let leftTrackImage = createTrackImage(rect: rect, barColor: self.leftBarColor!) .resizableImage(withCapInsets: .zero) //得到右侧带有刻度的轨道图片 let rightTrackImage = createTrackImage(rect: rect, barColor: self.rightBarColor!) //将前面生产的左侧、右侧轨道图片设置到UISlider上 self.setMinimumTrackImage(leftTrackImage, for: .normal) self.setMaximumTrackImage(rightTrackImage, for: .normal) } //生成轨道图片 func createTrackImage(rect: CGRect, barColor:UIColor) -> UIImage { //开始图片处理上下文 UIGraphicsBeginImageContextWithOptions(rect.size, false, 0) let context: CGContext = UIGraphicsGetCurrentContext()! //绘制轨道背景 context.setLineCap(.round) context.setLineWidth(self.barHeight!) context.move(to: CGPoint(x:self.barHeight!/2, y:rect.height/2)) context.addLine(to: CGPoint(x:rect.width-self.barHeight!/2, y:rect.height/2)) context.setStrokeColor(barColor.cgColor) context.strokePath() //绘制轨道上的刻度 for i in 0..<self.markPositions.count { context.setLineWidth(self.markWidth!) let position: CGFloat = self.markPositions[i]*rect.width/100.0 context.move(to: CGPoint(x:position, y: rect.height/2-self.barHeight!/2+1)) context.addLine(to: CGPoint(x:position, y:rect.height/2+self.barHeight!/2-1)) context.setStrokeColor(self.markColor!.cgColor) context.strokePath() } //得到带有刻度的轨道图片 let trackImage = UIGraphicsGetImageFromCurrentImageContext()! //结束上下文 UIGraphicsEndImageContext() return trackImage } }
3,使用样例
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //滑块1:使用默认样式、默认刻度(每10%一个刻度) let firstSlider = MarkSlider(frame:CGRect(x:10,y:50,width:200,height:40)) view.addSubview(firstSlider) //滑块2:修改默认样式 let secondSlider = MarkSlider(frame:CGRect(x:10,y:100,width:200,height:40)) secondSlider.markColor = UIColor(white: 1, alpha: 0.5) //刻度颜色 secondSlider.markPositions = [15,30,75] //刻度位置 secondSlider.markWidth = 3.0 //刻度宽度 secondSlider.leftBarColor = UIColor.orange //左轨道颜色 secondSlider.rightBarColor = UIColor(red: 255/255.0, green: 222/255.0, blue: 0/255.0, alpha: 1.0) //右轨道颜色 secondSlider.barHeight = 16 //轨道高度 view.addSubview(secondSlider) //滑块3:除了修改默认样式,还改变控制器颜色 let thirdSlider = MarkSlider(frame:CGRect(x:10,y:150,width:200,height:40)) thirdSlider.markColor = UIColor(white: 0, alpha: 0.1) thirdSlider.leftBarColor = UIColor(red: 108/255.0, green: 200/255.0, blue: 0/255.0, alpha: 1.0) thirdSlider.rightBarColor = UIColor(red: 138/255.0, green: 255/255.0, blue: 0/255.0, alpha: 1.0) thirdSlider.thumbTintColor = UIColor.orange //改变控制器颜色 view.addSubview(thirdSlider) //滑块4:除了修改默认样式,还改变控制器图片 let fourthSlider = MarkSlider(frame:CGRect(x:10,y:200,width:200,height:40)) fourthSlider.markColor = UIColor(white: 0, alpha: 0.1) fourthSlider.leftBarColor = UIColor(red: 108/255.0, green: 200/255.0, blue: 0/255.0, alpha: 1.0) fourthSlider.rightBarColor = UIColor(red: 138/255.0, green: 255/255.0, blue: 0/255.0, alpha: 1.0) fourthSlider.setThumbImage(UIImage(named: "sliderHandle"), for: .normal) //改变控制器图片 fourthSlider.barHeight = 4 view.addSubview(fourthSlider) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }源码下载:hangge_1597.zip
全部评论(0)