iOS 圓環(huán)型滑塊(Circle Slider)

一勺择、圓環(huán)型滑塊的設(shè)計(jì)

  • 最近設(shè)計(jì)師設(shè)計(jì)了一個(gè)圓環(huán)型滑塊,其作用和UISlider差不多床佳,用于拖動(dòng)改變播放音頻的進(jìn)度和指示音頻的播放進(jìn)度导俘。
  • 大概的樣子如下圖:


    圖一 設(shè)計(jì)圖
  • 有如下的特點(diǎn):
    • 滑動(dòng)的響應(yīng)區(qū)域?yàn)閳A環(huán)上,并且靠近滑塊驳概;
    • 點(diǎn)擊滑塊時(shí)赤嚼,滑塊有一個(gè)放大的動(dòng)畫,手指離開屏幕時(shí)滑塊恢復(fù)原來大兴秤帧更卒;
    • 當(dāng)value=0%時(shí),滑塊不可以再逆時(shí)針滑動(dòng)稚照,當(dāng)value=100%時(shí)蹂空,滑塊不可以再順時(shí)針滑動(dòng)。
    • 最后我自己再加了一個(gè)設(shè)計(jì)锐锣,指示音頻loading的進(jìn)度(這樣以來圓環(huán)就有了三層)腌闯。

二、成果展示Demo

Github 傳送門

  1. 重復(fù)滑動(dòng)
圖二 重復(fù)滑動(dòng)
  1. 限定360度和有l(wèi)oading的進(jìn)度
圖三 限定360度

三雕憔、接入使用

1. 接入

直接將我的項(xiàng)目中ZCircleSlider文件夾中的ZCircleSlider.h 和 ZCircleSlider.m拖到項(xiàng)目中即可

2.使用

//ZCircleSlider的背景色是透明的,不會(huì)擋住下面View
- (ZCircleSlider *)circleSlider {
    if (!_circleSlider) {
        _circleSlider = [[ZCircleSlider alloc] initWithFrame:CGRectMake((kScreenWidth - 300) / 2.0, (kScreenHeight - 300) / 2.0, 300, 300)];
        //走過的進(jìn)度的顏色
        _circleSlider.minimumTrackTintColor = kUIColorFromRGB(0x1482f0);
        //loading進(jìn)度的顏色糖声。如果loading = 1斤彼,即loading完成分瘦,那么也是圓環(huán)的顏色,同于backgroundTintColor
        _circleSlider.maximumTrackTintColor = kUIColorFromRGB(0xE62E2E);
        //圓環(huán)的顏色
        _circleSlider.backgroundTintColor = [UIColor colorWithWhite:0 alpha:0.2];
        //圓環(huán)的寬
        _circleSlider.circleBorderWidth = 5.0f;
        //圓形滑塊的半徑
        _circleSlider.thumbRadius = 8;
        //圓形滑塊放大效果的半徑
        _circleSlider.thumbExpandRadius = 12.5;
        //圓形滑塊的顏色
        _circleSlider.thumbTintColor = [UIColor redColor];
        //圓環(huán)的半徑
        _circleSlider.circleRadius = 260 / 2.0 + 2;
        //設(shè)定初始值value = 0
        _circleSlider.value = 0;
        //設(shè)定loadingProgress的初始值 = 0
        _circleSlider.loadProgress = 0;
        //開始點(diǎn)擊琉苇,響應(yīng)事件
        [_circleSlider addTarget:self
                          action:@selector(circleSliderTouchDown:)
                forControlEvents:UIControlEventTouchDown];
        //拖動(dòng)過程中嘲玫,響應(yīng)事件
        [_circleSlider addTarget:self
                          action:@selector(circleSliderValueChanging:)
                forControlEvents:UIControlEventValueChanged];
        //拖動(dòng)結(jié)束,響應(yīng)事件
        [_circleSlider addTarget:self
                          action:@selector(circleSliderValueDidChanged:)
                forControlEvents:UIControlEventTouchUpInside];
    }
    return _circleSlider;
}

#pragma mark - action

/*以下三個(gè)方法并扇,都要添加對(duì)slider.interaction的判斷去团。
 *因?yàn)殡m然看起來是個(gè)圓環(huán),但是響應(yīng)手勢(shì)的區(qū)域確實(shí)整個(gè)矩形的View
 *在內(nèi)部添加了interaction這個(gè)屬性用于限定響應(yīng)區(qū)域
 */
