Scrollable
Scrollable copied to clipboard
Header reappears on top when returning to fragment that has been scrolled down.
Currently, in my project, I have a fragment that has a scrollable layout that hosts a header image and a recycler view. When scrolling down and hitting a button at the bottom of the recycler view a new fragment is added to the stack. When returning to the original fragment that has the scrollable layout the header appears at the top even though the recycler view is still scrolled to the bottom. What would be the best way to retain the headers state so when returning to the fragment the header is not shown if the recycler view is currently scrolled all the way down?
Hey! If state is not restored automatically, you can manually save scrollY
(scrollableLayout.getScrollY()
) value to a Bundle (onSaveInstanceState
) and then just apply it when you need it with scrollableLayout.setScrollY()
. Although I think it peculiar that RecyclerView saves state correctly... Can you check if your added to a backstack fragment goes through onDestroyView
phase?
Yea the fragment hosting the scrollable layout hits the onDestroyView when returning to it from the fragment above it.
Well, if fragment went through onDestroyView
but not onSaveInstanceState
you can try to leverage the fragment's arguments functionality. So, onDestroyView
you save scrollY
:
getArguments().putInt("key", scrollableLayout.getScrollY());
and in onViewCreated
(after everything has been initialized, like scroll listeners, etc):
scrollableLayout.setScrollY(getArguments().getInt("key", 0));
I tried that and doesn't seem to be working. My onViewCreated looks like this
int y = getArguments().getInt("key", 0);
Log.i(TAG, "onViewCreated: " + y);
mScrollableLayout.setScrollY(y);
Log.i(TAG, "onViewCreated: " + mScrollableLayout.getScrollY());
the first log is showing 545 but when I print the scrollableLayout.getScrollY() it prints 0.
Hm. Are you by any chance using autoMaxScroll
feature? If yes, then before applying previously saved scroll you need to wait for the ScrollableLayout
to be laid out (internally ScrollableLayout uses OnGlobalLayoutListener
). Just to verify, can you also log scrollableLayout.getMaxScrollY()
before applying setScrollY()
?
Yea im using autoMaxScroll and logging getMaxScrollY() before applying setScrollY() is showing 0 too.
Yeah, so I thought. I think there is a bug with state restoration in ScrollableLayout. Meanwhile, you could something like that:
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final ScrollableLayout scrollableLayout = view.findViewById(R.id.scrollable_layout);
// your initialization
final int savedScrollY = getArguments().getInt("key");
if (savedScrollY > 0) {
scrollableLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// here we might validate that scrollableLayout was called first
if (scrollableLayout.getMaxScrollY() > 0) {
scrollableLayout.setScrollY(savedScrollY);
scrollableLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
});
}
}
Cool, it Worked!! Thanks for the quick response.