Элементы, добавленные в RecyclerView, не отображаются внизу

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

В настоящее время я использую .setStackFromEnd(true) на своем LinearLayoutManager, чтобы сообщения отображались снизу:

layMng = new LinearLayoutManager(this);
layMng.setStackFromEnd(true);

mRecyclerView.setLayoutManager(layMng);
mRecyclerView.setAdapter(mAdapter);

Что происходит, когда получено достаточно сообщений и список сообщений вот-вот переполнится за пределы верхней части экрана, он перестанет всегда показывать новые сообщения внизу. Мне приходится вручную прокручивать вниз, чтобы увидеть новые дополнения.

Как я могу заставить его либо всегда отображать новейшее сообщение, либо прокручивать RecyclerView вниз при получении нового элемента?

Я пробовал различные методы в своем менеджере компоновки, такие как .scrollToPosition() и .scrollToPositionWithOffset(), но ни одно из предложений, которые я видел до сих пор, не сработало. Некоторые из самых популярных вопросов StackOverflow по этой проблеме имеют лучшие ответы, которые даже не решают исходный вопрос.

Итак, как это делается?


person Orbit    schedule 23.06.2016    source источник
comment
Когда вы пробовали .scrollToPosition(), вы вызывали его в диспетчере макетов или в RecyclerView?   -  person Sammy T    schedule 23.06.2016
comment
Я пробовал оба. Который правильный? Насколько я мог судить, они не имели никакого эффекта.   -  person Orbit    schedule 23.06.2016
comment
можешь выложить свой xml файл, где объявлен recyclerview   -  person Gundu Bandgar    schedule 12.08.2019


Ответы (4)


Пожалуйста, проверьте layout_height. Это должно быть android:layout_height="match_parent"

Запустите smoothScrollToPosition в потоке пользовательского интерфейса

фрагмент кода из моего кода

            <android.support.v7.widget.RecyclerView
                android:id="@+id/topic_screen_list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginBottom="18dp"

                />

// здесь тема TopicScreenList ссылается на мой Recylerview: //-messageAdapter: ссылается на объект adpapter

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {

    LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
    layoutManager.setStackFromEnd(true);
    topicScreenList.setLayoutManager(layoutManager);
    topicScreenList.setAdapter(messageAdapter);
}

после получения любых новых сообщений из серверной службы вызывается следующий код

-Здесь MessageItem ссылается на новый элемент сообщения, потребляемый адаптером.

@Override
public void onNewMessage(final MessageItem messageItem) {
    if (getActivity() != null) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {                  
               messageAdapter.addMessageToEnd(messageItem);

       topicScreenList.smoothScrollToPosition(messageAdapter.getItemCount());

            }
        });
    }
}


//code from my Adapter  
public void addMessageToEnd(MessageItem messageItem) {
    messageItems.add(messageItem);
    notifyItemInserted(messageItems.size() -1);
}
person jee    schedule 19.11.2017

Попробуйте это, я также разрабатываю приложение для чата, и оно отлично работает для меня.

    mRecyclerView.setAdapter(adaptorChat);
    mRecyclerView.setHasFixedSize(true);
    LinearLayoutManager llm = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
    llm.setStackFromEnd(true);
    mRecyclerView.setLayoutManager(llm);

XML

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <android.support.v7.widget.RecyclerView
        android:id="@+id/messages_list_sponsor"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/edit_compose_msg_container" />

    <LinearLayout
        android:id="@+id/edit_compose_msg_container"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal"
        android:padding="3dp">

        <EditText
            android:id="@+id/compose_edit_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="10dp"
            android:layout_marginStart="10dp"
            android:layout_weight="1"
            android:background="@drawable/white_edit_text_style"
            android:hint="@string/enter_message"
            android:inputType="textMultiLine"
            android:minHeight="50dp"
            android:paddingEnd="4dp"
            android:paddingLeft="6dp"
            android:paddingRight="4dp"
            android:paddingStart="6dp"
            android:singleLine="false"
            android:textColor="@color/black"
            android:textColorHint="@android:color/darker_gray" />

        <ImageView
            android:id="@+id/send_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="5"
            android:clickable="true"
            android:padding="15dp"
            android:rotation="-35"
            android:layout_marginBottom="5dp"
            android:src="@drawable/message_send" />
    </LinearLayout>
</RelativeLayout>
person Sanoop Surendran    schedule 23.06.2016
comment
Помимо .setHasFixesSize (который, я не думаю, имеет отношение к этой проблеме), это то, что у меня уже было. Как выглядит ваш xml для вашего recyclerview? - person Orbit; 23.06.2016
comment
@Orbit.. Проверьте сейчас.. Посмотрим, будет ли это полезно - person Sanoop Surendran; 23.06.2016
comment
@Orbit LinearLayout содержит EditText и Button - person Sanoop Surendran; 23.06.2016
comment
Единственное отличие, которое у вас было, это то, что высота вашего recyclerviews была wrap_content, но это, похоже, также не влияет на эту проблему. Вы уверены, что ваша версия действительно работает так, как я описал в своем OP? - person Orbit; 23.06.2016

mRecyclerView.scrollToPosition(position); должно работать. Возможно, он пытается выполнить прокрутку до обновления положения/адаптера. Пытаться:

int delay = 500;

Handler handler = new Handler();
handler.postDelayed(new Runnable() {
    public void run() {
        //scroll to bottom
        mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount());
    }
}, delay);
person Sammy T    schedule 23.06.2016
comment
Кажется, не имеет никакого эффекта. - person Orbit; 23.06.2016
comment
Можете ли вы отредактировать свой исходный пост с кодом, показывающим, откуда вы звоните? - person Sammy T; 23.06.2016
comment
В мобильном банкомате, но я вызывал код, который вы разместили в моих действиях onCreate (), после того, как все настройки RV и адаптера были выполнены. - person Orbit; 23.06.2016
comment
Если он полностью загружен, он должен работать в onCreate, но не поможет вам при добавлении представления. Вы должны обязательно вызвать его после обновления адаптера. - person Sammy T; 23.06.2016
comment
Вот как я сначала попробовал это со своим собственным кодом, я делал adapter.add(object), а затем делал плавную прокрутку. Попробую ваш код с помощью runnable и сообщу позже. - person Orbit; 23.06.2016
comment
Да, это должно быть вызвано добавлением и вызвано после mAdapter.notifyDataSetChanged(); - person Sammy T; 23.06.2016
comment
Хм, для smoothScrollToPosition требуется собственный менеджер компоновки? В документах упоминается, что вам нужно переопределить RecyclerView.LayoutManager.smoothScrollToPosition, чтобы он работал, но, похоже, он работает, просто вызывая mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount());. Есть идеи, почему? - person Orbit; 24.06.2016
comment
Ну, я никогда не использовал Override, но, насколько я могу судить, использование .scrollToPosition() и .smoothScrollToPosition() более или менее одинаково, если только вы не хотите контролировать плавное движение прокрутки. Так что нет, если вы хотите использовать прокрутку по умолчанию. И да, если вы хотите рассчитать прокрутку самостоятельно. - person Sammy T; 24.06.2016

если вы установили mRecyclerView.setNestedScrollingEnabled(false), удалите это.

person Gundu Bandgar    schedule 12.08.2019