类似滴滴打车司机端滑动开始接单SlideView

开局一张图,先看看是不是想要的效果

类似滴滴打车司机端滑动开始接单SlideView_第1张图片

没错,今天就要实现这种效果,首先,可以看出来,这个效果是由两部分组成的,滑动的view以及背景view.重点就是滑动的View,并且分两种情况,当滑动距离超过一半时,则顺势滑下去,没有超过一半,则回弹到初始位置。

对于View跟随手势去滑动,当然是ViewDragHelper是比较合适的。我对这个类我也是第一次用,里面还有很多东西没有理解,只是简单的去运用。主要是自定义View继承自LinearLayout.

贴代码,不多BB,看会应该都能懂。

public class SlideRightViewDragHelper extends LinearLayout {

    private ViewDragHelper viewDragHelper;
    private View child;
    private Point childPosition = new Point();
    private Point childEndPosition = new Point();
    private OnReleasedListener onReleasedListener;
    private int oldX;


    public SlideRightViewDragHelper(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setTouchable(boolean isTouch) {
        if (isTouch) {
            //新建viewDragHelper ,viewGroup, 灵敏度,回调(子view的移动)
            viewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
                @Override
                public boolean tryCaptureView(View child, int pointerId) {
                    oldX = 0;
                    return true;
                }

                @Override
                public int clampViewPositionHorizontal(View child, int left, int dx) {
                    oldX = left;
                    return Math.max(0, left);
                }

                @Override
                public void onViewReleased(View releasedChild, float xvel, float yvel) {
                    if (oldX > getWidth() / 2) {
/*
 *之所以没这么写,是因为在滑到最右边之后,滑动的View就会被释放,我通过layout方法无法将view设置
 *为复原,然后我必须又要把view在移回最左边,但无法实现向右顺势滑动的效果,反正达不到预期的效果,
 *后来就自己写了个位移动画,最终实现了想要的效果。
*/
//                        viewDragHelper.settleCapturedViewAt(childEndPosition.x, childEndPosition.y);
//                        invalidate(); //必须刷新,因为其内部使用的是mScroller.startScroll,所以别忘了需要invalidate()以及结合computeScroll方法一起。
//                        if (onReleasedListener != null) {
//                            child.layout(childPosition.x, childPosition.y, getWidth(), getHeight());
//                            viewDragHelper.settleCapturedViewAt(childPosition.x, childPosition.y); //反弹
//                            onReleasedListener.onReleased();
//                        }
                         TranslateAnimation translateAnimation = 
new TranslateAnimation(0, childEndPosition.x, childPosition.y, childPosition.y);
                        translateAnimation.setDuration(300);
                        child.startAnimation(translateAnimation);
                        translateAnimation.setAnimationListener(new Animation.AnimationListener() {
                            @Override
                            public void onAnimationStart(Animation animation) {

                            }

                            @Override
                            public void onAnimationEnd(Animation animation) {
                                Handler handler = new Handler();
                                handler.postDelayed(new Runnable() {
                                    @Override
                                    public void run() {
                                        onReleasedListener.onReleased(0, 0, getWidth(), getHeight());
                                    }
                                }, 10);

                            }

                            @Override
                            public void onAnimationRepeat(Animation animation) {

                            }
                        });
                    } else {//滑动距离不够一半,回到初始位置
                        viewDragHelper.settleCapturedViewAt(childPosition.x, childPosition.y); //反弹
                        invalidate();//必须调用
                    }


                    super.onViewReleased(releasedChild, xvel, yvel);
                }

                @Override
                public void onViewCaptured(View capturedChild, int activePointerId) {
                    super.onViewCaptured(capturedChild, activePointerId);
                }


                @Override
                public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
                    super.onViewPositionChanged(changedView, left, top, dx, dy);
                }

            });
        } else {
            viewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
                @Override
                public boolean tryCaptureView(View child, int pointerId) {
                    return false;
                }
            });
        }
    }


    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        child = getChildAt(0);
    }

    @Override   //用viewDragHelper拦截-true
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return viewDragHelper.shouldInterceptTouchEvent(ev);
    }


    @Override  //viewDragHelper拦截事件
    public boolean onTouchEvent(MotionEvent event) {
        viewDragHelper.processTouchEvent(event);
        return true;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        //定位左侧的坐标
        childPosition.x = child.getLeft();
        childPosition.y = child.getTop();

        //定位右侧的坐标
        childEndPosition.x = child.getRight();
        childEndPosition.y = child.getTop();
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (viewDragHelper.continueSettling(true)) {
            invalidate();
        }
    }

    public void setOnReleasedListener(OnReleasedListener onReleasedListener) {
        this.onReleasedListener = onReleasedListener;
    }

    public interface OnReleasedListener {
        void onReleased(int left, int top, int right, int bottom);
    }
}

