I need some help concerning a very strange problem. It seems I'm the only one that stumbled upon it. In my app neither requestLayout() nor invalidate() have any effect inside a nested fragment on devices running Android 4.0, 4.1 and 4.2 (tested both on both emulator and real devices).
When I navigate to where I have to call requestLayout(), the activity's layout hierarchy contains a master detail flow and looks roughly like this (note that I add all fragments dynamically to a FrameLayout wrapper):
<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>
Now a problem I had was that the footer started hidden because of the behavior of CoordinatorLayout. The problem is described here in more detail.
Since my footer can be expanded to fill the screen, I had to implement a custom solution:
- To make sure the footer doesn't start hidden, I add the toolbar height as the bottom margin to the detail fragment's view.
- To prevent the footer from scrolling, I register an OnOffsetChangedListener on the AppBarLayout and pass the offset changes to the detail fragment, which in turn passes them to its root view and calls requestLayout() on it.
- Inside onMeasure(), the root view adds the offset to the height measured originally.
On Android 4.3 and above, this works perfectly. The footer is always pinned to the bottom of the screen and. When expanded, the view is also pinned to the top by growing and shrinking depending on the app bar offset. No problems.
But below Android 4.3, after some time requestLayout() simply has no effect at all! I tried invalidate() and forceLayout() too. Neither onMeasure() nor onLayout() are called and the bar keeps scrolling, sometimes hovering above the bottom of the screen and sometimes scrolling outside the screen. I have absolutely no idea how that is possible, but I observed that it depends on the ViewPagers: When swiping any of them at most twice, the footer gets detached somehow.
For now, I put in some if-clauses to make sure my implementation only fires for 4.3 and above. So on Android 4.0, 4.1 and 4.2 the footer scrolls in and out. But that just sucks, so please help: What can I do to make it work for those versions? Alternatively, do you have other ideas how to pin the footer to the bottom and still make it look nice?