dmtrlbdv
dmtrlbdv

Reputation: 327

Recycleview in coordinatorlayout

I am trying to create RelativeLayout that has CoordinatorLayout and LinearLayout at bottom and found some strange behavior that I can't resolve. This is my layout

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.support.design.widget.CoordinatorLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/sender"
        android:background="@android:color/white"
        android:fitsSystemWindows="true">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?actionBarSize"
                android:background="?colorPrimary"
                app:layout_scrollFlags="scroll|enterAlways" />

        </android.support.design.widget.AppBarLayout>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/messages_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    </android.support.design.widget.CoordinatorLayout>

    <LinearLayout
        android:id="@+id/sender"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:gravity="center_vertical"
        android:background="@android:color/white">

        <EditText
            android:id="@+id/inputText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:inputType="text" />

        <Button
            android:fontFamily="sans-serif"
            style="?android:attr/borderlessButtonStyle"
            android:textAppearance="?android:textAppearanceButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/send"
            android:textColor="?colorPrimary"
            android:id="@+id/send"/>

    </LinearLayout>

</RelativeLayout>

After changing data in adapter I trying to scroll to last element ( for example by recyclerView.smoothScrollToPosition(size); )and all I see is part of last view (not full size). If recycleview not nest to CoordinatorLayout - all works as expecting - I see full sized last element view. How can I change layout to works it all correctly ?

Upvotes: 5

Views: 3270

Answers (4)

Vilen
Vilen

Reputation: 5061

in your code remove app:layout_scrollFlags="scroll|enterAlways" from Toolbar and instead add it to AppBarLayout so it should be like this

<android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_scrollFlags="scroll|enterAlways">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?actionBarSize"
            android:background="?colorPrimary"/>

</android.support.design.widget.AppBarLayout>

Upvotes: 0

M-Wajeeh
M-Wajeeh

Reputation: 17304

Issue seems to be that smoothScrollToPosition() will silently scroll RecyclerView without letting CoordinatorLayout about the scroll being happening. This is what I came up with. Nice thing about it is that it should only scroll AppBarLayout if you have enough items in Adapter.

    final AppBarLayout layout = (AppBarLayout) findViewById(R.id.appbar);
    layout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
            lastVerticalOffset = verticalOffset;
        }
    });
    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            if (tryCollapseAppbarOnNextScroll && lastVerticalOffset != -layout.getTotalScrollRange()) {
                layout.setExpanded(false);
                tryCollapseAppbarOnNextScroll = false;
            }
        }
    });

Now whenever you send a message, do this:

tryCollapseAppbarOnNextScroll = true;
recyclerView.smoothScrollToPosition(adapter.getItemCount()-1);

Upvotes: 1

AndyDeveloper
AndyDeveloper

Reputation: 3030

The last element is clipped because the RecyclerView is not entirely visible on the screen. It is being pushed down by the expanded AppBar. Note that when scrolling manually, the AppBar will shrink as you reach the last element.

What worked best in my case was to simply collapse the AppBar before scrolling:

AppBarLayout appBarLayout = (AppBarLayout) getActivity().findViewById(R.id.appbar);
appBarLayout.setExpanded(false, false);
recyclerView.smoothScrollToPosition(position);

I imagine you could improve on this solution by collapsing it only when needed.

If collapsing the AppBar is not desired, then you could add bottom padding of the same height as the expanded AppBar. However, there will be other glitches (e.g. when scrolling to a position which is already in the RecyclerView, but just outside of the screen)

Upvotes: 0

Andrii Kovalchuk
Andrii Kovalchuk

Reputation: 4907

Try this way:

<RelativeLayout 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:layout_marginBottom="16dp">

The main point is to use to add android:layout_marginBottom to your activity

Upvotes: 0

Related Questions