天天看点

android边栏滑动view,Android用ViewDragHelper实现侧滑菜单栏

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

先上效果

手指左右滑动

android边栏滑动view,Android用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;

}

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,可以看到实际上侧边栏和主视图是重叠的,滑动的是主视图,移动的也是主视图,侧边栏始终未变;

xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="170dp"

android:layout_height="match_parent"

android:background="@color/colorPrimary">

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@color/colorAccent">