自定义圆环控件

circularSlider.001.jpeg

在开发过程中,有时候标准的 UIKit 控件并不能满足我们的需求,这时候就需要我们自定义。

自定义控件可以参考系统中已有控件来实现,比如 UIButton, ,UISegmentedControl, UISlider, UISwitch 等,它们都继承自 UIControl。

先来看一张最终的效果:

 

circular_slider.gif

 

该圆环控件可以做的事情:定制一个用户界面,通过该界面用户,可以在指定区域内拖动手柄,将当前的角度转化为需要显示的数据。交互操作会被转为控件的 Target 对应的 Action。

完整的工程示例可以在这里下载:SFCircularSlider

绘制用户界面

  1. 绘制底部圆环
    CGContextSaveGState(context);
    
    CGContextAddArc(context, kSelfWidth / 2, kSelfHeight / 2, _radius, -M_PI, M_PI * 2, 0);
    
    [_circularColor setStroke];
    
    CGContextSetLineWidth(context, _borderWidth);
    CGContextSetLineCap(context, kCGLineCapButt);
    
    CGContextDrawPath(context, kCGPathStroke);
    
    CGContextRestoreGState(context);

这里绘制圆的方向,零度位于圆的最右侧,向上为负数,向下是正数。

  1. 绘制填充区域
  CGContextSaveGState(context);
    
    CGContextAddArc(context, kSelfWidth / 2, kSelfHeight / 2, _radius,
                    DegreesToRadians(kCircleDegreeMin),
                    DegreesToRadians(kCircleDegree360 - _angle), 0);
    
    [_minimumTrackTintColor setStroke];
    
    CGContextSetLineWidth(context, _borderWidth);
    CGContextSetLineCap(context, kCGLineCapRound);  //设置线起点终点形状
    
    CGContextDrawPath(context, kCGPathStroke);
    
    CGContextRestoreGState(context);

_angle 代表当前角度,需要转换到绘制角度上。绘制起点为最小值到当前手势所在位置。

  1. 绘制未填充区域圆弧
    CGContextAddArc(context, kSelfWidth / 2, kSelfWidth / 2,
                    _radius, DegreesToRadians(kCircleDegree360 - _angle),
                    DegreesToRadians(kCircleDegreeMax), 0);
    
    [_maximumTrackTintColor setStroke];
    
    CGContextSetLineWidth(context, _borderWidth);
    CGContextSetLineCap(context, kCGLineCapRound);  //设置线起点终点形状
    
    CGContextDrawPath(context, kCGPathStroke);

未填充颜色区域原理相同,起点为手势所在位置,终点为最大值处。

  1. 绘制手柄(thumb)
    CGPoint handleCenter = [self pointFromAngle:_angle radius:_radius];
    
    [_thumbTintColor set];
    
    CGSize shadowOffset = CGSizeMake(0, 0);
    CGFloat colorValues[] = {0, 0, 1/2, .6};
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB ();
    CGColorRef color = CGColorCreate (colorSpace, colorValues);
    CGContextSetShadowWithColor(context, shadowOffset, 3, color);
    
    CGContextFillEllipseInRect(context, CGRectMake(handleCenter.x - _thumbRadius,
                                                   handleCenter.y - _thumbRadius,
                                                   _thumbRadius * 2, _thumbRadius * 2));
    
    CGContextSetLineCap(context, kCGLineCapButt);
    CGContextDrawPath(context, kCGPathStroke);
    
    CGColorRelease(color);
    CGColorSpaceRelease(colorSpace);

手柄跟踪当前手势所在的位置。为了增强立体感,添加投影的效果。CGContextSetShadowWithColor 中 offset 参数代表偏移的距离和方向,左负右正,上负下正,{0,0} 代表在一周上投影。

跟踪用户操作

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {}

通过重载 beginTracking 方法控制起始的触发区域。

- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(nullable UIEvent *)event {}

重载 continueTracking 来连续跟踪用户的手势,并在超出响应范围之外返回 NO

使用示例

    SFCircularSlider *circularSlider = [[SFCircularSlider alloc] init];
    circularSlider.value = 5;
    circularSlider.minimumValue = 0;
    circularSlider.maximumValue = 10;
    circularSlider.minimumTrackTintColor = [UIColor colorWithRed:255/255.0 green:177/255.0 blue:0/255.0 alpha:1];
    [circularSlider addTarget:self action:@selector(toucheUpInsideAction:) forControlEvents:UIControlEventTouchUpInside];
    [circularSlider addTarget:self action:@selector(valueChangedAction:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview:circularSlider];

支持设定最小/最大值,亦可接受 ValueChanged 和 TouchUpInside 的事件来响应当前拖动的值和拖动结束的值。

Demo 下载地址



作者:SmallflyBlog
链接:https://www.jianshu.com/p/75f7cc577e8a
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值