关于DrawLayout的一些坑
网上的全屏滑动有两种方法,第一种是自己写手势判断是否滑动
package com.example.apppiaost.util;
import android.app.Activity;
import android.content.Context;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
public class MyDrawLayout extends DrawerLayout
{
private float x1, x2, y1, y2;
public MyDrawLayout(Context context)
{
super(context);
}
public MyDrawLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public MyDrawLayout(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
x1 = event.getX();
y1 = event.getY();
}
if (event.getAction() == MotionEvent.ACTION_MOVE)
{
}
if (event.getAction() == MotionEvent.ACTION_UP)
{
x2 = event.getX();
y2 = event.getY();
if (x1 - x2 > 100)
{
this.closeDrawer(Gravity.LEFT);
return false;
} else if (x2 - x1 > 100)
{
this.openDrawer(Gravity.LEFT);
return true;
} else
{
this.closeDrawer(Gravity.LEFT);
return false;
}
}
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
x1 = event.getX();
y1 = event.getY();
}
if (event.getAction() == MotionEvent.ACTION_MOVE)
{
}
if (event.getAction() == MotionEvent.ACTION_UP)
{
x2 = event.getX();
y2 = event.getY();
if (x1 - x2 > 100)
{
this.closeDrawer(Gravity.LEFT);
return false;
} else if (x2 - x1 > 100)
{
this.openDrawer(Gravity.LEFT);
return true;
}
}
return super.onInterceptTouchEvent(event);
}
}
第二种通过反射修改滑动范围
public void setDrawerLeftEdgeSize(Activity activity, DrawerLayout drawerLayout, float displayWidthPercentage)
{
if (activity == null || drawerLayout == null)
return;
try
{
// find ViewDragHelper and set it accessible
Field leftDraggerField = drawerLayout.getClass().getDeclaredField("mLeftDragger");
leftDraggerField.setAccessible(true);
ViewDragHelper leftDragger = (ViewDragHelper) leftDraggerField.get(drawerLayout);
Field edgeSizeField = leftDragger.getClass().getDeclaredField("mEdgeSize");
edgeSizeField.setAccessible(true);
int edgeSize = edgeSizeField.getInt(leftDragger);
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
edgeSizeField.setInt(leftDragger, (int) (dm.widthPixels * displayWidthPercentage));
} catch (Exception e)
{
}
}
第一种方法不推荐使用,体验非常不好,特别是有listview这种能上下滑动的控件,
第二种效果就好多了,但是在我看来还有一个bug就是长按时菜单会弹出来,而且会弹到你设定的最大宽度处
为了解决这个问题试了各种方法都失败了,最终选择了修改源码。
首先,关联v4包的源码(百度上有教程),并找到DrawLayout(eclipse通过ctrl +鼠标左键就能打开)
其次,新建一个java文件,将DrawLayout源码全部粘贴到自己的文件中
最后,修改并使用自己的java文件
/*******修改手势的地方********/
public MyDrawLayout2(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
final float density = getResources().getDisplayMetrics().density;
mMinDrawerMargin = (int) (MIN_DRAWER_MARGIN * density + 0.5f);
final float minVel = MIN_FLING_VELOCITY * density;
mLeftCallback = new ViewDragCallback(Gravity.LEFT);
mRightCallback = new ViewDragCallback(Gravity.RIGHT);
mLeftDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mLeftCallback);
mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
mLeftDragger.setMinVelocity(minVel);
mLeftCallback.setDragger(mLeftDragger);
mRightDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mRightCallback);
mRightDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT);
mRightDragger.setMinVelocity(minVel);
mRightCallback.setDragger(mRightDragger);
// So that we can catch the back button
setFocusableInTouchMode(true);
//修改手势滑动范围(1.0f 代表全屏)
setDrawerLeftEdgeSize(context,mLeftDragger,1.0f);
ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegate());
ViewGroupCompat.setMotionEventSplittingEnabled(this, false);
}
//修改修改手势滑动范围
public void setDrawerLeftEdgeSize(Context activity,ViewDragHelper mLeftDragger,float displayWidthPercentage)
{
Field edgeSizeField;
try
{
edgeSizeField = mLeftDragger.getClass().getDeclaredField("mEdgeSize");
edgeSizeField.setAccessible(true);
DisplayMetrics dm = new DisplayMetrics();
((Activity)activity).getWindowManager().getDefaultDisplay().getMetrics(dm);
edgeSizeField.setInt(mLeftDragger, (int) (dm.widthPixels * displayWidthPercentage));
} catch (Exception e)
{
e.printStackTrace();
}
}
/*******取消长按效果的地方1**********/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
final int action = MotionEventCompat.getActionMasked(ev);
// "|" used deliberately here; both methods should be invoked.
final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev) | mRightDragger.shouldInterceptTouchEvent(ev);
boolean interceptForTap = false;
switch (action)
{
case MotionEvent.ACTION_DOWN:
{
final float x = ev.getX();
final float y = ev.getY();
mInitialMotionX = x;
mInitialMotionY = y;
if (mScrimOpacity > 0 && isContentView(mLeftDragger.findTopChildUnder((int) x, (int) y)))
{
interceptForTap = true;
}
/***多添加的代码closeDrawers(true)**/
closeDrawers(true);
mDisallowInterceptRequested = false;
mChildrenCanceledTouch = false;
break;
}
/*******取消长按效果的地方2**********/
@Override
public boolean onTouchEvent(MotionEvent ev)
{
mLeftDragger.processTouchEvent(ev);
mRightDragger.processTouchEvent(ev);
final int action = ev.getAction();
boolean wantTouchEvents = true;
switch (action & MotionEventCompat.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
{
final float x = ev.getX();
final float y = ev.getY();
mInitialMotionX = x;
mInitialMotionY = y;
/***多添加的代码closeDrawers(true)**/
closeDrawers(true);
mDisallowInterceptRequested = false;
mChildrenCanceledTouch = false;
break;
}