DrawerLayout 与 HorizontalScrollView 进入内容菜单
Posted
技术标签:
【中文标题】DrawerLayout 与 HorizontalScrollView 进入内容菜单【英文标题】:DrawerLayout with HorizontalScrollView into content menu 【发布时间】:2014-03-07 09:32:37 【问题描述】:我的问题很简单。我可以在 DrawerLayout 的内容菜单中使用 HorizontalScrollView 吗? 我的 DrawerLayout 看起来像这样:
<android.support.v4.widget.DrawerLayout
android:id="@+id/pnlMenu"
android:layout_
android:layout_ >
<!-- Main content view -->
<ListView
android:id="@+id/lst"
android:layout_
android:layout_
android:clickable="true"
android:fastScrollEnabled="true"
android:focusable="true"
android:focusableInTouchMode="true"
tools:listitem="@layout/item_layout" >
</ListView>
<!-- Content of menu -->
<FrameLayout
android:id="@+id/drawerFrame"
android:layout_
android:layout_
android:layout_gravity="start"
android:clickable="true"
android:background="@color/black" >
<fragment
android:id="@+id/frag"
android:layout_
android:layout_
class="com.test.TestFragment" />
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
在片段内部,我有 HorizontalScrollView,但是当我尝试触摸它时没有任何反应,因为抽屉布局跟随我的手指。 我认为禁用内容菜单中的触摸事件并仅在单击主要内容视图时使 DrawerLayout 可关闭将解决我的问题。真的吗?如果没有,谁能告诉我该怎么办?
谢谢。
【问题讨论】:
【参考方案1】:基于此解决方案:https://***.com/a/7258579/452486
我已经能够使HorizontalScrollView
可滚动。
创建一个类扩展DrawerLayout
:
public class AllowChildInterceptTouchEventDrawerLayout extends DrawerLayout
private int mInterceptTouchEventChildId;
public void setInterceptTouchEventChildId(int id)
this.mInterceptTouchEventChildId = id;
public AllowChildInterceptTouchEventDrawerLayout(Context context)
super(context);
public AllowChildInterceptTouchEventDrawerLayout(Context context, AttributeSet attrs)
super(context, attrs);
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
if (mInterceptTouchEventChildId > 0)
View scroll = findViewById(mInterceptTouchEventChildId);
if (scroll != null)
Rect rect = new Rect();
scroll.getHitRect(rect);
if (rect.contains((int) ev.getX(), (int) ev.getY()))
return false;
return super.onInterceptTouchEvent(ev);
并添加要拦截drawerlayout触摸事件的child id
AllowChildInterceptTouchEventDrawerLayout drawerLayout = (AllowChildInterceptTouchEventDrawerLayout) findViewById(R.id.layoutdrawer_id);
drawerLayout.setInterceptTouchEventChildId(R.id.horizontalscrollview_id);
【讨论】:
我没有测试过,但这应该是一个可行的答案,我猜。 这对我有用,但如果像我的一样,您的ScrollView
在 include
内,请务必以包含为目标。否则它不会触发命中。
我用这个,但我得到了 classCastException【参考方案2】:
最好设置requestDisallowInterceptTouchEvent(true)
标志而不是返回false。当我们有一个HorizontalScrollView
并且在它下面有另一个视图(例如ListView
带有一些菜单项)并且我们从HorizontalScrollView
区域到上述ListView
进行动态手势时,应用程序将因NPE 而崩溃。这种情况发生在您第一次打开应用程序并通过汉堡图标转到DrawerLayout
时。使用这个:
if (rect.contains((int) ev.getX(), (int) ev.getY()))
this.requestDisallowInterceptTouchEvent(true);
【讨论】:
【参考方案3】:如果您想在您的DrawerLayout
中包含HorizontalScrollView
,那么到目前为止所有答案的替代策略是在打开抽屉时锁定抽屉。这意味着用户将无法通过滑动关闭抽屉,但 HorizontalScrollView
内部的滚动将按预期工作。
通过调用实现加锁
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
这个电话的一个方便的地方是onDrawerOpened
。
不幸的是,当用户点击稀松布(屏幕的暗淡部分未被抽屉占用)时,锁定还可以防止抽屉关闭。您需要自己抓住那个水龙头并关闭它,如下所示:
mDrawerLayout.setOnTouchListener(new View.OnTouchListener()
@Override
public boolean onTouch(View v, MotionEvent event)
int x = (int) event.getX();
int drawerWidth = (int)getResources().getDimension(R.dimen.your_drawer_width);
if (x > drawerWidth)
// inside scrim
mDrawerLayout.closeDrawer();
return true;
return false;
);
【讨论】:
简单的解决方案。此外,您需要在mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNDEFINED)
关闭抽屉之前将抽屉锁定模式设置为未定义。我发现没有这个抽屉一旦关闭就不会打开以上是关于DrawerLayout 与 HorizontalScrollView 进入内容菜单的主要内容,如果未能解决你的问题,请参考以下文章
android ToolBar与DrawerLayout笔记
android 应用架构随笔五(ActionBar与侧滑菜单DrawerLayout)
Android 中 DrawerLayout + ViewPager 怎么解决滑动冲突
SwiftUI 列表视图与 GroupedListStyle 和 HorizontalSizeClass 在 iOS 13.5 上切换到横向模式时定期中断