Проблемы с CoordinatorLayout, ViewPager и requestLayout / onMeasure / onLayout на Android 4.2 или старше
Мне нужна помощь по очень странной проблеме. Кажется, я единственный, кто наткнулся на это. В моем приложении ни requestLayout(), ни invalidate () не имеют никакого эффекта внутри вложенного фрагмента на устройствах под управлением Android 4.0, 4.1 и 4.2 (протестировано как на эмуляторе, так и на реальных устройствах).
Когда я перехожу к тому месту, где мне нужно вызвать requestLayout(), иерархия макета действия содержит основной поток сведений и выглядит примерно так (обратите внимание, что я динамически добавляю все фрагменты в оболочку FrameLayout):
<DrawerLayout>
<CoordinatorLayout>
<LinearLayout (horizontal)>
<fragment in FrameLayout --> master/>
<ViewPager (using FragmentStatePagerAdapter)>
<PagerTabStrip/>
<fragment pages, each being only a single RecyclerView/>
</ViewPager>
</fragment in FrameLayout>
<fragment in FrameLayout --> detail>
<RelativeLayout>
<ViewPager (using FragmentStatePagerAdapter)/>
<a custom footer view that can be expanded to fill the screen/>
</RelativeLayout>
</fragment in FrameLayout>
</LinearLayout>
<AppBarLayout>
<Toolbar>
</AppBarLayout>
</CoordinatorLayout>
<NavigationView/>
</DrawerLayout>
Теперь у меня возникла проблема: нижний колонтитул стал скрытым из-за поведения CoordinatorLayout. Проблема описана здесь более подробно.
Так как мой нижний колонтитул можно расширить, чтобы заполнить экран, мне пришлось реализовать собственное решение:
- Чтобы нижний колонтитул не начинался скрытно, я добавляю высоту панели инструментов в качестве нижнего поля к представлению фрагмента детали.
- Чтобы предотвратить прокрутку нижнего колонтитула, я регистрирую OnOffsetChangedListener в AppBarLayout и передаю изменения смещения во фрагмент детали, который, в свою очередь, передает их в свое корневое представление и вызывает для него requestLayout ().
- Внутри onMeasure () корневое представление добавляет смещение к первоначально измеренной высоте.
На Android 4.3 и выше это работает отлично. Нижний колонтитул всегда прикреплен к нижней части экрана и. Когда развернуто, представление также прикреплено к вершине, увеличиваясь и уменьшаясь в зависимости от смещения панели приложения. Нет проблем.
Но ниже Android 4.3, через некоторое время requestLayout () просто не имеет никакого эффекта! Я пробовал invalidate () и forceLayout () тоже. Ни onMeasure (), ни onLayout () не вызываются, и панель продолжает прокручиваться, иногда зависая над нижней частью экрана, а иногда прокручиваясь за пределами экрана. Я абсолютно не представляю, как это возможно, но я заметил, что это зависит от ViewPager: при смахивании любого из них не более двух раз нижний колонтитул как-то отсоединяется.
На данный момент я вставил некоторые if-предложения, чтобы убедиться, что моя реализация работает только для 4.3 и выше. Так что в Android 4.0, 4.1 и 4.2 нижний колонтитул прокручивается и выходит. Но это просто отстой, поэтому, пожалуйста, помогите: что я могу сделать, чтобы это работало для этих версий? Кроме того, у вас есть другие идеи, как прикрепить нижний колонтитул к нижней части и при этом сделать его красивым?
1 ответ
Я решил это, переместив нижний колонтитул к координатору и используя BottomSheet. Это гарантирует, что он всегда в нужном месте.