仿拉钩薪资选择器

我们不缺少想法,只是缺少开始的勇气

之前有个同学问我拉钩的薪资选择怎么做,网上资料也找不到。说实话之前我倒是没有注意过拉钩的薪资范围选择是怎么样的。啥也别说了,去下一个看看呗!看到效果一脸懵逼啊,真的是一点想法都没有,当时事情也比较多,所以也就没有深究,有点辜负同学对我的信任了。

这段时间趁着有空,打算把自定义view重新温故一下,就想到了之前的需求。那咱也仿制一个呗,人家都实现了,那我肯定也是可以实现的。由于资质有限,花了大概两天的时间才造出一个90分的demo,废话不多说,先来看下效果。

仿拉钩薪资选择器_第1张图片
薪资范围.gif

什么?你还没看够,那你下下来慢慢看http://fir.im/kbrf, 接下来我来讲一下具体的实现思路:之前也想过在ProgressBar的基础上来实现,不过最后放弃了。条条大路通罗马,方法肯定不止一种,大家不要局限于我的思想。

-1- 不管三七二十一,先把view做出来,有个样子先,其他的再慢慢做

这一步非常简单,图片资料可以从拉钩的app中解压出来


android:layout_width="match_parent"
android:layout_height="wrap_content"
>

android:id="@+id/view_progress"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="@color/progress_select"
/>

android:id="@+id/slide_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
>

    

    

    






    

    

    



这时候你看到的效果应该是这样子的

仿拉钩薪资选择器_第2张图片
view.png
-2- 接下来就是处理左右两边view的滑动

关于这个需求我立马就想到了ViewDragHelper,简直就是处理滑动的利器,还没有学习的赶紧学习下,具体可参考 http://blog.csdn.net/lmj623565791/article/details/46858663 我捡Demo中用到的来讲一下

  • 创建实例
    mViewDragHelper = ViewDragHelper.create(this, 1.0f,new ViewDragHelper.Callback() {});
    三个参数分别为Viewgroup,灵敏度,回调
  • 触摸相关方法
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
    return mViewDragHelper.shouldInterceptTouchEvent(ev);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
    mViewDragHelper.processTouchEvent(event);
    return true;
    }
    是否拦截触摸,触摸事件处理都交给ViewDragHelper处理就好
  • 回调方法(我只捡Demo中用到的说)
    tryCaptureView 捕捉View,说白了就是指定哪些子View的触摸交给ViewDragHelper来处理。
    clampViewPositionHorizontal 对child移动的水平边界进行控制
    clampViewPositionVertical 对child移动的竖直边界进行控制
    getViewHorizontalDragRange 返回拖拽的范围,当子view中包含有可点击的view时此方法必须设置
    onViewCaptured 当captureview被捕获时回调
    onViewPositionChanged 当captureview的位置发生改变时回调
    onViewReleased 手指抬起回调
    onViewDragStateChanged 当ViewDragHelper状态发生变化时回调

完成这一步之后你可以看到两边的子View可以滑动了

-3- 滑动范围

仔细观察可以发现右边view的滑动范围是左边view到最右边,左边view同理。看了上面的回调方法自然知道范围在clampViewPositionHorizontal 和clampViewPositionVertical 中设置,还需要在手指抬起时记录下当前的位置
/**
* 对移动的边界进行控制
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
int leftBound = currentPositionLeft;
int rightBound = currentPotionRight == 0 ? getWidth() - slideRight.getWidth() : currentPotionRight - slideRight.getWidth();
int newLeft = Math.min(Math.max(left, leftBound), rightBound);
return newLeft;
}

        /**
         * 设置上下不能滑动
         */
        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            return 0;
        }
        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);

            if (releasedChild == slideLeft) {
                currentPositionLeft = slideLeft.getLeft();
            }

            if (releasedChild == slideRight) {
                currentPotionRight = slideRight.getRight();
            }

        }
-4- 选中状态

可以看到无论是移动左边的view还是右边的view,薪资的背景都是需要改变的。这时候你肯定会笑着说“这还不容易吗”,设置TextView的背景就好了。的确是这么做的

       @Override
        public void onViewDragStateChanged(int state) {
            super.onViewDragStateChanged(state);

            switch (state) {
                //不拖拽状态
                case ViewDragHelper.STATE_IDLE:
                    salaryLower.setBackgroundResource(R.drawable.bg_number_unselect);
                    salaryUpper.setBackgroundResource(R.drawable.bg_number_unselect);
                    break;
                //拖拽中
                case ViewDragHelper.STATE_DRAGGING:
                    if (mViewDragHelper.getCapturedView() == slideLeft) {
                        salaryLower.setBackgroundResource(R.drawable.bg_number_seleted);

                    } else {
                        salaryUpper.setBackgroundResource(R.drawable.bg_number_seleted);
                    }
                    break;
                //view设置中
                case ViewDragHelper.STATE_SETTLING:
                    break;
            }
        }

