iOS儀表盤的繪制

隨著iOS技術(shù)的發(fā)展,UI設(shè)計(jì)也越來(lái)越復(fù)雜,儀表盤視圖出現(xiàn)的頻率也越來(lái)越高,通常用在速度顯示、利率選擇等場(chǎng)景。由于工作需要,也研究了一下。
先展示一下做好的效果圖:


原型圖@2x.png
儀表盤.gif
儀表盤2.gif

首先感謝一下JXCircleSlider,在參考GitHub上的資源之后,選擇了這個(gè)開源項(xiàng)目,作為需求的雛形。這個(gè)項(xiàng)目主要作用是,提供了紅色按鈕的拖動(dòng)跟蹤效果,這是其他項(xiàng)目中所沒(méi)有的。本人的其他工作是,增加一個(gè)結(jié)束跟蹤的代理響應(yīng)、繪制日期和利率、動(dòng)態(tài)計(jì)算利息、添加中央顯示、長(zhǎng)按選擇本金。

@interface JXCircleSlider : UIControl

@property (nonatomic,assign) int lineWidth;
@property (nonatomic,setter=changeAngle:) int angle;

@property (nonatomic, strong) NSArray *dateAngleArray;
@property (nonatomic, strong) NSArray *rateArray;
@property (nonatomic, strong) NSArray *dateArray;

@property (nonatomic, copy) NSString *currentRate;
@property (nonatomic, copy) NSString *currentSavings;
@property (nonatomic, copy) NSString *currentInterest;

- (void)reDrawRect;

@end

JXCircleSlider只是一個(gè)demo,除lineWidth和angle外,其他屬性都是需求需要而添加的。分別分別存儲(chǔ)日期數(shù)組、利率數(shù)組、日期利率在圓上的角度數(shù)組、以及一些需要?jiǎng)討B(tài)調(diào)整而增加的屬性:當(dāng)前利率、當(dāng)前本金、當(dāng)前利息。

@interface JXCircleSlider ()

@property (nonatomic, strong) UILabel *savingsLabel;
@property (nonatomic, strong) SavingsPickerView *savingsPickerView;
@property (nonatomic, strong) UITextField *textField;

@property (nonatomic, assign) NSTimeInterval beganTime;
@property (nonatomic, assign) NSTimeInterval endTime;

@property (nonatomic, assign) CGFloat unitIntrest0;
@property (nonatomic, assign) CGFloat unitIntrest1;
@property (nonatomic, assign) CGFloat unitIntrest2;
@property (nonatomic, assign) CGFloat unitIntrest3;
@property (nonatomic, assign) CGFloat unitIntrest4;

@end

說(shuō)明:此處為類的私有屬性,因?yàn)橛虚L(zhǎng)按彈出本金選擇的需求添加了UILabel、UIPickerView、和一個(gè)接收響應(yīng)者但并不展示的UITextField。設(shè)置開始和結(jié)束時(shí)間beganTime、endTime是為了區(qū)分用戶是滑動(dòng)tableview還是滑動(dòng)儀表盤視圖(做差是否>0.2s)。unitIntrest為優(yōu)化動(dòng)態(tài)計(jì)算利息和設(shè)置的一組屬性。

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    //繪制背景圖片
    [self drawImageWithCGContextRef:context];
    
    //繪制日期利率
    [self drawDateInterestWithCGContextRef:context];
    
    //繪制浮動(dòng)利息
    [self drawInfoWithRect:rect];
    
    //繪制拖動(dòng)小塊
    [self drawDotWithCGContextRef:context];
}

說(shuō)明:類的主體內(nèi)容,沒(méi)有特別的內(nèi)容。使用UIImage、NSString、UILabel等進(jìn)行渲染到圖形上下文或view即可。這里只介紹一下拖動(dòng)小塊:

- (void)drawDotWithCGContextRef:(CGContextRef)context {
    CGPoint handleCenter =  [self dotPointFromAngle:self.angle];
    [[UIColor redColor] setStroke];
    CGContextSetLineWidth(context, 5);
    CGContextAddEllipseInRect(context, CGRectMake(handleCenter.x, handleCenter.y, 5, 5));
    CGContextDrawPath(context, kCGPathStroke);
}

說(shuō)明:畫一個(gè)半徑為5的點(diǎn)。以下所有的手勢(shì)都需要用這個(gè)點(diǎn)來(lái)展示效果。

-(BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
    [super beginTrackingWithTouch:touch withEvent:event];
        self.beganTime = touch.timestamp;
    return YES;
}


-(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
    [super continueTrackingWithTouch:touch withEvent:event];
    //獲取觸摸點(diǎn)
    CGPoint lastPoint = [touch locationInView:self];
    //使用觸摸點(diǎn)來(lái)移動(dòng)小塊
    [self movehandle:lastPoint];
    //發(fā)送值改變事件
    [self sendActionsForControlEvents:UIControlEventValueChanged];
    
    return YES;
}

- (void)endTrackingWithTouch:(nullable UITouch *)touch withEvent:(nullable UIEvent *)event {
    [super endTrackingWithTouch:touch withEvent:event];
    self.endTime = touch.timestamp;
    
    if (self.endTime - self.beganTime < 0.2) return;
    
    if (self.angle >= [self.dateAngleArray[0] intValue] && self.angle < [self.dateAngleArray[1] intValue]) {
        self.angle = [self.dateAngleArray[1] intValue];
    }else if (self.angle >= [self.dateAngleArray[1] intValue] && self.angle < [self.dateAngleArray[2] intValue]) {
        self.angle = [self.dateAngleArray[2] intValue];
    }else if (self.angle >= [self.dateAngleArray[2] intValue] && self.angle < [self.dateAngleArray[3] intValue]) {
        self.angle = [self.dateAngleArray[3] intValue];
    }else if (self.angle >= [self.dateAngleArray[3] intValue] || self.angle < [self.dateAngleArray[4] intValue]) {
        self.angle = [self.dateAngleArray[4] intValue];
    }else {
        self.angle = [self.dateAngleArray[0] intValue];
    }
    
    //刷新當(dāng)前利息
    [self updateCurrentInterest];
    
    [UIView animateWithDuration:0.5f animations:^{
        //重新繪制
        [self setNeedsDisplay];
    }];
}

說(shuō)明:項(xiàng)目的核心思路:監(jiān)聽用戶在儀表盤上的拖動(dòng)行為。根據(jù)前后兩個(gè)點(diǎn)計(jì)算偏移角度,重置圓點(diǎn)的位置,同時(shí)刷新當(dāng)前利息的數(shù)值。
下載地址InstrumentView、如果對(duì)你有用,歡迎點(diǎn)贊,謝謝!

最后編輯于
?著作權(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)容