- (IBAction)circleSliderTouchDown:(ZCircleSlider *)slider {
    if (!slider.interaction) {
        return;
    }
    
}

- (IBAction)circleSliderValueChanging:(ZCircleSlider *)slider {
    if (!slider.interaction) {
        return;
    }
    self.currentValueLabel.text = [NSString stringWithFormat:@"當(dāng)前值:%.0f",slider.value * 100];
    self.progressSlider.value = slider.value;
}

- (IBAction)circleSliderValueDidChanged:(ZCircleSlider *)slider {
    if (!slider.interaction) {
        return;
    }
    self.finalValueLabel.text = [NSString stringWithFormat:@"最終值:%.0f",slider.value * 100];
}

四穷蛹、實(shí)現(xiàn)原理

簡(jiǎn)單來說就是土陪,整個(gè)控件繼承與UIControl,根據(jù)value肴熏,loadProgress的值改變重新繪制layer和改變thumb的位置鬼雀;根據(jù)手勢(shì)所在的位置,重新繪制layer和改變thumb的位置蛙吏,并改變value源哩。

1. 根據(jù)所給value繪制圓弧

circleSlider.value和circleSlider.loadProgress,都是繪制圓弧鸦做。

1)在- (void)drawRect:(CGRect)rect;方法中繪制圓弧

在iOS中励烦,圓的0弧度的位置是圓心(x,y)的正右側(cè)(x+r,y)
這里我選擇起始位置為-M_PI_2弧度,即圓心的正上方(x,y-r);
弧長(zhǎng)對(duì)應(yīng)的變量就是運(yùn)動(dòng)的點(diǎn)相對(duì)于起點(diǎn)旋轉(zhuǎn)過的角度泼诱,而這個(gè)角度就等于value/1.0 * 360
下面給出了加載進(jìn)度圓弧的繪制方法坛掠,value的圓弧繪制方法同理

- (void)drawRect:(CGRect)rect {
    //加載的進(jìn)度
    UIBezierPath *loadPath = [UIBezierPath bezierPath];
    CGFloat loadStart = -M_PI_2;
    CGFloat loadCurre = loadStart + 2 * M_PI * self.loadProgress;
    
    [loadPath addArcWithCenter:self.drawCenter
                        radius:self.radius
                    startAngle:loadStart
                      endAngle:loadCurre
                     clockwise:YES];
    CGContextSaveGState(ctx);
    CGContextSetShouldAntialias(ctx, YES);
    CGContextSetLineWidth(ctx, self.circleBorderWidth);
    CGContextSetStrokeColorWithColor(ctx, self.maximumTrackTintColor.CGColor);
    CGContextAddPath(ctx, loadPath.CGPath);
    CGContextDrawPath(ctx, kCGPathStroke);
    CGContextRestoreGState(ctx);
}

2) 在值改變的時(shí)候重新繪制layer

在值改變的時(shí)候調(diào)用setNeedsDisplay方法重新繪制layer

- (void)setLoadProgress:(float)loadProgress {
    _loadProgress = loadProgress;
    [self setNeedsDisplay];
}

2.拖動(dòng)控制,以及保證thumb(滑塊的那個(gè)圓點(diǎn))在圓弧上運(yùn)動(dòng)

這里主要給出了解決的思路方法坷檩,具體的實(shí)現(xiàn)可到Github中查看

主要是在UIControl的以下三個(gè)方法上做文章:

//點(diǎn)擊開始
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event;

//拖動(dòng)過程中
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event;

//拖動(dòng)結(jié)束
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event;

1) 對(duì)于拖動(dòng)控制却音,以及保證thumb在圓弧上運(yùn)動(dòng)可以通過以下這道數(shù)學(xué)題做抽象

