Проблемы с 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. Проблема описана здесь более подробно.

Так как мой нижний колонтитул можно расширить, чтобы заполнить экран, мне пришлось реализовать собственное решение:

  1. Чтобы нижний колонтитул не начинался скрытно, я добавляю высоту панели инструментов в качестве нижнего поля к представлению фрагмента детали.
  2. Чтобы предотвратить прокрутку нижнего колонтитула, я регистрирую OnOffsetChangedListener в AppBarLayout и передаю изменения смещения во фрагмент детали, который, в свою очередь, передает их в свое корневое представление и вызывает для него requestLayout ().
  3. Внутри 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. Это гарантирует, что он всегда в нужном месте.

Другие вопросы по тегам