android: 侧滑菜单的实现(ViewDragHelper)

来源:互联网 发布:淘宝质量问题怎么赔偿 编辑:程序博客网 时间:2024/05/24 04:30
  • 关于侧滑效果,github上面已经有了很多成型的框架。可以非常方便的集成使用。
  • 不过,实际项目中,可能有些需求,框架并没有帮我们完成。所以,有时候,需要自己动手实现这样的效果。
  • 根据泡网,hongyang,还有Android群英传,以及网上各位大婶的博客文章。我写了一个简单的侧滑效果。
  • 记录在此,主要是加深印象。详情在代码注释中
/** * Created on 2017/1/24. */public class VdbGroup extends FrameLayout {    private ViewDragHelper helper;    private View firstView;    private View secondView;    public VdbGroup get() {        return this;    }    public VdbGroup(Context context) {        this(context, null);    }    public VdbGroup(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        // record init position of second view    }    public VdbGroup(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        helper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {            @Override            public boolean tryCaptureView(View child, int pointerId) {                return child == secondView;            }            // target child can scroll in x when touch move            @Override            public int clampViewPositionHorizontal(View child, int left, int dx) {                final int leftBound = firstView.getLeft(); // MainView侧滑的起点                final int rightBound = firstView.getMeasuredWidth() - leftBound + 10; // 终点 +10 是为了看到效果,实际使用中 去掉 +10 的操作                final int newLeft = Math.min(Math.max(left, leftBound), rightBound);                LogUtils.e("newL = " + newLeft + " rb = " + rightBound);                return newLeft;            }            // 子View 可点击的时候需要重新的方法            @Override            public int getViewHorizontalDragRange(View child) {                return getMeasuredWidth() - firstView.getMeasuredWidth();            }            // 当松手之后的回调            @Override            public void onViewReleased(View releasedChild, float xvel, float yvel) {                // when release let it go back of the init position                int secondLeft = secondView.getLeft();                int middle = (firstView.getLeft() + firstView.getRight()) / 2;                LogUtils.e("secondLeft = " + secondLeft + " menuRight = "                        + firstView.getRight() + " menuL = " + firstView.getLeft());                if (secondLeft > middle) {                    // open                    helper.smoothSlideViewTo(releasedChild, firstView.getRight(), firstView.getTop());                    ViewCompat.postInvalidateOnAnimation(get());                } else {                    // close                    helper.smoothSlideViewTo(releasedChild, firstView.getLeft(), firstView.getTop());                    ViewCompat.postInvalidateOnAnimation(get());                }            }        });    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        if (getChildCount() != 2) {            throw new RuntimeException("I had two children,where they are?");        }        firstView = getChildAt(0);        firstView.setVisibility(VISIBLE);        secondView = getChildAt(1);        secondView.setVisibility(VISIBLE);    }    @Override    public void computeScroll() {        if (helper.continueSettling(true)) {            ViewCompat.postInvalidateOnAnimation(this);        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        helper.processTouchEvent(event);        return true;    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        return helper.shouldInterceptTouchEvent(ev);    }}
  • 简单介绍一下getViewHorizontalDragRange(View child)方法:
// 子View 可点击的时候需要重新的方法@Override public int getViewHorizontalDragRange(View child) {     return getMeasuredWidth() - firstView.getMeasuredWidth(); }

这个方法,在子View可点击的时候需要重写。返回值>0,才可以拖动。

  • 还有这个方法clampViewPositionHorizontal(View child, int left, int dx)
@Overridepublic int clampViewPositionHorizontal(View child, int left, int dx) {    final int leftBound = firstView.getLeft(); // MainView侧滑的起点    final int rightBound = firstView.getMeasuredWidth() - leftBound + 10; // 终点    final int newLeft = Math.min(Math.max(left, leftBound), rightBound);    LogUtils.e("newL = " + newLeft + " rb = " + rightBound);    return newLeft;}

如果只是需要滑动效果,直接返回left即可。但是这里为了搞侧滑效果。所以,是希望她的滑动范围是MenuView的宽度。而int newLeft = Math.min(Math.max(left, leftBound), rightBound);这句代码的作用就是,如果left在指定的范围内,就返回left,否则就返回边界值。

  • 更多的关于ViewDragHelper的介绍,我就不介绍了。上面给出的链接都有详细的解释。
  • 好了,这样子,一个简单的侧滑效果就实现了,总体不到120行代码。
0 0
原创粉丝点击