当你沾沾自喜时,运行起来却发现手指释放的时候view永远是弹回刚开始时的位置。(去他妈的,怎么搞的),这东西困扰了我好久,后来仔细看setBackgroundResource的源码才发现会调用requestLayout重新回调onLayout,而这边记录的恰恰只有刚开始时的位置,不回去才怪呐。这里需要记录滑到的位置重写onLayout方法。

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);

    if (isFirst) {
        mLeftLower = slideLeft.getLeft();
        mTopLower = slideLeft.getTop();
        mLeftUpper = slideRight.getLeft();
        mTopUpper = slideRight.getTop();
        isFirst = false;
    }

    //设置view的位置
    slideLeft.layout(mLeftLower, mTopLower, mLeftLower + slideLeft.getMeasuredWidth(), mTopLower + slideLeft.getMeasuredHeight());
    slideRight.layout(mLeftUpper, mTopUpper, mLeftUpper + slideRight.getMeasuredWidth(), mTopUpper + slideRight.getMeasuredHeight());
}
-5- 改变TextView的薪资显示

聪明的你应该知道在onViewPositionChanged 方法中实现,仔细观察可以发现总共有35个薪资段

        @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            if (changedView == slideLeft) {
                int valuesLeft = (int) (left / unitLong);
                if (valuesLeft < 25) {
                    currentSalaryLeft = valuesLeft + 1;
                } else if (valuesLeft < 30) {
                    switch (valuesLeft){
                        case 25:
                            currentSalaryLeft = 30;
                            break;
                        case 26:
                            currentSalaryLeft = 35;
                            break;
                        case 27:
                            currentSalaryLeft = 40;
                            break;
                        case 28:
                            currentSalaryLeft = 45;
                            break;
                        case 29:
                            currentSalaryLeft = 50;
                            break;
                    }
                } else {
                    switch (valuesLeft){
                        case 30:
                            currentSalaryLeft = 60;
                            break;
                        case 31:
                            currentSalaryLeft = 70;
                            break;
                        case 32:
                            currentSalaryLeft = 80;
                            break;
                        case 33:
                            currentSalaryLeft = 90;
                            break;
                        case 34:
                            currentSalaryLeft = 100;
                            break;
                    }
                }
                pathLeft = left;
                mLeftLower = slideLeft.getLeft();
                salaryLower.setText(currentSalaryLeft + "K");
            }

            if (changedView == slideRight) {
                int valuesRight = (int) (left / unitLong);
                if (valuesRight < 25) {
                    currentSalaryRight = valuesRight + 1;
                } else if (valuesRight < 30) {
                    switch (valuesRight){
                        case 25:
                            currentSalaryRight = 30;
                            break;
                        case 26:
                            currentSalaryRight = 35;
                            break;
                        case 27:
                            currentSalaryRight = 40;
                            break;
                        case 28:
                            currentSalaryRight = 45;
                            break;
                        case 29:
                            currentSalaryRight = 50;
                            break;
                    }
                } else {
                    switch (valuesRight){
                        case 30:
                            currentSalaryRight = 60;
                            break;
                        case 31:
                            currentSalaryRight = 70;
                            break;
                        case 32:
                            currentSalaryRight = 80;
                            break;
                        case 33:
                            currentSalaryRight = 90;
                            break;
                        case 34:
                            currentSalaryRight = 100;
                            break;
                    }
                }
                pathRight = left;
                mLeftUpper = slideRight.getLeft();
                salaryUpper.setText(currentSalaryRight + "K");
            }

            if (salaryProgressListener != null) {
                salaryProgressListener.salaryProgress(currentSalaryLeft, currentSalaryRight);
            }
            postInvalidate();
        }
-6- 显示绿色的薪资范围
  • 自定义ViewGroup默认不调用onDraw方法,可以通过setBackgroud触发
  • PathMeasure可以用来截取Path片段
@Override
protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);
    mPath.reset();
    dstPath.reset();
    mPath.moveTo(viewProgress.getLeft(), viewProgress.getBottom() - viewProgress.getMeasuredHeight() / 2);
    mPath.lineTo(viewProgress.getRight(), viewProgress.getBottom() - viewProgress.getMeasuredHeight() / 2);
    mPathMeasure = new PathMeasure(mPath, false);
    mPathMeasure.getSegment(pathLeft, pathRight, dstPath, true);

    canvas.drawPath(dstPath, mPaint);}

Github地址https://github.com/liulingfeng/SalaryProgress 高兴点个Star就好

你可能感兴趣的:(仿拉钩薪资选择器)