Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoordinatorLayout with CollapsingToolbarLayout breaks with Keyboard in Dialog fragment

I recently decided to move my app to using the new Support design library, and recently discovered a very nasty bug.

Say I have a CoordinatorLayout hosting an AppBarLayout and any scrollable view, be it a ViewPager, NestedScrollView, or even a RecyclerView with the required scroll behavior; choosing to display a dialog fragment that displays the keyboard causes the AppBarLayout to disconnect from the scrolling view and they don't scroll together anymore.

Furthermore, The scrolling view is forced to resize to half the screen at the bottom, and the AppBar layout takes the top half, despite it not needing it.

A video of the bug is here: Youtube Link

EDIT:

Setting the the softInputMode of the Keyboard in the Activity to "adjustPan" fixes the issue. Apparently the CoordinatorLayout does not like being resized dynamically by the keyboard.

The offending XML looks like this, but I have multiple XML variations that exhibit this behavior, with the common element among them all being they use a CollapsingToolbarLayout:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="192dp"
    android:background="@color/transparent">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="144dp"
        android:elevation="4dp"
        app:contentScrim="?attr/colorPrimary"
        app:expandedTitleMarginBottom="@dimen/quadruple_margin"
        app:layout_collapseParallaxMultiplier="0.7"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:animateLayoutChanges="true"
            android:background="@color/primary"
            android:orientation="vertical">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="bottom"
                android:adjustViewBounds="true"
                android:scaleType="centerCrop"
                android:src="@drawable/ranking_background" />

            <View
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_alignParentTop="true"
                android:layout_gravity="bottom"
                android:background="@color/black_40" />

            <de.hdodenhof.circleimageview.CircleImageView
                android:id="@+id/profile_picture"
                android:layout_width="@dimen/double_margin"
                android:layout_height="@dimen/double_margin"
                android:layout_alignBottom="@+id/text"
                android:layout_marginLeft="@dimen/double_margin"
                android:layout_marginStart="@dimen/double_margin"
                android:src="@drawable/image_placeholder"
                android:visibility="gone" />

            <TextView
                android:id="@+id/text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_alignWithParentIfMissing="true"
                android:layout_marginLeft="@dimen/single_margin"
                android:layout_marginStart="@dimen/single_margin"
                android:layout_marginTop="@dimen/quadruple_margin"
                android:layout_toRightOf="@+id/profile_picture"
                android:text="@string/my_places_for"
                android:textColor="@color/white"
                android:textSize="20sp"
                android:visibility="gone" />

            <TextView
                android:id="@+id/sub_text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/text"
                android:layout_marginLeft="@dimen/single_margin"
                android:layout_marginStart="@dimen/single_margin"
                android:layout_marginTop="@dimen/single_margin"
                android:text="@string/pick_category_or_business"
                android:textColor="@color/white"
                android:textSize="16sp"
                android:visibility="gone" />
        </RelativeLayout>

        <android.support.v7.widget.Toolbar
            android:id="@+id/action_bar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/abc_action_bar_default_height_material"
            app:contentInsetLeft="@dimen/triple_margin"
            app:contentInsetStart="@dimen/triple_margin"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/Theme.AppCompat.NoActionBar"
            app:theme="@style/Theme.AppCompat.NoActionBar" />
    </android.support.design.widget.CollapsingToolbarLayout>

    <android.support.design.widget.CollapsingToolbarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/primary"
        app:layout_scrollFlags="scroll">

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:layout_alignParentBottom="true"
            android:background="@color/primary"
            android:elevation="4dp"
            app:layout_scrollFlags="enterAlways"
            app:tabGravity="fill"
            app:tabMode="fixed"
            app:tabSelectedTextColor="@color/white"
            app:tabTextColor="@color/grey_400" />
    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>

like image 417
Tunji_D Avatar asked Jun 12 '15 10:06

Tunji_D


2 Answers

The answer provided by Tunji_D will solve the problem, but not necessarily the underlying issue.

The scroll behavior on the coordinator layout has an issue right now during its invalidation step on its child views: https://code.google.com/p/android/issues/detail?id=176373#c5

So in order to fix it use this workaround provided by junya, and set your view's behavior with

app:layout_behavior="com.app.common.PatchedScrollingViewBehavior"

and use:

public class PatchedScrollingViewBehavior extends AppBarLayout.ScrollingViewBehavior {

    public PatchedScrollingViewBehavior() {
        super();
    }

    public PatchedScrollingViewBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onMeasureChild(CoordinatorLayout parent, View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
        if(child.getLayoutParams().height == -1) {
            List dependencies = parent.getDependencies(child);
            if(dependencies.isEmpty()) {
                return false;
            }

            AppBarLayout appBar = findFirstAppBarLayout(dependencies);
            if(appBar != null && ViewCompat.isLaidOut(appBar)) {
                if(ViewCompat.getFitsSystemWindows(appBar)) {
                    ViewCompat.setFitsSystemWindows(child, true);
                }

                int scrollRange = appBar.getTotalScrollRange();
//                int height = parent.getHeight() - appBar.getMeasuredHeight() + scrollRange;
                int parentHeight = View.MeasureSpec.getSize(parentHeightMeasureSpec);
                int height = parentHeight - appBar.getMeasuredHeight() + scrollRange;
                int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
                parent.onMeasureChild(child, parentWidthMeasureSpec, widthUsed, heightMeasureSpec, heightUsed);
                return true;
            }
        }

        return false;
    }


    private static AppBarLayout findFirstAppBarLayout(List<View> views) {
        int i = 0;

        for(int z = views.size(); i < z; ++i) {
            View view = (View)views.get(i);
            if(view instanceof AppBarLayout) {
                return (AppBarLayout)view;
            }
        }

        return null;
    }
}
like image 166
apollow Avatar answered Nov 10 '22 21:11

apollow


Go to your Android manifest and change the "Window soft input mode" to :

android:windowSoftInputMode="adjustPan|adjustNothing"
like image 41
HeyGawau Avatar answered Nov 10 '22 21:11

HeyGawau