自定義圓環(huán)控件

circularSlider.001.jpeg

在開發(fā)過程中,有時(shí)候標(biāo)準(zhǔn)的 UIKit 控件并不能滿足我們的需求,這時(shí)候就需要我們自定義。

自定義控件可以參考系統(tǒng)中已有控件來(lái)實(shí)現(xiàn),比如 UIButton, ,UISegmentedControl, UISlider, UISwitch 等,它們都繼承自 UIControl。

先來(lái)看一張最終的效果:


circular_slider.gif

該圓環(huán)控件可以做的事情:定制一個(gè)用戶界面,通過該界面用戶,可以在指定區(qū)域內(nèi)拖動(dòng)手柄,將當(dāng)前的角度轉(zhuǎn)化為需要顯示的數(shù)據(jù)。交互操作會(huì)被轉(zhuǎn)為控件的 Target 對(duì)應(yīng)的 Action。

完整的工程示例可以在這里下載:SFCircularSlider

繪制用戶界面

  1. 繪制底部圓環(huán)
    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);

這里繪制圓的方向,零度位于圓的最右側(cè),向上為負(fù)數(shù),向下是正數(shù)。

  1. 繪制填充區(qū)域
  CGContextSaveGState(context);
    
    CGContextAddArc(context, kSelfWidth / 2, kSelfHeight / 2, _radius,
                    DegreesToRadians(kCircleDegreeMin),
                    DegreesToRadians(kCircleDegree360 - _angle), 0);
    
    [_minimumTrackTintColor setStroke];
    
    CGContextSetLineWidth(context, _borderWidth);
    CGContextSetLineCap(context, kCGLineCapRound);  //設(shè)置線起點(diǎn)終點(diǎn)形狀
    
    CGContextDrawPath(context, kCGPathStroke);
    
    CGContextRestoreGState(context);

_angle 代表當(dāng)前角度,需要轉(zhuǎn)換到繪制角度上。繪制起點(diǎn)為最小值到當(dāng)前手勢(shì)所在位置。

  1. 繪制未填充區(qū)域圓弧
    CGContextAddArc(context, kSelfWidth / 2, kSelfWidth / 2,
                    _radius, DegreesToRadians(kCircleDegree360 - _angle),
                    DegreesToRadians(kCircleDegreeMax), 0);
    
    [_maximumTrackTintColor setStroke];
    
    CGContextSetLineWidth(context, _borderWidth);
    CGContextSetLineCap(context, kCGLineCapRound);  //設(shè)置線起點(diǎn)終點(diǎn)形狀
    
    CGContextDrawPath(context, kCGPathStroke);

未填充顏色區(qū)域原理相同,起點(diǎn)為手勢(shì)所在位置,終點(diǎn)為最大值處。

  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);

手柄跟蹤當(dāng)前手勢(shì)所在的位置。為了增強(qiáng)立體感,添加投影的效果。CGContextSetShadowWithColor 中 offset 參數(shù)代表偏移的距離和方向,左負(fù)右正,上負(fù)下正,{0,0} 代表在一周上投影。

跟蹤用戶操作

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

通過重載 beginTracking 方法控制起始的觸發(fā)區(qū)域。

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

重載 continueTracking 來(lái)連續(xù)跟蹤用戶的手勢(shì),并在超出響應(yīng)范圍之外返回 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];

支持設(shè)定最小/最大值,亦可接受 ValueChanged 和 TouchUpInside 的事件來(lái)響應(yīng)當(dāng)前拖動(dòng)的值和拖動(dòng)結(jié)束的值。

Demo 下載地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容