如何在从左向右滑动时显示DrawerLayout,无论在哪里?

背景

谷歌已经推出了DrawerLayout,当你点击操作栏的“向上”button时,在屏幕的左侧显示一个菜单。

因为这个库在actionBarSherlock上还不被支持,所以已经有一种方法来使用这个项目来克服它。

它已经在许多应用程序的变种:电stream,Gmail,环聊,YouTube …

这个问题

在“电stream”应用程序(和YouTube)中,当用户从左向右滑动(最左侧)页面时, 无论手指触摸到什么位置,都会出现DrawerLayout。

我怎样才能达到同样的效果? 也许我应该使用onInterceptTouchEvent ?

没有太多的文档和教程可以做什么很酷的事情,除了这个链接 (好吧, 这也是)。 他们说(在“让用户快速浏览”部分)左边大约20dp用于这个function,但是我可以看到“电stream”的工作面积要大得多。

它似乎库仍然不完全,所以布局xml文件甚至不能在可视化UI编辑器中显示…


编辑:看来,图书馆是开源的。 代码可用于:

.../android-sdk\sources\android-18\android\support\v4\widget\DrawerLayout.java .../android-sdk\sources\android-18\android\support\v4\widget\SlidingPaneLayout.java .../android-sdk\sources\android-18\android\support\v4\app\ActionBarDrawerToggle.java 

现在的问题是如何使它像我写的那样工作,这样它就可以在youtube上工作,使我们能够定制它的外观和从哪里滚动。

Solutions Collecting From Web of "如何在从左向右滑动时显示DrawerLayout,无论在哪里?"

SlidingMenu是我见过的最好的滑动图书馆,这是非常好的图书馆。
您可以设置getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN)启用所有屏幕的getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN)

问题是DrawerLayout使用ViewDragHelper,它具有20dp的默认EDGE_SIZE ,用于计算mEdgeSize,如下所示:

 mEdgeSize = (int) (EDGE_SIZE * density + 0.5f); 

这是一个函数,它将mEdgeSize设置为显示宽度的百分比:

 public static 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); // find edgesize and set is accessible Field edgeSizeField = leftDragger.getClass().getDeclaredField("mEdgeSize"); edgeSizeField.setAccessible(true); int edgeSize = edgeSizeField.getInt(leftDragger); // set new edgesize Point displaySize = new Point(); activity.getWindowManager().getDefaultDisplay().getSize(displaySize); edgeSizeField.setInt(leftDragger, Math.max(edgeSize, (int) (displaySize.x * displayWidthPercentage))); } catch (NoSuchFieldException e) { // ignore } catch (IllegalArgumentException e) { // ignore } catch (IllegalAccessException e) { // ignore } } 

所以,假设您希望您的左边的30%对滑动事件做出反应并打开导航抽屉,然后只需调用:

 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); setDrawerLeftEdgeSize(this, mDrawerLayout, 0.3f); 

我试着改变默认的EDGE_SIZE解决scheme,并且遇到了长时间的点击问题。 最后,Ifound通过计算X偏移来覆盖dispatchTouchEvent并根据滑动方向打开抽屉。

 @Override public boolean dispatchTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: startX = ev.getX(); startY = ev.getY(); break; case MotionEvent.ACTION_UP: endX = ev.getX(); endY = ev.getY(); float sensitivity = 5; // From left to right if (endX - startX >= sensitivity) { if (mDrawerLayout.isDrawerOpen(Gravity.RIGHT)) { mDrawerLayout.closeDrawer(Gravity.RIGHT); } else { mDrawerLayout.openDrawer(Gravity.LEFT); } } // From right to left if (startX - endX >= sensitivity) { if (mDrawerLayout.isDrawerOpen(Gravity.LEFT)) { mDrawerLayout.closeDrawer(Gravity.LEFT); } else { mDrawerLayout.openDrawer(Gravity.RIGHT); } } break; } 

通过使用他人的帮助:( 第一) (第二)

我发现使用reflection可以实现修改抽屉菜单的幻灯片20dp的屏幕边缘

