前言
这边文章主要 是写
一、半圆弧型滑块的设计
最近项目中需要用到半圆弧形滑块,其作用和UISlider差不多,用于拖动改变播放音乐的播放进度。
大概样子是这样的:
特点如下:
滑动响应区域为弧环上,并且靠近滑动块,,并限制了中心区域不可滑动;
当值为0时不可再逆时针滑动,当值为最大值时,不再可顺时针滑动。
最后我自己设计一个功能,可以按固定值随意跳动,按值控制滑动条的进度。
二、成功展示
三、接入使用
1.接入
直接将CYCircularSlider.h和CYCircularSlider.m文件拖到项目中即可
2.使用
CGRect sliderFrame = CGRectMake(([UIScreen mainScreen].bounds.size.width-275)/2, ([UIScreen mainScreen].bounds.size.height-275)/2, 275,275); _circularSlider =[[CYCircularSlider alloc]initWithFrame:sliderFrame]; [self.view addSubview:_circularSlider]; //设置代理 _circularSlider.delegate = self;
四、实现原理
整控件继承UIControl,根据值的改变重新绘制layer和改变thumb的位置;根据手势所在的位置,重新layer和改变thumb的位置,并且改变值。
1.根据所给_angle绘制圆弧
在- (void)drawRect:(CGRect)rect;
方法中绘制圆弧
(self.frame.size.width/2,self.frame.size.height/2)
,弧长对应的变量就是运动的点相对于起点旋转过的角度,而这个角度就等于M_PI/180*(_angle)
。 下面给出背景圆弧和进度圆弧的绘制方法
#pragma mark 画圆-(void)drawRect:(CGRect)rect{ [super drawRect:rect]; //画固定的下层圆 CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextAddArc(ctx, self.frame.size.width/2, self.frame.size.height/2, radius, M_PI/180*140, M_PI/180*40, 0); [_unfilledColor setStroke]; CGContextSetLineWidth(ctx, _lineWidth); CGContextSetLineCap(ctx, kCGLineCapButt); CGContextDrawPath(ctx, kCGPathStroke); CGContextAddArc(ctx, self.frame.size.width/2, self.frame.size.height/2, radius, M_PI/180*140, M_PI/180*(_angle), 0); //画可滑动的上层圆 [_filledColor setStroke]; CGContextSetLineWidth(ctx, _lineWidth); CGContextSetLineCap(ctx, kCGLineCapButt); CGContextDrawPath(ctx, kCGPathStroke); [self drawHandle:ctx]; }
在值改变的时候重新绘制layer
#pragma mark 设置进度条位置-(void)setAngel:(int)num{ _angle = num; [self setNeedsDisplay]; }
2.绘制thumb以及确保在圆弧上运动
#pragma mark 画thumb-(void)drawHandle:(CGContextRef)ctx{ CGContextSaveGState(ctx); CGPointhandleCenter = [self pointFromAngle: _angle]; [_handleColor set]; CGContextFillEllipseInRect(ctx, CGRectMake(handleCenter.x-2.5, handleCenter.y-2.5, _lineWidth+5, _lineWidth+5)); CGContextRestoreGState(ctx); }
3.拖动控制。
主要是在UIControl的以下三个方法上做文章:
//点击开始- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event;//拖动过程中 - (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event; //拖动结束 - (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event;
实现如下:
-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { [super continueTrackingWithTouch:touch withEvent:event]; CGPoint lastPoint = [touch locationInView:self]; //用于排除点在圆外面点与圆心半径80以内的点 if ((lastPoint.x>=0&&lastPoint.x<=275)&&(lastPoint.y>=0 && lastPoint.y<=275)) { if ((lastPoint.x<=57.5||lastPoint.x>=217.5)||(lastPoint.y<=57.5 ||lastPoint.y>=217.5)) { [self moveHandle:lastPoint]; } } [self sendActionsForControlEvents:UIControlEventValueChanged]; return YES; } -(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{ [super endTrackingWithTouch:touch withEvent:event]; [self.delegate senderVlueWithNum:(int8_t)roundf(_currentValue)]; }
在拖动过程中处理数据、实现重绘layer改变_angle值,在拖动结束中实现代理方法。
4.对于当值为0时,滑块不可以再逆时针滑动,当值为最大值时,滑块不可以再顺时针滑动。
只要判断_angle>40 && _angle< 140
时,将_angle
抛出就可以了。
五、尾言
1、参考资料
2、下载传送门
或3.再说几句
因为实在是比较忙,而且沉不住心来写的太仔细,项目里面也有很多地方写的有问题和不够好,以后有时间再修改,有问题也请大家留言,我会改正的。
另外总得来说,弧形滑动条是就是把圆形滑动条的起始位置和终点位置经过修改,然后计算绘制弧长的参数等也要进行一些修改。