類似滴滴打車司機端滑動開始接單SlideView

開局一張圖,先看看是不是想要的效果

沒錯,今天就要實現這種效果,首先,可以看出來,這個效果是由兩部分組成的,滑動的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) {
                    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(500);
                        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) {
                //自己的操作
            }
});

到這裏就結束了,這種功能也不是很難,前提是一定要多實踐才行。加油

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章