1.設(shè)定平面直角坐標(biāo)系原點(diǎn)為O(0,0),向右為x軸的正方向矢炼,向下為y軸的正方向系瓢;--------(iOS的屏幕坐標(biāo)系)
2.在坐標(biāo)系中有一個(gè)已知的圓C(a,b),半徑為r句灌;--------(圓環(huán)型Slider)
3.平面內(nèi)任意一點(diǎn)S(m,n)夷陋;--------(點(diǎn)擊的位置)
求:
    1)點(diǎn)S到圓C的最短距離是否小于44;(限定點(diǎn)擊響應(yīng)的區(qū)域?yàn)閳A弧內(nèi)外44個(gè)點(diǎn)的區(qū)域)
    2)線段SC與圓的交點(diǎn)T(xT,yT)胰锌;(thumb的位置骗绕,肯定在圓弧上)
    3)線段ST的距離是否小于44;(限定點(diǎn)擊開始時(shí)的響應(yīng)區(qū)域?yàn)橐詔humb圓心资昧,半徑為44的圓以內(nèi))

2) 對(duì)于當(dāng)value=0%時(shí)酬土,滑塊不可以再逆時(shí)針滑動(dòng),當(dāng)value=100%時(shí)格带,滑塊不可以再順時(shí)針滑動(dòng)撤缴。

1. 平面內(nèi)一個(gè)圓C半徑為r刹枉,其圓心位于坐標(biāo)系原點(diǎn),即C(0,0)屈呕,圓弧上有一點(diǎn)T(x,y);
2. 坐標(biāo)系可分為第一微宝、二、三和四象限虎眨。
    1)那么當(dāng)點(diǎn)T相對(duì)于起始點(diǎn)(0,-r)蟋软,順時(shí)針轉(zhuǎn)過的角度<60度時(shí),禁止移動(dòng)到第二嗽桩,三岳守,四象限;
    2)當(dāng)點(diǎn)T相對(duì)于起始點(diǎn)(0,-r)涤躲,順時(shí)針轉(zhuǎn)過角度>300度時(shí)棺耍,禁止移動(dòng)到第一,二种樱,三象限蒙袍;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嫩挤,隨后出現(xiàn)的幾起案子害幅,更是在濱河造成了極大的恐慌,老刑警劉巖岂昭,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件以现,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡约啊,警方通過查閱死者的電腦和手機(jī)邑遏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來恰矩,“玉大人记盒,你說我怎么就攤上這事⊥飧担” “怎么了纪吮?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)萎胰。 經(jīng)常有香客問我碾盟,道長(zhǎng),這世上最難降的妖魔是什么技竟? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任冰肴,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嚼沿。我一直安慰自己估盘,他們只是感情好瓷患,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布骡尽。 她就那樣靜靜地躺著,像睡著了一般擅编。 火紅的嫁衣襯著肌膚如雪攀细。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天爱态,我揣著相機(jī)與錄音谭贪,去河邊找鬼。 笑死锦担,一個(gè)胖子當(dāng)著我的面吹牛俭识,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洞渔,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼套媚,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了磁椒?” 一聲冷哼從身側(cè)響起堤瘤,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎浆熔,沒想到半個(gè)月后本辐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡医增,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年慎皱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片叶骨。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茫多,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出邓萨,到底是詐尸還是另有隱情地梨,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布缔恳,位于F島的核電站宝剖,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏歉甚。R本人自食惡果不足惜万细,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赖钞,春花似錦腰素、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至献起,卻和暖如春洋访,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谴餐。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工姻政, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岂嗓。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓汁展,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親厌殉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子食绿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件年枕、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,105評(píng)論 4 62
  • 三月熏兄,驚蜇品洛。 一聲春雷,萬(wàn)物復(fù)蘇了摩桶。南方有句農(nóng)諺:雷打驚蜇前,四十八天雨綿綿桥状。前些天跟一個(gè)南方的朋友通...
    川江水閱讀 208評(píng)論 0 1
  • “快跑——辅斟!快跑——”尾音未落,這個(gè)仿佛要將嗓子撕裂般吼叫出來的聲音便在瞬間湮沒在了熊熊燃燒的大火之中芦拿。 少女的兩...
    ea3a431876df閱讀 424評(píng)論 0 1
  • 參加早起群已經(jīng)有六天了士飒,之前就有早起的想法,但是嘗試了幾天后發(fā)現(xiàn)自己堅(jiān)持不下來蔗崎。主要是兩個(gè)原因酵幕,一個(gè)是沒有一個(gè)早起...
    楠牧閱讀 227評(píng)論 1 1
  • 前言 在上一節(jié)我們通過使用NumPy的數(shù)組分割成功的在我們的圖像上畫了一個(gè)綠色的方塊,但是如果我們想畫一個(gè)單一的線...
    樓上小宇閱讀 3,345評(píng)論 1 2