noties / Scrollable

Android scrollable tabs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Header reappears on top when returning to fragment that has been scrolled down.

stshelton opened this issue · comments

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.