带有RecyclerView的Android ViewPager在BottomSheet中不正确地工作

当我尝试滚动列表,有时这工作不正确 – BottomSheet截获滚动事件和隐藏。

如何重现这一点:

  1. 打开底部表
  2. 更改ViewPager的页面
  3. 尝试滚动列表

结果:BottomSheet将被隐藏。

这里是示例代码:

编译'com.android.support:design:23.4.0'

MainActivity.java

package com.nkdroid.bottomsheetsample; import android.os.Bundle; import android.support.design.widget.BottomSheetBehavior; import android.support.design.widget.TabLayout; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private BottomSheetBehavior behavior; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final Button btnView = (Button) findViewById(R.id.btnView); btnView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { behavior.setState(BottomSheetBehavior.STATE_EXPANDED); } }); final View bottomSheet = findViewById(R.id.bottom_sheet); behavior = BottomSheetBehavior.from(bottomSheet); final ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager); viewPager.setAdapter(new MyPagerAdapter()); final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.setupWithViewPager(viewPager); } private class MyPagerAdapter extends PagerAdapter { @Override public int getCount() { return 15; } @Override public Object instantiateItem(final ViewGroup container, final int position) { final RecyclerView recyclerView = new RecyclerView(MainActivity.this); recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); recyclerView.setAdapter(new ItemAdapter()); container.addView(recyclerView); return recyclerView; } @Override public boolean isViewFromObject(final View view, final Object object) { return view.equals(object); } @Override public void destroyItem(final ViewGroup container, final int position, final Object object) { container.removeView((View) object); } @Override public CharSequence getPageTitle(final int position) { return String.valueOf(position); } } public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder> { @Override public ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) { return new ViewHolder(new TextView(MainActivity.this)); } @Override public void onBindViewHolder(final ViewHolder holder, final int position) { } @Override public int getItemCount() { return 100; } public class ViewHolder extends RecyclerView.ViewHolder { public TextView textView; public ViewHolder(final View itemView) { super(itemView); textView = (TextView) itemView; } } } } 

activity_main.xml中

 <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout android:id = "@+id/coordinatorLayout" xmlns:android = "http://schemas.android.com/apk/res/android" xmlns:app = "http://schemas.android.com/apk/res-auto" xmlns:tools = "http://schemas.android.com/tools" android:layout_width = "match_parent" android:layout_height = "match_parent" android:background = "#a3b1ef" android:fitsSystemWindows = "true" tools:context = ".ui.MainActivity" > <Button android:id = "@+id/btnView" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:text = "Show view" app:layout_behavior = "@string/appbar_scrolling_view_behavior" /> <LinearLayout android:id = "@+id/bottom_sheet" android:layout_width = "match_parent" android:layout_height = "400dp" android:background = "#fff" android:gravity = "center" android:orientation = "vertical" app:layout_behavior = "@string/bottom_sheet_behavior" > <android.support.design.widget.TabLayout android:id = "@+id/tabs" android:layout_width = "match_parent" android:layout_height = "wrap_content" app:tabMode = "scrollable" /> <android.support.v4.view.ViewPager android:id = "@+id/viewPager" android:layout_width = "match_parent" android:layout_height = "match_parent" /> </LinearLayout> </android.support.design.widget.CoordinatorLayout> 

截图

任何想法的解决方法?

我遇到了同样的限制,但能够解决这个问题。

您描述的效果的原因是BottomSheetBehavior (从v24.2.0开始)只支持在布局过程中以下列方式标识的一个滚动子项:

 private View findScrollingChild(View view) { if (view instanceof NestedScrollingChild) { return view; } if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; for (int i = 0, count = group.getChildCount(); i < count; i++) { View scrollingChild = findScrollingChild(group.getChildAt(i)); if (scrollingChild != null) { return scrollingChild; } } } return null; } 

你可以看到,它基本上find了使用DFS的第一个滚动的孩子。

我稍微增强了这个实现,并组装了一个小型以及一个示例应用程序。 你可以在这里find它: https : //github.com/laenger/ViewPagerBottomSheet

只需将maven回购url添加到您的build.gradle:

 repositories { maven { url "https://raw.github.com/laenger/maven-releases/master/releases" } } 

将库添加到依赖关系:

 dependencies { compile "biz.laenger.android:vpbs:0.0.2" } 

使用ViewPagerBottomSheetBehavior作为底部工作表视图:

 app:layout_behavior="@string/view_pager_bottom_sheet_behavior" 

在底部表单中设置任何嵌套的ViewPager:

 BottomSheetUtils.setupViewPager(bottomSheetViewPager) 

(这也适用于ViewPager 底部图表视图和更多的嵌套的ViewPagers)

样本实施