【仿汽车之家】价格区间选择控件
仿照汽车之家iOS客户端“找车”栏目的价格区间选择控件,最终实现效果如下:
一、界面实现
*根据屏幕大小以及刻度的大小,宏定义需要用到的一些值
#define SCREENW [UIScreen mainScreen].bounds.size.width
#define SCREENH [UIScreen mainScreen].bounds.size.height
#define PRICEBGW 271.0
#define PRICEBGH 21.0
#define PRICEBGX (SCREENW - PRICEBGW)*0.5
#define PRICEBGY (SCREENH - PRICEBGH)*0.5
#define PRICEMAX (SCREENW*0.5 + PRICEBGW*0.44)
#define PRICEMIN (SCREENW*0.5 - PRICEBGW*0.45)
#define NODE1 (PRICEBGX + 103)
项目中用了两张图片,一张是刻度图(紫色框中的UIIMageView,图片命名为priceRuler@2x.png),一张是把手图(两个红色框内分别有一个UIIMageView,图片命名为xiabashou@2x.png),蓝色框内的进度条,使用一个UIView来实现,而使用UILabel来显示用户选择的数值范围。
priceRuler@2x.png
xiabashou@2x.png
我们把界面实现的代码写到一个函数中,函数名为setUpView,并在viewDidLoad中调用。
-(void)setUpView{//数值显示resultLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, SCREENW, 60)];[resultLabel setTextAlignment:NSTextAlignmentCenter];[resultLabel setFont:[UIFont systemFontOfSize:18]];[self.view addSubview:resultLabel];//刻度图UIImageView *priceBg = [[UIImageView alloc] initWithFrame:CGRectMake(PRICEBGX, PRICEBGY, PRICEBGW, PRICEBGH)];[priceBg setImage:[UIImage imageNamed:@"priceBg"]];[self.view addSubview:priceBg];//蓝色进度条progressView = [[UIView alloc] initWithFrame:CGRectMake(PRICEBGX, CGRectGetMaxY(priceBg.frame)-2, PRICEBGW, 2.f)];[progressView setBackgroundColor:[UIColor colorWithRed:30.0/255.0 green:144.0/255.0 blue:255.0/255.0 alpha:1.0]];[self.view addSubview:progressView];//左把手CGFloat commonHandImageViewW = 20.f;CGFloat commonHandImageViewH = 25.f;CGFloat leftHandImageViewX = PRICEBGX - commonHandImageViewW*0.5;CGFloat leftHandImageViewY = PRICEBGY + commonHandImageViewH;leftHandImageView = [[UIImageView alloc] initWithFrame:CGRectMake(leftHandImageViewX, leftHandImageViewY, commonHandImageViewW, commonHandImageViewH)];[leftHandImageView setImage:[UIImage imageNamed:@"xiabashou"]];[self.view addSubview:leftHandImageView];//右把手CGFloat rightHandImageViewX = CGRectGetMaxX(priceBg.frame) - commonHandImageViewW*0.5;CGFloat rightHandImageViewY = leftHandImageViewY;rightHandImageView = [[UIImageView alloc] initWithFrame:CGRectMake(rightHandImageViewX, rightHandImageViewY, commonHandImageViewW, commonHandImageViewH)];[rightHandImageView setImage:[UIImage imageNamed:@"xiabashou"]];[self.view addSubview:rightHandImageView];}
现在运行项目,已经可以看到一个区间选择器了,但是我们在屏幕进行任意拖动操作,界面并没有任何改变。因此我们需要使得app能够响应我们的手势。
二、响应用户手势
为了响应用户的拖动手势,给两个把手(UIIMageView)分别添加滑动手势识别(UIPanGestureRecognizer)。我们在setUpView中继续添加如下代码
-(void)setUpView{….….//给左把手添加滑动手势识别UIPanGestureRecognizer *leftPanRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(leftHandMove:)];[leftPanRecognizer setMinimumNumberOfTouches:1];[leftPanRecognizer setMaximumNumberOfTouches:1];[leftHandImageView setUserInteractionEnabled:YES];[leftHandImageView addGestureRecognizer:leftPanRecognizer];//给右把手添加滑动手势识别UIPanGestureRecognizer *rightPanRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(rightHandMove:)];[rightHandImageView setUserInteractionEnabled:YES];[rightHandImageView addGestureRecognizer:rightPanRecognizer];}
实现leftHandMove:和rightHandMove:方法,处理滑动事件:
-(void)leftHandMove:(UIPanGestureRecognizer *)pan{CGPoint point = [pan translationInView:leftHandImageView];CGFloat x = leftHandImageView.center.x + point.x;if(x > PRICEMAX){x = PRICEMAX;}else if (x< PRICEBGX ){x = PRICEBGX;}leftHandImageView.center = CGPointMake(ceilf(x), leftHandImageView.center.y);[pan setTranslation:CGPointZero inView:self.view];
}
-(void)rightHandMove:(UIPanGestureRecognizer *)pan{CGPoint point = [pan translationInView:rightHandImageView];CGFloat x = rightHandImageView.center.x + point.x;if(x>PRICEBGX+PRICEBGW){x = PRICEBGX+PRICEBGW;}else if (x<PRICEMIN){x = PRICEMIN;}rightHandImageView.center = CGPointMake(ceilf(x), rightHandImageView.center.y);}
在leftHandMove:方法中,我们使用translationInView函数,得到在指定的View坐标系中的改变值point,将原来的x坐标值加上改变的值后,若超出符合要求的刻度范围,我们要设置其为边界值,然后再更新把手的位置,否则直接更新即可。rightHandMove:同理实现。
尝试运行项目并拖动把手,现在把手的位置可以水平拖动了,但是UILabel还没有显示我们选中的范围,蓝色进度条也没随之改变。
三、更新数值显示和蓝色进度条
为了得到上一步中用户选中的值,我们先声明两个个全局变量:
float leftValue;
float rightValue;
- (void)viewDidLoad {[super viewDidLoad];leftValue = 0;rightValue = 100;[self setUpView];
}
<pre code_snippet_id="1582410" snippet_file_name="blog_20160219_8_6433823" name="code" class="objc">-(void)leftHandMove:(UIPanGestureRecognizer *)pan{……leftValue = x;
</pre><pre code_snippet_id="1582410" snippet_file_name="blog_20160219_9_4132529" name="code" class="objc">}
现在,我们写一个更新数值和进度条的函数,函数名为updateData。
-(void)updateData{[resultLabel setText:[NSString stringWithFormat:@"%.0f~%.0f",leftValue,rightValue]];}
我们再一次运行程序,滑动手柄,数值虽然改变了,但并不是我们想要的价格数值!!
这是因为屏幕的坐标和刻度图的坐标范围并不一致,因此我们需要将数据处理一下。可能你已经发现,刻度图中的范围并不是均匀分布的,而是分成三段:0~25、25~40、40~100。因此我们在处理时需要分段处理。
我们写一个将左边转换为价格的转换函数:
//坐标->价格
-(CGFloat)x2price:(CGFloat)x{CGFloat price = 0.f;//<5if(x < PRICEMIN){price = 0;}//5~25else if (x < PRICEBGX + 133){price = (x - PRICEMIN) / 120 * 20 + 5;}//25~40else if (x < PRICEBGX + 163){price = (x - PRICEBGX - 133) *0.5 + 25;}//40~100else if (x < PRICEBGX + 253){price = (x - PRICEBGX - 163) * 2 / 3 + 40;}//100+else{price = 100;}return price;
}
将leftHandMove:中的leftValue = x;修改为如下
-(void)leftHandMove:(UIPanGestureRecognizer *)pan{……leftValue = [self x2price:ceilf(x)];
}
同理rightHandMove:也做相应处理。重新运行程序,滑动把手,显示的价格数值正是我们所期望的。
我们还要更新蓝色进度条,只需修改它的frame即可:
-(void)updateData{[resultLabel setText:[NSString stringWithFormat:@"%.0f~%.0f",leftValue,rightValue]];CGRect progressRect = CGRectMake(leftHandImageView.center.x, progressView.frame.origin.y, rightHandImageView.center.x - leftHandImageView.center.x, progressView.frame.size.height);progressView.frame = progressRect;
}
四、优化
当将右边的把手一直往左滑动,它将滑到左边把手的左边,也就是用户选择的区间中,上界值比下界值更小了!这并不是我们期望的结果。我们希望上界至少要比下界大1个单位,所以当用户滑动右把手到上界比下界小于等于1时,左把手也要跟着滑动,与右把手始终保持1个单位。
我们在rightHandMove:函数中添加如下代码:
-(void)rightHandMove:(UIPanGestureRecognizer *)pan{……if (rightValue-leftValue <= 1) {leftValue = rightValue - 1;leftHandImageView.center = CGPointMake([self price2x:leftValue], leftHandImageView.center.y);}}
同理在leftHandMove:函数中添加对应代码:
-(void)leftHandMove:(UIPanGestureRecognizer *)pan{……if (rightValue-leftValue <= 1) {rightValue = leftValue + 1;rightHandImageView.center = CGPointMake([self price2x:rightValue], rightHandImageView.center.y);}}
注意到函数中用到了方法price2x:,这个函数是将价格转换为对应的x坐标,作用于前面用到的x2price:刚好相反。
//价格->坐标
-(CGFloat)price2x:(CGFloat)price{CGFloat x;//<5if (price<5) {x = PRICEBGX;}//5~25else if (price >= 5 && price < 25) {x = (price-5) * 6 + PRICEMIN;}//25~40else if (price >= 25 && price <40) {x = (price-25) * 2 + 133 + PRICEBGX;}//40~100else if (price >=40 && price <100){x = (price-40) * 3/2 +163 + PRICEBGX;}else if(price >= 100){x = PRICEBGX + PRICEBGW;}return x;
}
运行程序,现在已经不能将右把手拖动到左把手的前面的吧~
完整源代码下载:http://download.csdn.net/detail/dolacmeng/9436673
相关文章:

Apache服务器部署(2)
签名CA证书 环境:server1:172.25.1.1 重置虚拟机 挂载yum源 [rootserver1 ~]# yum install mod_ssl -y //下载ssl模块 [rootserver1 ~]# yum install crypto-utils -y //安装加密软件 [rootserver1 ~]# genkey …

ASCII、Unicode、GBK和UTF-8字符编码的区别联系
一直对编码这块晕晕乎乎,今天终于看到一篇写的很清楚也很风趣的文章,转过来mark一下。 很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物。他们看到8个开关状态是好的&…
【iOS】快速集成轮播控件
自己写的一个轮播控件,初始化后只要实现两个数据源方法,几行代码就能快速集成,支持本地图片和网络图片,支持点击事件,可定制播放速度、指示器颜色/位置、默认加载图等,效果: 1.下载地址…

Hibernate中get方法和load方法的区别
一、get和load方法都是根据id去获得对应数据的,但是获得机制不同:如果使用get方法,hibernate会去确认该id对应的数据是否存在,它首先会去session中去查询(session缓存其实就hibernate的一级缓存),如果没有,…

DNS高速缓存
DNS相关资料: 1.什么是DNS DNS(Domain Name System域名系统) 是互联网上存储域名和ip映射关系的一个分布式数据库,它负责把域名转换成ip地址,或ip地址转换为域名。DNS运行于TCP/UDP的53端口上。 2.什么是高速…

将时间改为显示:几天前,几小时前,或者几分钟前
(原博客地址:http://blog.csdn.net/kenhins/article/details/38010811) 方法一: 个人做法是保存时间戳,然后在前端用jq插件做转换,比如 smart-time-ago ----------------------------------------------- 方…
支持placeholder和自适配高度的TextView控件
一.应用于项目的效果如下: 二.使用方法: 1.导入JXTextView.h头文件 2.初始化,并添加到view中: JXTextView *textView [[JXTextView alloc] initWithFrame:CGRectMake(10, 10, 200, 30)];textView.placeholder "请输入内容";tex…

ZOJ 3735 dp
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode3735 好久没做DP题了,一开始没理解题目里的C(M,3)是干什么,原来就是组合,C M 取3,就等于n*(n-1)*(n-2)/6;题目里还有…

haproxy实现高可用及负载均衡
Haproxy简介: Haproxy是一个使用c语言编写的自由开发源代码软件,它提供高可用性、负载均衡、以及基于http和tcp的应用程序代理。Haproxy特别使用于那些负载特别大的web站点。Haproxy运行在当前的硬件上,完全可以支持数以万计的并发连接&#…

Apache转发到Tomcat
#vi /etc/httpd/conf/httpd.conf 添加下面配置 NameVirtualHost *:80 <VirtualHost *:80>ProxyPreserveHost OnServerName www.域名.comProxyPass / http://www.域名.com:8080/system/ErrorLog logs/error_logCustomLog logs/access_log common</VirtualHost> 作者…

.net基础问题
string sqlstr "select BranchCode,BranchName from t_sys_Branch where Jglx_DataDm{0} and IsVisible1"; sqlstr string.Format(sqlstr, departType); 上述代码运行之后 sqlstr"select BranchCode,BranchName from t_sys_Branch where Jglx_DataDmdepartTyp…
【iOS】NSDate分类,获得中国农历
1.说明: 参考网上代码写的一个分类,只需一句代码就可得到NSDate对象所对应的中国农历、星期。 2.使用方法: (1)导入分类头文件: #import "NSDateChineseDate.h"(2)NSDat…

LVS_NAT实现负载均衡
简介: 基于NAT机制实现。当用户请求到达director之后,director将请求报文的目标地址(即VIP)改成选定的realserver地址,同时将报文的目标端口也改成选定的realserver的相应端口,最后将报文请求发送到指定的realserver;…
自定义Push和Pop过渡动画
一、效果和源码 本文介绍如何实现一个NavigationController的自定义Push和Pop过渡动画,运行效果如下: 源码:https://github.com/dolacmeng/TransitionDemo 或http://download.csdn.net/detail/dolacmeng/9572384二、准备工作 首先࿰…

centos 安装 mysql 5.7
一,wget http://dev.mysql.com/get/mysql57-community-release-el6-8.noarch.rpm 二,yum localinstall mysql57-community-release-el6-8.noarch.rpm 三,yum install mysql-server 四,mysqld --initialize --usermysql 五…

c语言:婚礼上的谎言
/* 三对新人参加婚礼,三位新郎A,B,C,三位新娘X,Y,Z。 有人想知道谁与谁结婚,于是就问他们: A说他将和X结婚; X说他的未婚夫是C; C说他将和Z结婚。 这人时候知道他们都在说谎。编程求谁与谁结婚! */ /* 思路…

redis主从复制、高可用和集群
redis简介: redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hashs(哈希类型);这些数据类型都支持push/pop、…

对学习编译原理的看法
我认为编译原理这本书是一门与代码做斗争的课程,学习编译原理能够追寻程序设计语言的本质,了解计算机各种语言编译的原理。学习了编译原理能够更加深入的了解计算机各种高级语言使用的原理,能使自己更加容易更加好的学习好程序语言࿰…
iOS提示气泡,带动画
1.效果如图: 从项目中抠出来的,做了简单的封装。 2.用法: //顶部提示HYNoticeView *noticeTop [[HYNoticeView alloc] initWithFrame:CGRectMake(50, 66, 250, 40) text:"这里可以查询全城婚礼人的档期哦!" position:…

GIt/Github常用命令
1)git init:初始化本地仓库 2)创建文件:touch read.txt 3)当操作本地的文件时,使用常用的命令,如(mv,ls。。)就可以操作,当操作暂存区的文件时需要在命令前家…

python练习题(python之“求一个数的阶乘并求结果中从后向前数第一个不为0(零)的数” 等)
实验环境:python2.7 题目1:python之“求一个数的阶乘并求结果中从后向前数第一个不为0(零)的数”程序: import math def factorial(n): #定义一个函数,返回一个数的阶乘 if n0: return 1 else: sumn*factorial(n-…
【动画1】UIView动画
讲一下动画。将分为以下5篇博客。 一)UIView动画 二)Layer动画 三)3D动画 四)转场动画 五)第三方动画框架 相关代码:https://github.com/dolacmeng/AnimationDemo 参考资料:iOS Animation…

【python】解压文件
参考:http://essen.iteye.com/blog/1941489 tarfile模块 具体使用方法: https://docs.python.org/2/library/tarfile.html 例子:一次性解压所有文件 import tarfilet tarfile.open("abc.tgz", "r:gz")t.extractall(path…

JS设计模式——3.封装与信息隐藏
封装、信息隐藏与接口的关系 信息隐藏是目的,封装是手段。 接口提供了一份记载着可供公共访问的方法的契约。它定义了两个对象间可以具有的关系。只要接口不变,这个关系的双方都是可以替换的。 一个理想的软件系统应该为所有类定义接口。 创建对象的基本…

nginx源码编译、负载均衡及模块的扩展
1、nginx源码编译 实验环境: iptables和selinux关闭 redhat6.5 nginx:test1: 172.25.1.11 [roottest1 ~]# ls nginx-1.14.0.tar.gz [roottest1 ~]# tar zxf nginx-1.14.0.tar.gz [roottest1 ~]# useradd -s /sbin/nologin nginx [roottest1 ~]# i…

LinkedHashMap and LinkedHashSet
LinkedHashMap实现了Map接口,是HashMap的直接子类,它同时满足HashMap和linked list的某些特性。可将LinkedHashMap看作采用linked list增强的HashMap。 LinkedHashMap在HashMap的基础上,采用双向链表(doubly-linked listÿ…

Windows Phone开发(19):三维透视效果
Windows Phone开发(19):三维透视效果 原文:Windows Phone开发(19):三维透视效果 三维效果也可以叫透视效果,所以,我干脆叫三维透视效果。理论知识少讲,直接用例开场吧&am…
【动画2】CALayer动画
一)UIView动画 二)CoreAnimation动画 前言:上一篇已经介绍了UIKit给我们封装好的UIView动画的使用,UIKit动画是建立在CoreAnimation动画之上的,CoreAnimation是直接作用于CALayer上而非UIView。一、CoreAnimation动画…

nginx+tomcat+memcache实现负载均衡、session共享
实验架构图: Table of Contents 1、配置tomcat 2、安装memcache 3、查看tomcat和memcache是否配置好 4、nginx实现负载均衡: 5、客户端进行测试: 6、验证结论: 7、总结: 实验环境: linux redhat6.…

(转)二叉树系列面试问题
转自 :http://blog.csdn.net/luckyxiaoqiang/article/details/7518888/ 版权所有,转载请注明出处,谢谢!http://blog.csdn.net/walkinginthewind/article/details/7518888 树是一种比较重要的数据结构,尤其是二叉树。二…