// // HDLOnRollCurtainSeekBar.m // HDL_Widget_iOS // // Created by 陈嘉乐 on 2020/6/15. // Copyright © 2020 JLChen. All rights reserved. // #import "HDLOnRollCurtainSeekBar.h" #import "HDLUtlisXM.h" #define APP_DEFAULT_OFFLINE_COLOR HEXCOLORA(0xE9E9EC,0.8) @interface HDLOnRollCurtainSeekBar () /** 是否正在移动 */ @property (nonatomic, assign) BOOL bTouchMove; /** 进度单位符号 */ @property (nonatomic, strong) NSString *mProgressBarUnitSring; /** 最小值 */ @property (nonatomic, assign) float mMinValue; /** 最大值 */ @property (nonatomic, assign) float mMaxValue; /** 边距 */ @property (nonatomic, assign) int mCurtainPadding; /** */ //@property (nonatomic, strong) UIImageView *bgImageView; /** 顶部padding */ @property (nonatomic, assign) int mCurtainPaddingTop; /** 是否离线 */ @property (nonatomic, assign) BOOL isOffline; /** 是否百叶窗类型 */ @property (nonatomic, assign) BOOL isBlindsType; @end @implementation HDLOnRollCurtainSeekBar{ int _mMoveCount; CGPoint _mCenterPoint; //圆心坐标 bool _bIsInCurtainProgress; CGFloat _mCurtainHeight; CGFloat _mCurtainWidth; float _mPercent; CGFloat _mButtonWidth; CGFloat _mCurtainY; CGFloat _mCornerRadius; UIImage *_curtainImage; UIImage *_curtainImage_close; UIImage *_buttonImage; UIImage *_bgImage; } -(instancetype)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { _isClickable = YES; _mMoveCount = 0; _mProgress = 0; _mPercent = 0; _mMaxValue = 100.0f; _mMinValue = 0.0f; _mCornerRadius = 0; _mProgressTextColor = [UIColor blackColor]; _mProgressTextSize = 15; _mProgressBarUnitSring = @"%"; _isProgressTextShow = YES; // _mCurtainPaddingTop = 45; _mCurtainPadding = self.frame.size.width*12/130; _mCurtainPaddingTop = self.frame.size.height*14/172; [self refreshFrame]; self.backgroundColor = [UIColor clearColor]; // _bgImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; // [_bgImageView setImage:[UIImage imageNamed:@"ic_wd_curtain_roll_bg"]]; // [self addSubview:_bgImageView]; _curtainImage = [UIImage imageNamed:@"ic_wd_on_curtain_roll_progress"]; _curtainImage_close = [UIImage imageNamed:@"ic_wd_on_curtain_roll_progress_close"]; _buttonImage = [UIImage imageNamed:@"ic_wd_on_curtain_open"]; _bgImage = [UIImage imageNamed:@"ic_wd_on_curtain_roll_bg"]; } return self; } /** 刷新布局,更新关键值 */ -(void)refreshFrame{ _mCenterPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2); [self onCurtainSizeChange]; } /** 刷新布局,更新关键值 */ -(void)onCurtainSizeChange{ // _mCurtainPadding = _CurtainPadding; if(!_isBlindsType){ _mCurtainPadding = self.frame.size.width * 12 / 149 - 1; }else{ //百叶窗效果 _mCurtainPadding = self.frame.size.width * 2 / 149 - 1; } _mCurtainPaddingTop = self.frame.size.height * 14 / 172; _mCurtainWidth = self.frame.size.width - _mCurtainPadding * 2; _mButtonWidth = self.frame.size.width * 56 / 149; _mCurtainHeight = self.frame.size.height - _mCurtainPaddingTop; } #pragma mark drawRect 绘制图形 -(void)drawRect:(CGRect)rect{ [super drawRect:rect]; CGContextRef ctx = UIGraphicsGetCurrentContext(); //将当前图形状态推入堆栈 CGContextSaveGState(ctx); //*********绘制背景********* [self drawBackIamge]; //*********绘制动态的进度条********* [self drawProgressBar:ctx]; //*********绘制显示进度值文字********* [self drawProgressText:ctx]; //*********绘制按钮图片********* [self drawImageButton:ctx]; // //*********如果离线绘制离线背景遮挡层********* // [self drawOfflineView:ctx]; //把堆栈顶部的状态弹出 CGContextRestoreGState(ctx); } // ///** // 绘制边框 // // @param ctx 画布 // */ //-(void)drawBorderPath:(CGContextRef)ctx{ // CGRect drawRect = {5+_mBackLineWidth/2, 5+_mBackLineWidth/2, self.frame.size.width-10-_mBackLineWidth, self.frame.size.height-10-_mBackLineWidth}; // // UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:drawRect cornerRadius:_mCornerRadius]; // path.lineWidth = _mBackLineWidth; //线宽 // path.lineCapStyle = kCGLineCapRound; //弯角样式 // path.lineJoinStyle = kCGLineJoinBevel; //交点的样式 // [_mCurtainBorderColor set]; // // CGContextSetLineWidth(ctx, _mBackLineWidth); // CGContextAddPath(ctx, path.CGPath); // CGContextDrawPath(ctx, kCGPathStroke); // // [path stroke]; //边框线颜色 //} /** 如果离线绘制离线背景遮挡层 @param ctx 画布 */ -(void)drawOfflineView:(CGContextRef)ctx{ if(_isOffline){ CGRect drawRect2 = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height); UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:5]; [APP_DEFAULT_OFFLINE_COLOR set]; CGContextAddPath(ctx, path3.CGPath); CGContextDrawPath(ctx, kCGPathFill); } } /** 绘制背景图 */ -(void)drawBackIamge{ //绘制背景图 CGRect rectBgImage = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height); [_bgImage drawInRect:rectBgImage]; } /** 绘制进度条 @param ctx 画布 */ -(void)drawProgressBar:(CGContextRef)ctx{ //*******绘制剪裁限制显示区域********* CGRect drawRect2 = CGRectMake(0, _mCurtainPaddingTop, self.frame.size.width, _mCurtainHeight); UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:drawRect2 cornerRadius:0]; // [APP_DEFAULT_BG set]; CGContextAddPath(ctx, path2.CGPath); // 剪裁路径 CGContextClip(ctx); _mCurtainY = _mPercent * _mCurtainHeight + _mCurtainPaddingTop; CGRect rectImage = CGRectMake(_mCurtainPadding, _mCurtainY - _mCurtainHeight, _mCurtainWidth, _mCurtainHeight); // [_curtainImage drawInRect:rectImage]; if(_isOffline){ [_curtainImage_close drawInRect:rectImage]; }else{ [_curtainImage drawInRect:rectImage]; } } /** 绘制进度显示值文字 @param ctx 画布 */ -(void)drawProgressText:(CGContextRef)ctx{ if(_isProgressTextShow){ [self drawString:[NSString stringWithFormat:@"%d%@", _mProgress, _mProgressBarUnitSring]]; } } /** 绘制进度显示值文字 @param ctx 画布 */ -(void)drawImageButton:(CGContextRef)ctx { CGContextRestoreGState(ctx);// 恢复到之前的context CGContextSaveGState(ctx); CGRect rectImage = CGRectMake(_mCenterPoint.x-_mButtonWidth/2, _mCurtainY-_mButtonWidth/2 , _mButtonWidth, _mButtonWidth); [_buttonImage drawInRect:rectImage]; } /** drawString 现在当前进度值 @param mText 显示文本 */ - (void) drawString:(NSString *)mText { NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init]; paragraph.alignment = NSTextAlignmentCenter; NSDictionary *dic = @{NSFontAttributeName : [UIFont systemFontOfSize:_mProgressTextSize], NSForegroundColorAttributeName : _mProgressTextColor, NSParagraphStyleAttributeName : paragraph }; // CGRect textRect = CGRectMake(outsidePoint.x, outsidePoint.y, 80, 20); // [mText drawInRect:textRect withAttributes:dic]; //2019-08-15 修改文字绘制方法,最终实现文本居中效果 CGSize textSize = [mText sizeWithAttributes:dic]; if(_mPercent > 0.3){ CGPoint textPoint = CGPointMake(_mCenterPoint.x - textSize.width/2, _mCurtainY-_mButtonWidth/4 - textSize.height-5);//根据中点坐标绘制 [mText drawAtPoint:textPoint withAttributes:dic]; }else{ CGPoint textPoint = CGPointMake(_mCenterPoint.x - textSize.width/2, _mCurtainY+_mButtonWidth/4 + 5);//根据中点坐标绘制 [mText drawAtPoint:textPoint withAttributes:dic]; } } #pragma mark Touch Event 点击事件 -(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { [super beginTrackingWithTouch:touch withEvent:event]; if(!_isClickable) return YES;//禁止点击 _bTouchMove = NO; _mMoveCount = 0; // CGPoint startPoint = [touch locationInView:self]; // _bIsInArcProgress = [self getStartPointIsInArcProgress:startPoint];//判断开始坐标是否在可点击区域 _bIsInCurtainProgress = YES;//不限制点击区域 [self.mProgressChangedDelegate onStartTrackingTouch]; return YES; } -(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{ [super endTrackingWithTouch:touch withEvent:event]; if(!_isClickable) return;//禁止点击 if(!_bTouchMove){//没移动,仅点击 CGPoint lastPoint = [touch locationInView:self]; [self getCurrentProgressWithLastPoint:lastPoint]; [self sendActionsForControlEvents:UIControlEventValueChanged]; } [self.mProgressChangedDelegate onStopTrackingTouch:_mProgress]; } -(BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { [super continueTrackingWithTouch:touch withEvent:event]; if(!_isClickable) return YES;//禁止点击 if(_mMoveCount < 2){ _mMoveCount++; }else{ _bTouchMove = YES; //开始移动 } if(_bIsInCurtainProgress){//如果刚开始点击的坐标在可点击区域 CGPoint lastPoint = [touch locationInView:self]; [self getCurrentProgressWithLastPoint:lastPoint]; } [self sendActionsForControlEvents:UIControlEventValueChanged]; return YES; } /** 根据坐标计算出当前进度百分比和对应的进度值 @param point 当前坐标 */ -(void)getCurrentProgressWithLastPoint:(CGPoint)point { _mPercent = (point.y - _mCurtainPaddingTop ) / _mCurtainHeight; // NSLog(@"point.y:%f _mCurtainHeight:%f",point.x, _mCurtainWidthHalf); // NSLog(@"_mPercent:%f",_mPercent); // // if(_mPercent > 1){ _mPercent = 1; }else if(_mPercent < 0){ _mPercent = 0; } _mProgress = (1 -_mPercent) * (_mMaxValue - _mMinValue) + _mMinValue; if(_bTouchMove){ [self.mProgressChangedDelegate onProgressChanged:_mProgress]; } [self setNeedsDisplay]; } /** 根据进度值,计算当前 _mProgressAngle值 @param mProgress 进度值 */ -(void)setSeekBarProgressToValue:(int)mProgress{ if(mProgress < _mMinValue){ mProgress = _mMinValue; } if(mProgress > _mMaxValue){ mProgress = _mMaxValue; } _mProgress = mProgress; _mPercent = 1 - (_mProgress - _mMinValue) / (_mMaxValue - _mMinValue); // [self.mProgressChangedDelegate onProgressChanged:_mProgress]; } #pragma mark 设置进度条位置 /** 设置进度值 @param mProgress 进度值 */ -(void)setProgress:(int)mProgress{ [self setSeekBarProgressToValue:mProgress]; [self setNeedsDisplay]; } /** 设置进度显示值单位 @param mString 单位字符 */ -(void)setProgressBarUnitSring:(NSString *)mString{ _mProgressBarUnitSring = mString; } /** 设置最大值最小值 @param mMinValue 最小值 @param mMaxValue 最大值 */ -(void)setMinAndMaxValue:(float)mMinValue mMaxValue:(float)mMaxValue{ if(mMinValue < mMaxValue){ _mMinValue = mMinValue; _mMaxValue = mMaxValue; }else{ _mMinValue = mMaxValue; _mMaxValue = mMinValue; } _mProgress = _mMinValue; _mPercent = 0.0f; } /** 重置布局 @param mCGRect 布局 */ -(void)initWithFrameSeekBar:(CGRect) mCGRect{ self.frame = mCGRect; [self refreshFrame]; } ///** // 设置边距 // */ //-(void)setCurtainPadding:(int)Padding{ // _mCurtainPadding = Padding; // [self onCurtainSizeChange]; //} // // ///** // 设置顶部边距 // */ //-(void)setCurtainPaddingTop:(int)Padding{ // _mCurtainPaddingTop = Padding; // [self onCurtainSizeChange]; //} /** 设置是否离线 */ -(void)setOffline:(BOOL)isOffline{ _isOffline = isOffline; _isClickable = !_isOffline; [self setNeedsDisplay]; } /** 获取高度 Y值 */ -(CGFloat)getProgressY{ return _mCurtainY; } /** 设置百叶窗类型 */ -(void)setBlindsType:(BOOL)isBlindsType{ _isBlindsType = isBlindsType; if(!_isBlindsType){ _curtainImage = [UIImage imageNamed:@"ic_wd_on_curtain_roll_progress"]; _curtainImage_close = [UIImage imageNamed:@"ic_wd_on_curtain_roll_progress_close"]; }else{ _curtainImage = [UIImage imageNamed:@"ic_wd_on_curtain_blinds_progress"]; _curtainImage_close = [UIImage imageNamed:@"ic_wd_on_curtain_blinds_progress_close"]; } [self onCurtainSizeChange]; [self setNeedsDisplay]; } @end