Android用ViewDragHelper实现侧滑菜单栏

本文简单模仿了一般软件的侧滑菜单栏,只有当滑动主视图时,侧边菜单栏才会显示与隐藏,使用的是ViewDragHelper,让ViewDragHelper控制主视图的左右滑动,以达到侧滑菜单出现的假象,实际侧滑菜单一直没动,只有主视图在动。

  • 先上效果

手指左右滑动


侧边栏效果图
  • 自定义控件代码

其继承自FrameLayout,通过拦截触摸事件,将其交给ViewDragHelper处理,将拦截事件也交给ViewDragHelper,设置其何时开始检测触摸,并且设置滑动的子控件,即可实现该效果;

public class DragViewGroup extends FrameLayout {

    private ViewDragHelper mHelper;
    private View mLeftView;
    private View mMainView;
    private int mLefeWidth;

    public DragViewGroup(@NonNull Context context) {
        super(context);
        initView();
    }

    public DragViewGroup(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public DragViewGroup(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        //布局加载完成,可获取两个子控件
        mLeftView = getChildAt(0);
        mMainView = getChildAt(1);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //此时已测量完成,可获取抽屉的宽度
        mLefeWidth = mLeftView.getMeasuredWidth();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //事件拦截任务交给ViewDragHelper
        return mHelper.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mHelper.processTouchEvent(event);
        //返回true,事件不再向父控件传
        return true;
    }

    /**
     * 初始化ViewDragHelper
     */
    private void initView() {
        mHelper = ViewDragHelper.create(this,mCallBack);
    }

    private ViewDragHelper.Callback mCallBack = new ViewDragHelper.Callback() {
        //何时开始滑动检测
        @Override
        public boolean tryCaptureView(@NonNull View view, int i) {
            //当滑动的对象是mainView时开始检测触摸事件
            return view == mMainView;
        }

        @Override
        public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
            //处理水平滑动(子view左边界距离当前framelayout左边界距离),返回滑动位置
            if (left > 0) {
                return left>mLefeWidth ? mLefeWidth : left;
            } else {
                return 0;
            }
        }

        @Override
        public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
            //处理垂直滑动,返回垂直滑动位置
            return 0;
        }

        @Override
        public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);
            //手指抬起时处理
            if (mMainView.getLeft()>mLefeWidth/2) {
                //让左边菜单栏完全展示
                mHelper.smoothSlideViewTo(mMainView,mLefeWidth,0);
                //它执行后会调用到computerScroll()
                ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
            } else {
                //让左边菜单栏隐藏
                mHelper.smoothSlideViewTo(mMainView,0,0);
                ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
            }
        }
    };

    @Override
    public void computeScroll() {
        //如果滑动还未结束
        if (mHelper.continueSettling(true)) {
            //继续调用computeScroll
            ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
        }
    }
}

  • 布局文件

由于DragViewGroup是FrameLayout,可以看到实际上侧边栏和主视图是重叠的,滑动的是主视图,移动的也是主视图,侧边栏始终未变;



    
        
        
        
    

你可能感兴趣的:(Android用ViewDragHelper实现侧滑菜单栏)