Android 4.2 或更早版本上 CoordinatorLayout、ViewPager 和 requestLayout / onMeasure / onLayout 的问题
Problems with CoordinatorLayout, ViewPager and requestLayout / onMeasure / onLayout on Android 4.2 or older
关于一个非常奇怪的问题,我需要一些帮助。看来我是唯一偶然发现它的人。在我的应用程序中,requestLayout() 和 invalidate() 在设备 运行 Android 4.0、4.1 和 4.2(在模拟器和真实设备上均经过测试)上的嵌套片段内没有任何影响。
当我导航到我必须调用 requestLayout() 的位置时,activity 的布局层次结构包含一个主细节流程,大致如下所示(请注意,我将所有片段动态添加到 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 的行为,页脚开始隐藏。更详细地描述了问题 。
由于我的页脚可以展开以填满屏幕,我不得不实施自定义解决方案:
- 为了确保页脚不会开始隐藏,我将工具栏高度添加为详细信息片段视图的底部边距。
- 为了防止页脚滚动,我在 AppBarLayout 上注册了一个 OnOffsetChangedListener 并将偏移量更改传递给细节片段,后者又将它们传递给它的根视图并在其上调用 requestLayout()。
- 在 onMeasure() 内部,根视图将偏移量添加到最初测量的高度。
在 Android 4.3 及更高版本上,这可以完美运行。页脚始终固定在屏幕底部。展开时,视图也会根据应用栏偏移量通过增大和缩小来固定到顶部。没问题。
但是低于Android 4.3,一段时间后requestLayout()根本就没有效果了!我也试过 invalidate() 和 forceLayout() 。 onMeasure() 和 onLayout() 都没有被调用,并且栏一直滚动,有时悬停在屏幕底部上方,有时滚动到屏幕外。我完全不知道这是怎么可能的,但我观察到这取决于 ViewPagers:最多滑动其中任何一个两次时,页脚会以某种方式分离。
目前,我加入了一些 if 子句以确保我的实现仅针对 4.3 及更高版本触发。所以在 Android 4.0、4.1 和 4.2 上,页脚滚动进出。但这很糟糕,所以请帮忙:我该怎么做才能让它适用于这些版本?或者,您是否有其他想法如何将页脚固定在底部并仍然让它看起来不错?
我通过将页脚向上移动到协调器并使用 BottomSheet 解决了这个问题。这样可以确保它始终位于正确的位置。
关于一个非常奇怪的问题,我需要一些帮助。看来我是唯一偶然发现它的人。在我的应用程序中,requestLayout() 和 invalidate() 在设备 运行 Android 4.0、4.1 和 4.2(在模拟器和真实设备上均经过测试)上的嵌套片段内没有任何影响。
当我导航到我必须调用 requestLayout() 的位置时,activity 的布局层次结构包含一个主细节流程,大致如下所示(请注意,我将所有片段动态添加到 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 的行为,页脚开始隐藏。更详细地描述了问题
由于我的页脚可以展开以填满屏幕,我不得不实施自定义解决方案:
- 为了确保页脚不会开始隐藏,我将工具栏高度添加为详细信息片段视图的底部边距。
- 为了防止页脚滚动,我在 AppBarLayout 上注册了一个 OnOffsetChangedListener 并将偏移量更改传递给细节片段,后者又将它们传递给它的根视图并在其上调用 requestLayout()。
- 在 onMeasure() 内部,根视图将偏移量添加到最初测量的高度。
在 Android 4.3 及更高版本上,这可以完美运行。页脚始终固定在屏幕底部。展开时,视图也会根据应用栏偏移量通过增大和缩小来固定到顶部。没问题。
但是低于Android 4.3,一段时间后requestLayout()根本就没有效果了!我也试过 invalidate() 和 forceLayout() 。 onMeasure() 和 onLayout() 都没有被调用,并且栏一直滚动,有时悬停在屏幕底部上方,有时滚动到屏幕外。我完全不知道这是怎么可能的,但我观察到这取决于 ViewPagers:最多滑动其中任何一个两次时,页脚会以某种方式分离。
目前,我加入了一些 if 子句以确保我的实现仅针对 4.3 及更高版本触发。所以在 Android 4.0、4.1 和 4.2 上,页脚滚动进出。但这很糟糕,所以请帮忙:我该怎么做才能让它适用于这些版本?或者,您是否有其他想法如何将页脚固定在底部并仍然让它看起来不错?
我通过将页脚向上移动到协调器并使用 BottomSheet 解决了这个问题。这样可以确保它始终位于正确的位置。