【仿汽车之家】价格区间选择控件

来源:互联网 发布:Linux指令批量执行 编辑:程序博客网 时间:2024/04/26 07:50

仿照汽车之家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;        //<5    if(x < PRICEMIN){        price = 0;    }    //5~25    else if (x < PRICEBGX + 133){        price = (x - PRICEMIN) / 120 * 20 + 5;    }    //25~40    else if (x < PRICEBGX +  163){        price = (x - PRICEBGX - 133) *0.5 + 25;    }    //40~100    else 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;    //<5    if (price<5) {        x = PRICEBGX;    }    //5~25    else if (price >= 5 && price < 25) {        x = (price-5) * 6 + PRICEMIN;    }    //25~40    else if (price >= 25 && price <40) {        x = (price-25) * 2 + 133 + PRICEBGX;    }    //40~100    else 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





0 0
原创粉丝点击