Android ViewPager с RecyclerView работает неправильно внутри BottomSheet

Когда я пытаюсь прокрутить список, иногда это работает некорректно – BottomSheet перехватывает событие прокрутки и скрывает.

Как воспроизвести это:

  1. Открытый нижний лист
  2. Изменение страницы ViewPager
  3. Попробуйте прокрутить список

Результат: BottomSheet будет скрыт.

Вот пример кода:

Compile '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 ( 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; } 

Вы можете видеть, что он по существу находит первого прокручивающего ребенка с использованием DFS.

Я немного улучшил эту реализацию и собрал небольшую библиотеку, а также пример приложения. Вы можете найти его здесь: https://github.com/laenger/ViewPagerBottomSheet

Просто добавьте URL-адрес репозитория maven к вашему 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)

Выборочная реализация

Intereting Posts
Ошибка кинжала 2: зависимость "не может быть предоставлена ​​без конструктора @Inject" Пауза GC Ошибка после андроида 4.4.2 обновления Как уменьшить размер текста в формате xml? MVC в Android: приложение или служба для асинхронных обновлений? SetSoftInputMode для диалога, чтобы не скрывать EditText во время ввода? Как использовать карту Android для увеличения с помощью жесты (iphone like) Уведомление об отсутствии звука или вибрации? OnEnterAnimationComplete () не вызывается после транзакции активности Как правильно использовать Google Plus для входа в систему с несколькими действиями? Есть ли советы по управлению памятью, которые нужно соблюдать при создании приложений для Android? Можно ли наложить кнопку поверх другого? Как создать навигационный ящик без поддержки библиотеки Блендер и Вуфория Как повторно включить палитру дизайна в Android Studio SQLiteOpenHelper «onCreate» не называется? (БД не существует)