主要重写了ViewDragHelper的三个方法

tryCaptureView()试图要捕捉的View 当返回true时,可对当前View进行操作,返回false,则不可操作

clampViewPositionHorizontal()  在水平滑动过程中,可以得到当前View的left值

onViewReleased() 当手指抬起的时候回走这个方法,但我总觉得当我滑到最右边的时候,就会把我的View给释放掉,这个方法还不是很懂

当View滑动到最右边时,就会通过接口告知Activity当前view已经滑到最右边,实现这个接口,并作出对应的操作。

dragHelper.setOnReleasedListener(new SlideRightViewDragHelper.OnReleasedListener() {
            @Override
            public void onReleased(final int left, final int top, final int right, final int bottom) {
                //自己的操作
            }
});

把所有代码都贴一下

布局代码

 



        

Activity代码

public class SlideViewActivity extends AppCompatActivity implements View.OnClickListener {
    SlideRightViewDragHelper dragHelper;
    LinearLayout llSlideBg;
    TextView tv;
    Button bt;

    boolean onLine = false;//false为离线  true为在线
    boolean orderState = false; //false为未接单  true为接单

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_slide_view);
        initView();
        dragHelper.setOnReleasedListener(new SlideRightViewDragHelper.OnReleasedListener() {
            @Override
            public void onReleased(final int left, final int top, final int right, final int bottom) {
                if (orderState == true) {//可接单状态——>不可接单状态
                    orderState = !orderState;
                    llSlideBg.setBackgroundColor(getResources().getColor(R.color.red));
                } else {//不可接单状态——>可接单状态
                    orderState = !orderState;
                    llSlideBg.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
                }
                tv.setText(orderState == true ? ">>滑动结束听单" : ">>滑动开始听单");
                dragHelper.setBackgroundColor(orderState == true ? getResources().getColor(R.color.red) : getResources().getColor(R.color.colorPrimary));
                llSlideBg.layout(left, top, right, bottom);
            }
        });
    }

    private void initView() {
        llSlideBg = findViewById(R.id.slide_view_ll);
        tv = findViewById(R.id.slide_view_tv);
        bt = findViewById(R.id.slide_view_bt);
        dragHelper = findViewById(R.id.slide_view_drag_helper);
        bt.setOnClickListener(this);
        dragHelper.setTouchable(false);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.slide_view_bt:
                if (onLine) {//当前为上线  去下线
                    onLine = !onLine;
                    llSlideBg.setBackgroundColor(getResources().getColor(R.color.gray));
                    dragHelper.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
                    bt.setText("上线");
                    dragHelper.setTouchable(false);
                    tv.setText(">>滑动开始听单");
                    dragHelper.recovery(llSlideBg);
                } else {//当前为下线 去上线
                    onLine = !onLine;
                    llSlideBg.setBackgroundColor(getResources().getColor(R.color.red));
                    dragHelper.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
                    bt.setText("下线");
                    dragHelper.setTouchable(true);
                }
                break;
        }
    }
}

 

到这里就结束了,这种功能也不是很难,前提是一定要多实践才行。加油

你可能感兴趣的:(自定义View)