由于项目需要实现一个垂直的Slider,滑动条使用UIlabel实现,按钮使用UIButton,按钮可以设置背景图片,代码如下

VerticalSlider.h

//
// VerticalSlider.h
// EXOTerra
//
// Created by huang zhengguo on 2019/8/30.
// Copyright © 2019 Inledco. 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 thumImage 滑动按钮背景
*
* @return 垂直滑动条
*
*/
- (instancetype)initWithFrame:(CGRect)frame title:(NSString *)title thumImage:(NSString *)thumImage; @end NS_ASSUME_NONNULL_END

VerticalSlider.m

//
// VerticalSlider.m
// EXOTerra
//
// Created by huang zhengguo on 2019/8/30.
// Copyright © 2019 Inledco. 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 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 = [UIColor darkGrayColor];
self.backLabel.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:self.backLabel]; self.progressLabel = [[UILabel alloc] init]; self.progressLabel.backgroundColor = [UIColor blueColor];
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(, ) 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) * ( - 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 * ];
} - (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) * ( - 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

iSO垂直滑动条VerticalSlider的更多相关文章

  1. 第15.44节、PyQt输入部件:QAbstractSlider派生类QScrollBar滚动条、QSlider滑动条、QDial刻度盘功能详解

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.引言 Designer中的输入部件Horizo ...

  2. 第三十七章、PyQt输入部件:QAbstractSlider派生类QScrollBar滚动条、QSlider滑动条、QDial刻度盘功能介绍

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.引言 Designer中的输入部件Horizo ...

  3. Slider 滑动条效果

    转载自:http://www.cnblogs.com/cloudgamer/archive/2008/12/24/Slider.html 这个滑动条(拖动条)效果,一开始是参考了BlueDestiny ...

  4. 疯狂JAVA讲义---第十二章:Swing编程(五)进度条和滑动条

    http://blog.csdn.net/terryzero/article/details/3797782 疯狂JAVA讲义---第十二章:Swing编程(五)进度条和滑动条 标签: swing编程 ...

  5. Qt基础学习---滑动条之QSlider

    Qt滑动条基本用法: //mydialog.h #ifndef MYDIALOG_H #define MYDIALOG_H #include <QDialog> class QLineEd ...

  6. 滑动条QSlider

    QSlider只提供整数范围 滑块接受Tab键的焦点,并同时提供了一个鼠标滚轮和键盘接口.键盘接口如下: Left/Right 移动水平滑块一个步长.Up/Down 移动垂直滑块一个步长.PageUp ...

  7. Android中ViewPager实现滑动条及与Fragment结合的实例教程

    ViewPager类主要被用来实现可滑动的视图功能,这里我们就来共同学习Android中ViewPager实现滑动条及与Fragment结合的实例教程,需要的朋友可以参考下 自主实现滑动指示条先上一个 ...

  8. 第二百二十节,jQuery EasyUI,Slider(滑动条)组件

    jQuery EasyUI,Slider(滑动条)组件 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI 中 Slider(滑动条)组件的使用方法,这个 ...

  9. Win10 UI入门 导航滑动条 求UWP工作

    借鉴了 段博琼 大哥写的导航滑动,自己实现了一个类似安卓 IOS 导航滑动条 支持等比例 分割 tabView 支持动画滑动 效果如下图 WYGrid 你可以想象一个GridView  itemsWr ...

随机推荐

  1. poj 2689 Prime Distance (素数二次筛法)

    2689 -- Prime Distance 没怎么研究过数论,还是今天才知道有素数二次筛法这样的东西. 题意是,要求求出给定区间内相邻两个素数的最大和最小差. 二次筛法的意思其实就是先将1~sqrt ...

  2. Ubuntu 18.04LTS安装配置Java OpenJDK8

    安装OpenJDK8 sudo apt-get install openjdk-8-jdk 配置Java环境变量 sudo vim /etc/profile 在profile末尾添加以下内容: exp ...

  3. Hibernate懒加载导致json数据对象传输异常的问题---(非常重要)

    1. 异常: [console_demo][WARN] [2016-12-15 19:49:35] org.springframework.web.servlet.mvc.support.Defaul ...

  4. 一个div居于另一个div底部

    一个div如何与另一个div底部对齐,方法有很多,比如使用绝对定位 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional/ ...

  5. 洛谷P2590 [ZJOI2008]树的统计 题解 树链剖分+线段树

    题目链接:https://www.luogu.org/problem/P2590 树链剖分模板题. 剖分过程要用到如下7个值: fa[u]:u的父节点编号: dep[u]:u的深度: size[u]: ...

  6. 2017年NOIP普及组复赛题解

    题目涉及算法: 成绩:入门题: 图书管理员:模拟: 棋盘:最短路/广搜: 跳房子:RMQ/二分答案/DP(本人解法). 成绩 题目链接:https://www.luogu.org/problemnew ...

  7. 2009年NOIP普及组复赛题解

    题目涉及算法: 多项式输出:模拟: 分数线划定:模拟.排序: 细胞分裂:质因数分解: 道路游戏:动态规划. 多项式输出 题目链接:https://www.luogu.org/problem/P1067 ...

  8. Python--day65--模板语言之filter

    参考的原文链接:http://www.cnblogs.com/liwenzhou/p/7931828.html Filters(过滤器) 在Django的模板语言中,通过使用 过滤器 来改变变量的显示 ...

  9. [C++] 获取IE代理服务器的账号密码

    很多程序需要使用'浏览器设置'的代理服务器,IE设置的代理服务器有可能是需要账号密码的.怎样编程获取浏览器设置的代理服务器的账号密码呢? InternetQueryOption(NULL, INTER ...

  10. Js中“==”和“===”的区别

    从字面上来讲,‘==’代表相等,‘===’代表严格相等. 具体来讲,比较过程如下: 比较过程: ‘==’:      1. 首先判断两个值的类型是否相同,如果相同,进行‘===’判断.      2. ...