宣布内容和抽屉后,你可以这样做:

 public class MainActivity extends Activity { private DrawerLayout mDrawerLayout; private ListView mDrawerList; private ActionBarDrawerToggle mDrawerToggle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerList = (ListView) findViewById(R.id.left_drawer); // set a custom shadow that overlays the main content when the drawer opens mDrawerLayout.setDrawerShadow(R.drawable.your_drawer_shadow, GravityCompat.START); // set up the drawer's list view with items and click listener mDrawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.your_drawer_list, yourItems)); mDrawerList.setOnItemClickListener(new DrawerItemClickListener()); // enable ActionBar app icon to behave as action to toggle nav drawer getActionBar().setDisplayHomeAsUpEnabled(true); getActionBar().setHomeButtonEnabled(true); Field mDragger = null; try { mDragger = mDrawerLayout.getClass().getDeclaredField( "mLeftDragger"); //mRightDragger for right obviously } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } mDragger.setAccessible(true); ViewDragHelper draggerObj = null; try { draggerObj = (ViewDragHelper) mDragger .get(mDrawerLayout); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } Field mEdgeSize = null; try { mEdgeSize = draggerObj.getClass().getDeclaredField( "mEdgeSize"); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } mEdgeSize.setAccessible(true); int edge = 0; try { edge = mEdgeSize.getInt(draggerObj); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { mEdgeSize.setInt(draggerObj, edge * 5); //optimal value as for me, you may set any constant in dp //You can set it even to the value you want like mEdgeSize.setInt(draggerObj, 150); for 150dp } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } // ActionBarDrawerToggle ties together the the proper interactions // between the sliding drawer and the action bar app icon mDrawerToggle = new ActionBarDrawerToggle( this, /* host Activity */ mDrawerLayout, /* DrawerLayout object */ R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */ R.string.drawer_open, /* "open drawer" description for accessibility */ R.string.drawer_close /* "close drawer" description for accessibility */ ) { public void onDrawerClosed(View view) { } public void onDrawerOpened(View drawerView) { } }; mDrawerLayout.setDrawerListener(mDrawerToggle); } } 

那么,它适合我的人!

你可以在Navigation Drawer中使用它

 DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); Field mDragger = mDrawerLayout.getClass().getDeclaredField( "mLeftDragger");//mRightDragger or mLeftDragger based on Drawer Gravity mDragger.setAccessible(true); ViewDragHelper draggerObj = (ViewDragHelper) mDragger .get(mDrawerLayout); Field mEdgeSize = draggerObj.getClass().getDeclaredField( "mEdgeSize"); mEdgeSize.setAccessible(true); int edge = mEdgeSize.getInt(draggerObj); mEdgeSize.setInt(draggerObj, edge * 3); 

使用这个项目SlidingMenu你可以达到这个效果,并与ActionBarSherlock集成。

要从左向右滑动菜单,只需在创build菜单时自定义菜单并添加:

 slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN); 

希望这可以帮助。

首先,我不确定你的意思是关于不支持DrawerLayout的ActionBarSherlock。 你可以很高兴地使用DrawerLayout和ActionBarSherlock,我有使用这个组合的应用程序。 您将需要更改支持jar版本,但我发现ActionbarSherlock没有这个问题。

以通常的方式实现DrawerLayout。 然后在你的片段中实现onTouchEvent或者interceptTouchEvent,当这个types是一个'move'types的事件从左向右滑动的时候,你可以调用DrawerLayout上的openDrawer方法。 您需要添加处理手指行进的距离,以确保打开抽屉的呼叫不太敏感。

当我们覆盖默认边缘我们的那部分重叠的屏幕停止工作,我已经在viewpager中使用了上面的代码,但现在当我滚动到左侧从右侧,而不是下一个查看页面,它保持不变。 会有什么解决scheme呢? 我用setDrawerLeftEdgeSize(this,mDrawerLayout,distance );

 public static 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); // find edgesize and set is accessible Field edgeSizeField = leftDragger.getClass().getDeclaredField( "mEdgeSize"); edgeSizeField.setAccessible(true); int edgeSize = edgeSizeField.getInt(leftDragger); // set new edgesize Point displaySize = new Point(); activity.getWindowManager().getDefaultDisplay() .getSize(displaySize); edgeSizeField.setInt(leftDragger, Math.max(edgeSize, (int) (displaySize.x * displayWidthPercentage))); } catch (NoSuchFieldException e) { // ignore } catch (IllegalArgumentException e) { // ignore } catch (IllegalAccessException e) { // ignore } } 

和上面一样..