Android實現簡單的像QQ同樣的側滑欄

package com.lgkj.zeng;
import android.animation.FloatEvaluator;
import android.animation.IntEvaluator;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
/**
 * Created by Zzm_Pc on 2017/1/10.
 */
public class DragViewDemo extends FrameLayout {
    private ViewDragHelper viewDrag;
    private View iuView;
    private View fishView;
    private float fishRange;
    private float iuRange;
    private float ratio;
    private float iuRatio;
    private FloatEvaluator floatEvaluator;
    private IntEvaluator intEvaluator;
    private boolean is = true;

    private enum OpenState {Close, Open}

    OpenState nowOpenState = OpenState.Close;
    private OpenStateListener openStateListener;

    public DragViewDemo(Context context) {
        super(context);
        initial();
    }

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

    public DragViewDemo(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initial();
    }

    //加載此佈局
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        iuView = getChildAt(0);
        fishView = getChildAt(1);

    }

    //在onMeasure方法執行完後就會執行該方法
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        fishRange = getMeasuredWidth() * 0.55f;
        iuRange = getMeasuredWidth() / 2f;
        Log.i("information", getMeasuredWidth() + "   ");
    }

    @Override
    public void computeScroll() {
        if (viewDrag.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(DragViewDemo.this);
        }
    }

    //初始化要作的事情,如初始化變量或者一些類。
    private void initial() {
        viewDrag = ViewDragHelper.create(this, new DragCallBack());
        floatEvaluator = new FloatEvaluator();
        intEvaluator = new IntEvaluator();

    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return viewDrag.shouldInterceptTouchEvent(ev);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        viewDrag.processTouchEvent(event);
        return true;
    }

    //接口回調
    private class DragCallBack extends ViewDragHelper.Callback {
        //viewdraghelper重要的chong重寫方法
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            return child == fishView || child == iuView;
        }

        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            if (child == fishView) {
                if (left > fishRange) {
                    left = (int) fishRange;
                } else if (left < 0) {
                    left = 0;
                }
            } else if (child == iuView) {
                //獲得iuView移動的條件
                if (left > 0) left = 0;
                if (-left > iuRange) left = -(int) iuRange;
            }
            return left;
        }

        @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            super.onViewPositionChanged(changedView, left, top, dx, dy);
            if (changedView == fishView) {
                //計算移動距離的比率
                ratio = fishView.getLeft() * 1f / fishRange;
                change(changedView, dx);
                if (ratio == 0 && nowOpenState != OpenState.Open) {
                    //側欄打開的狀態
                    nowOpenState=OpenState.Open;
                    if (openStateListener != null) {
                        openStateListener.opened(ratio);
                    }

                } else if (ratio == 1 && nowOpenState != OpenState.Close) {
                    //側欄關閉
                    nowOpenState=OpenState.Close;
                    if (openStateListener != null) {
                        openStateListener.closed(ratio);
                    }

                } else {
                    //正在拖拽側欄中
                    if (openStateListener != null) {
                        openStateListener.opening(ratio);
                    }
                }
            } else if (changedView == iuView) {
                iuRatio = -iuView.getLeft() / iuRange;
                changedView.setScaleX(floatEvaluator.evaluate(iuRatio, 1, 0.5));
                changedView.setScaleY(floatEvaluator.evaluate(iuRatio, 1, 0.5));
                fishView.setScaleX(floatEvaluator.evaluate(iuRatio, 0.8, 1));
                fishView.setScaleY(floatEvaluator.evaluate(iuRatio, 0.8, 1));
                fishView.layout(intEvaluator.evaluate(iuRatio, (int) fishRange, 0),
                        fishView.getTop(),
                        fishView.getMeasuredWidth() +
                                intEvaluator.evaluate(iuRatio, (int) fishRange, 0),
                        fishView.getBottom() + dy);
                if (iuRatio == 1 && nowOpenState != OpenState.Open) {
                    //側欄打開的狀態
                    nowOpenState=OpenState.Open;
                    if (openStateListener != null) {
                        openStateListener.opened(iuRatio);
                    }

                } else if (iuRatio == 0 && nowOpenState != OpenState.Close) {
                    //側欄關閉
                    nowOpenState=OpenState.Close;
                    if (openStateListener != null) {
                        openStateListener.closed(iuRatio);
                    }

                } else {
                    //正在拖拽側欄中
                    if (openStateListener != null) {
                        openStateListener.opening(iuRatio);
                    }
                }

            }
        }

        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);
            if (releasedChild == fishView && releasedChild.getLeft() > fishRange / 2f) {
                viewDrag.smoothSlideViewTo(releasedChild, (int) fishRange, releasedChild.getTop());
                is = false;
                //刷新
                ViewCompat.postInvalidateOnAnimation(DragViewDemo.this);
            } else if (releasedChild == fishView && releasedChild.getLeft() < fishRange / 2f) {
                viewDrag.smoothSlideViewTo(releasedChild, 0, releasedChild.getTop());
                //刷新
                ViewCompat.postInvalidateOnAnimation(DragViewDemo.this);
            } else if (releasedChild == iuView && -releasedChild.getLeft() > iuRange / 2) {
                viewDrag.smoothSlideViewTo(releasedChild, (int) -iuRange, releasedChild.getTop());
                //刷新
                ViewCompat.postInvalidateOnAnimation(DragViewDemo.this);
            } else if (releasedChild == iuView && -releasedChild.getLeft() < iuRange / 2) {
                viewDrag.smoothSlideViewTo(releasedChild, 0, releasedChild.getTop());
                //刷新
                ViewCompat.postInvalidateOnAnimation(DragViewDemo.this);
            }
        }
    }

    private void change(View view, int dx) {
        if (view == fishView) {
            view.setScaleX(floatEvaluator.evaluate(ratio, 1, 0.8));
            view.setScaleY(floatEvaluator.evaluate(ratio, 1, 0.8));
            if (iuView.getLeft() == 0) {
                iuView.setTranslationX(floatEvaluator.evaluate(ratio, -iuView.getMeasuredWidth() / 2, 0));
            } else {
                iuView.layout(intEvaluator.evaluate(ratio, (int) -iuRange, 0), iuView.getTop(), iuView.getMeasuredWidth() + intEvaluator.evaluate(ratio, (int) -iuRange, 0), iuView.getBottom());
            }
            iuView.setScaleX(floatEvaluator.evaluate(ratio, 0.5, 1));
            iuView.setScaleY(floatEvaluator.evaluate(ratio, 0.5, 1));

        }
    }

    //設置監聽器,把數據暴露出去
    public void setOpenStateListener(OpenStateListener openStateListener) {
        this.openStateListener = openStateListener;
    }

    //側欄的拖拽狀態的監聽接口
    public interface OpenStateListener {
        void opening(float ratio);

        void closed(float ratio);

        void opened(float ratio);
    }
}

  /* Log.i("informationFishview",
                        "iuRange/4------"
                                + iuRange / 4
                                + "   left------:" + left
                                + "   dx------:" + dx
                                + " getRight  " + fishView.getRight()
                                + "   getx:" + fishView.getX()
                                + "   getleft:" + fishView.getLeft()
                                + "   getRight:" + fishView.getRight()
                                + " getWidth " + fishView.getWidth() +
                                "  measureWith  " + fishView.getMeasuredWidth()
                                + "   ratio:" + ratio
                );*/
相關文章
相關標籤/搜索