Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cheesesquare: enterAlways produces wrong layout

Adding enterAlways to the scroll flags of the Cheesesquare demo:

<android.support.design.widget.CollapsingToolbarLayout
    android:id="@+id/collapsing_toolbar"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    app:contentScrim="?attr/colorPrimary"
    app:layout_scrollFlags="scroll|exitUntilCollapsed|enterAlways">

results in a wrong layout:

enter image description here

During scrolling down, the header comes in correctly but it doesn't stop in the correct position. Scrolling further displaces the parts: the backdrop image appears in the wrong position and the toolbar becomes invisible because of the changes in the background color. (I also added a colorPrimary background to the toolbar here to make it more visible but the problem doesn't depend on the color, of course). The libraries are the latest as of today, 23.1.0.

Is there any workaround or we have to wait for it to be fixed in the library? Right now, it seems to be a showstopper for any app needing this functionality.

enterAlwaysCollapsed works but that gives a different functionality, it's not a workaround.

like image 456
Gábor Avatar asked Sep 27 '22 18:09

Gábor


1 Answers

I solved this issue with a bit of patching to the AppBarLayout class source code. Apparently they didn't think people will use it like this. Or they did and I'm way off. anyways it works for me.

You need to make a small change to this method. look for SCROLL_FLAG_EXIT_UNTIL_COLLAPSED

 /**
 * Return the scroll range when scrolling down from a nested pre-scroll.
 */
private int getDownNestedPreScrollRange() {
    if (mDownPreScrollRange != INVALID_SCROLL_RANGE) {
        // If we already have a valid value, return it
        return mDownPreScrollRange;
    }

    int range = 0;
    for (int i = getChildCount() - 1; i >= 0; i--) {
        final View child = getChildAt(i);
        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
        final int childHeight = child.getMeasuredHeight();
        final int flags = lp.mScrollFlags;

        if ((flags & LayoutParams.FLAG_QUICK_RETURN) == LayoutParams.FLAG_QUICK_RETURN) {
            // First take the margin into account
            range += lp.topMargin + lp.bottomMargin;
            // The view has the quick return flag combination...
            if ((flags & LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED) != 0) {
                // If they're set to enter collapsed, use the minimum height
                range += ViewCompat.getMinimumHeight(child);
                // This is what is missing...
            } else if ((flags & LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED) == LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED) {
                range += childHeight - ViewCompat.getMinimumHeight(child);
            } else {
                // Else use the full height
                range += childHeight;
            }
        } else if (range > 0) {
            // If we've hit an non-quick return scrollable view, and we've already hit a
            // quick return view, return now
            break;
        }
    }
    return mDownPreScrollRange = range;
}

You may need to decrement the status bar height if you are using "android:fitsSystemWindows="true".

Hope it helps. There a some classes that you will need to copy from the design library to allow all imports & some methods that will turn public.

Cheers.

like image 131
TalMihr Avatar answered Oct 23 '22 03:10

TalMihr