仿照汽车之家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;

在viewDidLoad中初始化
- (void)viewDidLoad {[super viewDidLoad];leftValue = 0;rightValue = 100;[self setUpView];
}
然后在leftHandMove:和rightHandMove:中将用户选中的值分别赋值给leftValue和rightValue。
<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

【仿汽车之家】价格区间选择控件相关推荐

  1. android可以剪辑代码的控件,Android 仿抖音视频裁剪范围选择控件,支持本地视频和网络视频...

    实现后效果:由于是在模拟器上跑的背面的封面列表加载不出来,实际效果请真机运行 image.png 具体代码如下: 绘制上层滑动控件部分 package com.cj.customwidget.widg ...

  2. 自定义的仿美团,飞猪日期选择控件一

    本文是参考了网上找到的相应的文章和项目,自己动手实践的记录. 本文的主要目的是:1.复习一下自定义的view 2.利用Androidstudio4.0.2开发对比一下与之前有什么区别,因为在创建新项目 ...

  3. php汽车门户源码,discuz仿汽车之家门户带论坛源码

    discuz仿汽车之家源码已新增整站源码直接在线安装 本模板采用蓝色调,使网站看起来更显专业和科技感. 模板有门户资讯频道和论坛页面,框架代码以及大部分模块代码手工编写,从而减少代码冗余问题,对官方模 ...

  4. 云炬Android开发笔记 15评价晒单功能实现(自定义评分控件和仿微信自动多图选择控件)

    阅读目录 1. 晒单评价 1.1 点击页面跳转的实现 1.2 自定义评价订单的布局实现 1.3 星星布局的实现 2. 仿微信自动多图及删除控件 2.1 属性值及控件的定义 2.2 图片初始化方法onM ...

  5. 【无限互联】学员作品:仿汽车之家的App

    一.项目介绍:    本次项目是一个仿汽车之家的一款App:它主要是用来帮助人们不用出门就可以学习和掌握关于汽车各种知识和信息,也可以帮想买车的朋友买到一款符合你各种需求的好车. 二.效果图: 1.首 ...

  6. android 仿照ios 图片选择,GitHub - wildma/PictureSelector: Android 图片选择器(仿 IOS 图片选择控件)...

    PictureSelector Android 图片选择器(仿 IOS 图片选择控件) 效果图 功能特点 支持通过拍照获取图片 支持通过相册获取图片 支持图片是否裁剪两种场景 支持仿 IOS 底部弹出 ...

  7. android double比较大小吗,Android双向选择控件DoubleSeekBar使用详解

    本文实例为大家分享了Android双向选择控件DoubleSeekBar的使用方法,供大家参考,具体内容如下 先看效果图 1.DoubleSlideSeekBar public class Doubl ...

  8. 选择控件— UI组件系列

    重点 (Top highlight) The word "toggle" is a reference to a switch with a short handle that a ...

  9. android高仿钉钉和小米的日历控件

    原文地址:http://www.jianshu.com/p/622fdded4dc9 简介 这是一个高仿钉钉和小米的日历控件,支持快速滑动,界面缓存.想要定制化UI,使用起来非常简单,就像使用List ...

最新文章

  1. 编写程序,统计一个长度为2的字符串在另一个字符串中出现的次数
  2. gcc for Windows 开发环境介绍
  3. python中的datatype啥意思_案例中使用的是dataType,但是用在联系上面dataType不可用,必须改写成type:..._慕课问答...
  4. 终于找到可以一文多发的平台了!
  5. 【渝粤题库】国家开放大学2021春4010渠道管理答案
  6. Array.prototype.slice.call
  7. python处理excel表格-60万行的Excel数据,Python轻松处理
  8. 跑分cpu_跑分超过100万的CPU诞生
  9. Rsync结合Inotify 实时同步配置
  10. 如何正确卸载天锐绿盾客户端
  11. html5网页设计-表单
  12. OpenSSH概念和基本用法——SSH 客户端
  13. 【计算方法】解线性方程组的四种方法
  14. 微信注册验证成功之后不跳转_想申请小号的网友福利来了:绑定了微信的手机号怎么注册新的微信...
  15. 哈尔滨理工大学21级新生程序设计竞赛(同步赛)Jay的小迷弟(快速幂)
  16. React 基于ant design Pro 4 实现的一个分页, 自定义页码颜色
  17. 铁流:苹果为何不找IBM,而选择中国浪潮
  18. c语言雷克子波函数表达式,雷克子波频率研究
  19. 8 种实现垂直和水平居中元素的方法汇总
  20. 河北钢铁的数字化雄心

热门文章

  1. JPush 使用教程
  2. Java中单元测试中:@BeforeClass,@Before,@Test,@After,@AfterClass中的问题详解
  3. Java IO系列之字节流拷贝文件性能比较
  4. 获取SQLServer数据库中所有表
  5. 【ZT】我家宝宝不会哭----分享在美国养孩子的妈妈经(必看)
  6. 基于第四层交换技术的负载均衡
  7. Colly源码解析——框架
  8. 提高C++性能的编程技术笔记:虚函数、返回值优化+测试代码
  9. FFmpeg简介及在vc2010下编译步骤
  10. 海思3536:kernel编译和mpp_single编译过程报错及解决方法