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 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 = https://www.it610.com/article/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 = https://www.it610.com/article/1.0 - (yOriginPoint - self.backLabel.frame.origin.y) / (self.backLabel.frame.size.height - THUM_BTN_HEIGHT); if (self.passValue) {KMYLOG(@"colorValue = https://www.it610.com/article/%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 = https://www.it610.com/article/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

【iOS实现垂直滑动条效果】以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    推荐阅读