ViewPager в CoordinatorLayout неожиданно сжимается
В моем Android-приложении, работающем на Android 5.1.1, у меня есть макет с использованием Toolbar
с TabLayout
, а внизу - ViewPager
. Все они объединены в CoordinatorLayout
.
На первой странице ViewPager
есть RecyclerView
обслуживающий CardView
элемент.
Моя проблема в том, что мой ViewPager
продолжает изменяться таким образом, чтобы мои элементы списка CardView
обрезались.
Моя основная компоновка выглядит в основном так:
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent" >
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.design.widget.CoordinatorLayout>
И первый фрагмент, который обслуживает мой ViewPager
, выглядит так:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v7.widget.RecyclerView
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"/>
</FrameLayout>
Это делает что-то похожее на это:
![введите описание изображения здесь]()
При нажатии кнопки в моем макете я использую startActivityForResult
для вызова другого действия, а иногда при возврате к моей работе мой список обрезается так, что видится только половина первого элемента:
![введите описание изображения здесь]()
После поворота по горизонтали на другой пейджер в ViewPager
, а затем обратно проблема исчезнет, поэтому кажется, что повторная компоновка не была правильно запущена. Нажатие HOME и возобновление моей активности НЕ разрешают проблему. Обратите внимание, что это происходит, даже если я не изменяю свой макет каким-либо образом, я просто возвращаюсь из вызова startActivityForResult. И да, это случается иногда... И у меня нет фоновых потоков, которые могли бы объяснить кажущееся случайное поведение.
Сначала я подумал, что это уменьшилось RecyclerView
, но с помощью HierarchyViewer я смог найти, что на самом деле весь ViewPager
уменьшился примерно до половины его первоначальной высоты.
Я попробовал разные хаки, чтобы обойти это, включая вызов invalidate()
и requestLayout()
на весь мой просмотр hiearchy, но ничего не помогло (хотя прокрутка на другую страницу и обратно исправлена). Кроме того, это не те решения, к которым я хочу прибегнуть... Затем я попытался изменить высоту ViewPager на wrap_content
, что фактически решило эту конкретную проблему; после возвращения в мою работу первый элемент в моем RecyclerView
никогда не обрезается, и я могу прокручивать вниз до других элементов. Однако теперь вместо этого последний элемент моего списка всегда обрезается, как видно на этом скриншоте, где список прокручивается до конца:
![введите описание изображения здесь]()
Поскольку я сейчас нахожусь в точке, где я действительно не понимаю, что происходит, мне нужна помощь. Что я должен использовать как layout_height для моего ViewPager и, прежде всего, почему? Для меня match_parent
имеет смысл, но как я должен здесь думать? Есть ли разумная причина, которую мои взгляды обрезали при использовании match_parent
, или я действительно столкнулся с ошибкой в ViewPager
, RecyclerView
и/или CoordinatorLayout
? Как я могу убедиться, что мой ViewPager
последовательно заполняет всю область экрана под AppBar и что мой RecyclerView
можно прокручивать по вертикали для правильного отображения всех элементов списка CardView
?
Ответы
Ответ 1
У меня возникла аналогичная проблема при использовании более старой версии библиотеки поддержки.
См. следующие проблемы:
https://code.google.com/p/android/issues/detail?id=176406
https://code.google.com/p/android/issues/detail?id=176187
Убедитесь, что вы используете последнюю версию Support library
, версия 23.1, начиная с этой записи.
Ответ 2
Оказывается, это почти наверняка ошибка в CoordinatorLayout
или, что еще более вероятно, в AppBarLayout$ScrollingViewBehavior
. Стремясь создать MCVE, я понял, что мой суб-активность имел IME на экране, что вызвало сокращение ViewPager - когда моя активность возобновляется после onActivityResult
, ViewPager
сокращается в результате уменьшенной экранной недвижимости от IME, но никогда не расширяется, несмотря на то, что IME больше не отображается и факт, что CoordinatorLayout
действительно расширен.
После отладки и перехода через onLayout
и onMeasure
из CoordinatorLayout
и ViewPager
теперь я уверен, что CoordinatorLayout
неправильно передает изменение размера своим дочерним элементам.
Я обнаружил, что могу "исправить" проблему, вызвав requestLayout
на моем ViewPager
, но только если вызов достаточно задерживается (10 мс никогда не работает, 100 мсек работает большую часть времени):
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mViewPager.requestLayout();
}
}, 100);
}
Это, очевидно, не надежное решение, но, выяснив, что еще больше выясняется, мне, вероятно, даже не нужно CoordinatorLayout
, так как у меня нет никакого продвинутого поведения прокрутки. Поэтому моим решением будет просто перейти с LinearLayout
или RelativeLayout
в качестве моей группы корневого представления. Приятно и просто, не нужно усложнять вещи.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent" >
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Однако я попытаюсь сконденсировать это в простой пример и указать ошибку с Google.
Что касается того, что я должен использовать в качестве высоты для моего ViewPager
, мое первоначальное использование match_parent
по-прежнему представляется разумным. Тот факт, что wrap_content
решил проблему (но вызвал другие проблемы), вероятно, был просто из-за несоответствий, вызванных ошибкой.
Ответ 3
В вашем фрагменте просто удалите frameLayout и создайте родительский элемент recyclerView... Надеюсь, он сработает:
<android.support.v7.widget.RecyclerView
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp">
<android.support.v7.widget.RecyclerView/>