Recycleview в coordinatorlayout


Я пытаюсь создать RelativeLayout, который имеет CoordinatorLayout и LinearLayout в нижней части и обнаружил некоторое странное поведение, которое я не могу разрешить. Это мой макет

    <?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>

После изменения данных в адаптере я пытаюсь прокрутить до последнего элемента(например, recyclerView.smoothScrollToPosition (size);) и все, что я вижу, - это часть последнего представления (не полный размер). Если recycleview не вложен в CoordinatorLayout - все работает как ожидалось - я вижу полноразмерный вид последнего элемента. Как я могу измениться верстка, чтобы все работало правильно ?

4 5

4 ответа:

В вашем коде удалите app:layout_scrollFlags="scroll|enterAlways" из Toolbar и вместо этого добавьте его в AppBarLayout, поэтому он должен быть таким

<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>

Попробуйте сделать так:

<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">

Главное, чтобы использовать, чтобы добавить android: layout_marginBottom к вашей деятельности

Последний элемент обрезается, поскольку RecyclerView не полностью виден на экране. Он толкается вниз с помощью расширенной Панели приложений. Обратите внимание, что при прокрутке вручную панель приложений будет сжиматься по мере приближения к последнему элементу.

В моем случае лучше всего было просто свернуть панель приложений перед прокруткой:

AppBarLayout appBarLayout = (AppBarLayout) getActivity().findViewById(R.id.appbar);
appBarLayout.setExpanded(false, false);
recyclerView.smoothScrollToPosition(position);
Я полагаю, что вы могли бы улучшить это решение, свернув его только тогда, когда это необходимо.

Если сворачивание Панели приложений нежелательно, то вы можете добавить нижняя прокладка той же высоты, что и развернутая панель приложений. Однако будут и другие сбои (например, при прокрутке до позиции, которая уже находится в RecyclerView, но сразу за пределами экрана)

Проблема, кажется, в том, что smoothScrollToPosition() будет молча прокручивать RecyclerView, не давая CoordinatorLayout о том, что свиток происходит. Вот что я придумал. Хорошо, что он должен прокручивать только AppBarLayout, Если у вас достаточно элементов в адаптере.

    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;
            }
        }
    });
Теперь всякий раз, когда вы отправляете сообщение, сделайте следующее:
tryCollapseAppbarOnNextScroll = true;
recyclerView.smoothScrollToPosition(adapter.getItemCount()-1);