iOS实现垂直滑动条效果

iOS实现垂直滑动条效果

我们知道在 iOS 开发中,有一个控件经常用到,那就是滑动条(UISlider),可以满足我们滑动取值的需求。但是现在有一个需求,就是需要一个垂直的滑动条,而 UISlider 并不能设置为垂直滑动,所以我们就需要自己定义一个控件来实现垂直的要求。

整理之后,我们可以得出需要以下的基本需求:

可以上下滑动

按钮可以自定义图片

可以设置最小值

可以设置最大值

可以在滑动过程中获取实时的值

可以在滑动结束时获取到最终的值

可以设置进度背景色

我们的实现原理就是实现一个自定义的 UIView,然后在上面添加需要用到的控件,对控件添加一定的手势功能,从而实现垂直滑动。实现了一个单独的类,功能不多,但是能满足以上基本的需求,代码如下,代码中用到的宏可以自行替换,开箱即用,简单明了:

VerticalSlider.h

// //  VerticalSlider.h //   // //  Created by huang zhengguo on 2019/8/30. //  Copyright © 2019 huang zhengguo . All rights reserved. // #import <UIKit/UIKit.h> 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];         // 初始化数据         self.value = 0.0;     }     return self; } #pragma mark --- 按钮拖动方法 - (void)thumbPanAction:(UIPanGestureRecognizer *)panGestureRecognizer {     // 转换坐标     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);         }     }     // 转换成原来坐标系的坐标     [panGestureRecognizer setTranslation:CGPointMake(0, 0) inView:self];     if (panGestureRecognizer.state == UIGestureRecognizerStateEnded) {         if (self.passEndValue) {             KMYLOG(@"结束滑动");             // 转为字符串,又转为float,是为了去的两位小数的浮点数             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

推荐阅读

    计算机主板BIOS设置详细-BIOS知识

    计算机主板BIOS设置详细-BIOS知识,,什么是电脑BIOS,一般电脑主板已经设置完毕后,电脑就开始按del键进入BIOS。系统启动BIOS,即微机的基本输入

    6s 32G能升级到ios14吗

    6s 32G能升级到ios14吗,手机,系统,6s 32G能升级到ios14吗可以,但是ios14更新以后会占用10左右储存,还有系统没有完全汉化,如果没接受,也就可以

    三常见BIOS故障排除解决方案

    三常见BIOS故障排除解决方案,,笔记本电脑如何长时间出现黑屏为什么为什么如何删除和修改旧IBM笔记本电脑BIOS设置中的密码我想你会与这些

    联想bios设置图解|联想bios设置方法

    联想bios设置图解|联想bios设置方法,,联想bios设置方法1.首先我们打开电脑,当开机标识出现或者电脑开机时,连续使用键盘“DEL”进入BIOS设置

    coc进度转电脑ios|coc快速升级

    coc进度转电脑ios|coc快速升级,,1. coc快速升级1、 首先,你要知道并学会“刷墙”。它的意思是尽量给城墙多升升级,免得你防御很强,但

    dellu盘启动设置|dellu盘启动bios设置

    dellu盘启动设置|dellu盘启动bios设置,,1. dellu盘启动bios设置1、插入U盘,开机按F2进BIOS,也可以先按F12进这个界面,然后选择BIOS Setup回车

    串口硬盘bios设置|BIOS设置硬盘

    串口硬盘bios设置|BIOS设置硬盘,,1. BIOS设置硬盘接好SATA硬盘后,开机,按Del键进入CMOS设置界面;按键盘上的TAB键和方向键,进入integrated

    bios设置电源管理|Bios电源设置

    bios设置电源管理|Bios电源设置,,1. Bios电源设置电脑开机显示没有检测到开机设备,这是因为计算机的硬盘损坏导致的,因为计算机在开机自检的