網(wǎng)站首頁 編程語言 正文
我們知道在 iOS 開發(fā)中,有一個控件經(jīng)常用到,那就是滑動條(UISlider),可以滿足我們滑動取值的需求。但是現(xiàn)在有一個需求,就是需要一個垂直的滑動條,而 UISlider 并不能設(shè)置為垂直滑動,所以我們就需要自己定義一個控件來實現(xiàn)垂直的要求。
整理之后,我們可以得出需要以下的基本需求:
- 可以上下滑動
- 按鈕可以自定義圖片
- 可以設(shè)置最小值
- 可以設(shè)置最大值
- 可以在滑動過程中獲取實時的值
- 可以在滑動結(jié)束時獲取到最終的值
- 可以設(shè)置進度背景色
我們的實現(xiàn)原理就是實現(xiàn)一個自定義的 UIView,然后在上面添加需要用到的控件,對控件添加一定的手勢功能,從而實現(xiàn)垂直滑動。實現(xiàn)了一個單獨的類,功能不多,但是能滿足以上基本的需求,代碼如下,代碼中用到的宏可以自行替換,開箱即用,簡單明了:
VerticalSlider.h
// // ?VerticalSlider.h // ? // // ?Created by huang zhengguo on 2019/8/30. // ?Copyright ? 2019 huang zhengguo . All rights reserved. // ? #import? NS_ASSUME_NONNULL_BEGIN ? @interface VerticalSlider : UIView ? @property (assign, nonatomic) float value; @property (strong, nonatomic) UIImage *thumImage; @property (assign, nonatomic) float minimumValue; @property (assign, nonatomic) float maximumValue; ? @property (copy, nonatomic) void (^passValue) (float); @property (copy, nonatomic) void (^passEndValue) (float); ? /** ?* 初始化滑動條 ?* ?* @param frame 大小 ?* @param title 標題 ?* @param progressColor 進度顏色 ?* @param thumImage 滑動按鈕背景 ?* ?* @return 垂直滑動條 ?* ?*/ - (instancetype)initWithFrame:(CGRect)frame title:(NSString *)title progressColor:(UIColor *)progressColor thumImage:(NSString *)thumImage; ? @end ? NS_ASSUME_NONNULL_END
VerticalSlider.m
// // ?VerticalSlider.m //? // // ?Created by huang zhengguo on 2019/8/30. // ?Copyright ? 2019 zhengguohuang. All rights reserved. // ? #import "VerticalSlider.h" ? #define THUM_BTN_WIDTH 30.0 #define THUM_BTN_HEIGHT 50.0 ? @interface VerticalSlider() ? @property (strong, nonatomic) UIButton *thumBtn; // 使用兩個label表示進度,一個背景,一個進度 @property (strong, nonatomic) UILabel *backLabel; @property (strong, nonatomic) UILabel *progressLabel; // 底部標題 @property (strong, nonatomic) UILabel *titleLabel; // 值標題 @property (strong, nonatomic) UILabel *valueLabel; ? @end ? @implementation VerticalSlider ? - (instancetype)initWithFrame:(CGRect)frame title:(NSString *)title progressColor:(UIColor *)progressColor thumImage:(NSString *)thumImage { ? ? if (self = [super initWithFrame:frame]) { ? ? ? ? // 滑動按鈕 ? ? ? ? self.thumBtn = [[UIButton alloc] init]; ? ? ? ? ? [self.thumBtn setBackgroundImage:[UIImage imageNamed:thumImage] forState:UIControlStateNormal]; ? ? ? ? self.thumBtn.translatesAutoresizingMaskIntoConstraints = NO; ? ? ? ?? ? ? ? ? UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(thumbPanAction:)]; ? ? ? ? ? [self.thumBtn addGestureRecognizer:panGestureRecognizer]; ? ? ? ? [self addSubview:self.thumBtn]; ? ? ? ? ? // 進度條 ? ? ? ? self.backLabel = [[UILabel alloc] init]; ? ? ? ? ? self.backLabel.backgroundColor = [progressColor colorWithAlphaComponent:0.3]; ? ? ? ? self.backLabel.translatesAutoresizingMaskIntoConstraints = NO; ? ? ? ? ? [self addSubview:self.backLabel]; ? ? ? ? ? self.progressLabel = [[UILabel alloc] init]; ? ? ? ? ? self.progressLabel.backgroundColor = progressColor; ? ? ? ? self.progressLabel.translatesAutoresizingMaskIntoConstraints = NO; ? ? ? ? ? [self addSubview:self.progressLabel]; ? ? ? ? ? // 底部標題 ? ? ? ? self.titleLabel = [[UILabel alloc] init]; ? ? ? ? ? self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO; ? ? ? ? self.titleLabel.textAlignment = NSTextAlignmentCenter; ? ? ? ? self.titleLabel.textColor = [UIColor whiteColor]; ? ? ? ? self.titleLabel.text = title; ? ? ? ? ? [self addSubview:self.titleLabel]; ? ? ? ? ? // 頂部值 ? ? ? ? self.valueLabel = [[UILabel alloc] init]; ? ? ? ? ? self.valueLabel.translatesAutoresizingMaskIntoConstraints = NO; ? ? ? ? self.valueLabel.textAlignment = NSTextAlignmentCenter; ? ? ? ? self.valueLabel.textColor = [UIColor whiteColor]; ? ? ? ? ? [self addSubview:self.valueLabel]; ? ? ? ? ? [self bringSubviewToFront:self.thumBtn]; ? ? ? ? ? [self setConstraints]; ? ? ? ?? ? ? ? ? // 初始化數(shù)據(jù) ? ? ? ? self.value = 0.0; ? ? } ? ?? ? ? return self; } ? #pragma mark --- 按鈕拖動方法 - (void)thumbPanAction:(UIPanGestureRecognizer *)panGestureRecognizer { ? ? // 轉(zhuǎn)換坐標 ? ? CGPoint point = [panGestureRecognizer translationInView:self]; ? ?? ? ? CGFloat yOriginPoint = panGestureRecognizer.view.frame.origin.y + point.y; ? ? if (yOriginPoint >=self.backLabel.frame.origin.y && yOriginPoint <= (self.backLabel.frame.origin.y + self.backLabel.frame.size.height - THUM_BTN_HEIGHT)) { ? ? ? ? panGestureRecognizer.view.frame = CGRectMake(panGestureRecognizer.view.frame.origin.x, panGestureRecognizer.view.frame.origin.y + point.y, THUM_BTN_WIDTH, THUM_BTN_HEIGHT); ? ? ? ?? ? ? ? ? self.value = 1.0 - (yOriginPoint - self.backLabel.frame.origin.y) / (self.backLabel.frame.size.height - THUM_BTN_HEIGHT); ? ? ? ? if (self.passValue) { ? ? ? ? ? ? KMYLOG(@"colorValue = %f", self.value); ? ? ? ? ? ? self.passValue(self.value); ? ? ? ? } ? ? } ? ? ? // 轉(zhuǎn)換成原來坐標系的坐標 ? ? [panGestureRecognizer setTranslation:CGPointMake(0, 0) inView:self]; ? ?? ? ? if (panGestureRecognizer.state == UIGestureRecognizerStateEnded) { ? ? ? ? if (self.passEndValue) { ? ? ? ? ? ? KMYLOG(@"結(jié)束滑動"); ? ? ? ? ? ? // 轉(zhuǎn)為字符串,又轉(zhuǎn)為float,是為了去的兩位小數(shù)的浮點數(shù) ? ? ? ? ? ? self.passEndValue([[NSString stringWithFormat:@"%.2f", self.value] floatValue]); ? ? ? ? } ? ? } } ? - (void)setValue:(float)value { ? ? _value = value; ? ? ? self.thumBtn.frame = CGRectMake(self.thumBtn.frame.origin.x, (self.backLabel.frame.size.height - THUM_BTN_HEIGHT) * (1 - value) + self.backLabel.frame.origin.y, THUM_BTN_WIDTH, THUM_BTN_HEIGHT); ? ? self.progressLabel.frame = CGRectMake(self.progressLabel.frame.origin.x, self.thumBtn.frame.origin.y + THUM_BTN_HEIGHT, self.progressLabel.frame.size.width, self.backLabel.frame.origin.y + self.backLabel.frame.size.height - self.thumBtn.frame.origin.y - THUM_BTN_HEIGHT); ? ? self.valueLabel.text = [NSString stringWithFormat:@"%.0f%%", value * 100]; } ? - (void)setConstraints { ? ? NSArray *titleLabelArray = @[self.titleLabel, self.valueLabel]; ? ? for (UILabel *label in titleLabelArray) { ? ? ? ? NSLayoutConstraint *labelLeadingLayoutConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0.0]; ? ? ? ? NSLayoutConstraint *labelTrailingLayoutConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0]; ? ? ? ? NSLayoutConstraint *labelHeightLayoutConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:30.0]; ? ? ? ? ? [self addConstraints:@[labelLeadingLayoutConstraint, labelTrailingLayoutConstraint, labelHeightLayoutConstraint]]; ? ? ? ? ? if (label == self.titleLabel) { ? ? ? ? ? ? NSLayoutConstraint *labelBottomLayoutConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]; ? ? ? ? ? ? ? [self addConstraint:labelBottomLayoutConstraint]; ? ? ? ? } else if (label == self.valueLabel) { ? ? ? ? ? ? NSLayoutConstraint *labelTopLayoutConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]; ? ? ? ? ? ? ? [self addConstraint:labelTopLayoutConstraint]; ? ? ? ? } ? ? } ? ?? ? ? NSArray *labelArray = @[self.backLabel, self.progressLabel]; ? ? for (UILabel *label in labelArray) { ? ? ? ? NSLayoutConstraint *progressCenterXLayoutConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]; ? ? ? ? NSLayoutConstraint *progressBottomLayoutConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.titleLabel attribute:NSLayoutAttributeTop multiplier:1.0 constant:-8.0]; ? ? ? ? NSLayoutConstraint *progressWidthLayoutConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:3.0]; ? ? ? ? ? [self addConstraints:@[progressCenterXLayoutConstraint, progressBottomLayoutConstraint, progressWidthLayoutConstraint]]; ? ? ? ? ? if (label == self.backLabel) { ? ? ? ? ? ? NSLayoutConstraint *progressTopLayoutConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.valueLabel attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]; ? ? ? ? ? ? ? [self addConstraint:progressTopLayoutConstraint]; ? ? ? ? } else { ? ? ? ? ? ? NSLayoutConstraint *progressHeightLayoutConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0.0]; ? ? ? ? ? ? ? [self addConstraint:progressHeightLayoutConstraint]; ? ? ? ? } ? ? } ? ? ? NSLayoutConstraint *thumBtnCenterXLayoutConstraint = [NSLayoutConstraint constraintWithItem:self.thumBtn attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]; ? ? NSLayoutConstraint *thumBtnBottomLayoutConstraint = [NSLayoutConstraint constraintWithItem:self.thumBtn attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.backLabel attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]; ? ? NSLayoutConstraint *thumBtnWidthLayoutConstraint = [NSLayoutConstraint constraintWithItem:self.thumBtn attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:THUM_BTN_WIDTH]; ? ? NSLayoutConstraint *thumBtnHeightLayoutConstraint = [NSLayoutConstraint constraintWithItem:self.thumBtn attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:THUM_BTN_HEIGHT]; ? ? ? [self addConstraints:@[thumBtnCenterXLayoutConstraint, thumBtnBottomLayoutConstraint, thumBtnWidthLayoutConstraint, thumBtnHeightLayoutConstraint]]; } ? - (void)layoutSubviews { ? ? [super layoutSubviews]; ? ?? ? ? self.thumBtn.frame = CGRectMake(self.thumBtn.frame.origin.x, (self.backLabel.frame.size.height - THUM_BTN_HEIGHT) * (1 - self.value) + self.backLabel.frame.origin.y, THUM_BTN_WIDTH, THUM_BTN_HEIGHT); ? ? self.progressLabel.frame = CGRectMake(self.progressLabel.frame.origin.x, self.thumBtn.frame.origin.y + THUM_BTN_HEIGHT, self.progressLabel.frame.size.width, self.backLabel.frame.origin.y + self.backLabel.frame.size.height - self.thumBtn.frame.origin.y - THUM_BTN_HEIGHT); } ? /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { ? ? // Drawing code } */ ? @end
原文鏈接:https://blog.csdn.net/hzgisme/article/details/116017885
相關(guān)推薦
- 2022-10-25 C++構(gòu)建函數(shù)使用介紹_C 語言
- 2022-09-17 利用Python提取PDF文本的簡單方法實例_python
- 2022-04-21 C語言中隨機數(shù)rand()函數(shù)詳解_C 語言
- 2022-09-26 tomcat下載安裝及配置環(huán)境變量,但打開startup文件出現(xiàn)閃退問題解決方法
- 2023-07-02 Linux系統(tǒng)下如何實現(xiàn)修改主機名_Linux
- 2022-10-19 Beego?AutoRouter工作原理解析_Golang
- 2022-07-29 Linux中Vi和Vim編輯器用法詳解_linux shell
- 2023-03-21 C#中[]的幾種用法示例代碼_C#教程
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支