Прокрутите RecyclerView вверх соответственно при открытии клавиатуры

Я создал чат и, как мессенджер facebook, внизу есть EditText, а выше - RecyclerView сообщений. Когда открывается клавиатура, я хочу прокрутить RecyclerView ровно настолько, насколько он должен прокручиваться вверх. Чтобы быть более конкретным, давайте предположим, что в RecyclerView есть 5 сообщений, и в настоящее время 3-е сообщение находится чуть выше EditText. Поэтому, когда клавиатура открыта, я хочу оставить третье сообщение чуть выше EditText, как и раньше. Я искал, но не смог найти. Если это дублирующий вопрос, я буду признателен, если кто-нибудь может предоставить ссылку.


person Ariful Hoque Maruf    schedule 24.11.2017    source источник
comment
Пробовал уже, не получилось.   -  person Ariful Hoque Maruf    schedule 24.11.2017
comment
android:windowSoftInputMode=adjustPan попробуйте этот.   -  person mehul chauhan    schedule 24.11.2017
comment
Возможный дубликат stackoverflow .com/questions/34102741/   -  person Hemant Parmar    schedule 24.11.2017
comment
Ну, я не хочу прокручивать до последнего элемента @HemantParmar   -  person Ariful Hoque Maruf    schedule 24.11.2017
comment
Это тоже не сработало @mehul   -  person Ariful Hoque Maruf    schedule 24.11.2017


Ответы (7)


recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
            if ( bottom < oldBottom) {
                recyclerView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        recyclerView.scrollToPosition(adapter.getItemCount());
                    }
                }, 100);
            }
        }
    });

если это не работает, используйте smoothScrollToPosition вместо scrollToPosition

Это работа для меня.

person Ulagapandi UPMS    schedule 08.11.2019

Поздний ответ, но, возможно, кто-то найдет его полезным.

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

Предполагая, что самые новые сообщения находятся первыми в вашем списке/массиве, вы можете просто установить LinearLayoutManager в обратном порядке.

layoutManager.reverseLayout = true

Я не могу объяснить, почему, но похоже, что RecyclerView всегда пытается сохранить положение прокрутки верхней границы. Поэтому, когда отображается клавиатура, доступное вертикальное пространство сжимается, и RecyclerView просто пытается сохранить свою верхнюю часть такой же, как и раньше. Сделав его обратным макетом, вы можете добиться желаемого поведения.

person Marat    schedule 24.12.2019

Я искал правильное решение, и я нашел его, я думаю.

Когда вы размещаете свой recyclerview внутри ConstraintLayout, думая таким образом, что вы можете легко разместить свой recyclerview правильно по отношению к другим вашим представлениям (в вашем случае ваш текст редактирования), это не сработает.

Раньше это был мой макет xml, где он не работал (у меня reverseLayout=true в моем LinearLayoutManager):

<androidx.constraintlayout.widget.ConstraintLayout>

  <RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    app:layout_constraintBottom_toTopOf="@id/editText"
    app:layout_constraintTop_toBottomOf="parent" />

  <EditText
    android:id="@+id/editText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toBottomOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

С этим макетом каждый раз, когда я открывал или закрывал клавиатуру, нажимая EditText, позиция прокрутки немного перемещалась вверх.

Я исправил это, не используя ConstraintLayout, а заменив его на старый добрый RelativeLayout вот так:

<RelativeLayout>

  <RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_above="@id/editText"
    android:layout_height="match_parent" <!-- This is important, with 0dp it still doesnt work  -->
     />

  <EditText
    android:id="@+id/editText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true" />

</RelativeLayout>

При установке высоты RecyclerView на match_parent это будет работать. (Причина, по которой мы используем RelativeLayout, заключается в том, что в ConstraintLayout вы не можете установить layouth_height равным match_parent дочерних представлений, иначе он не будет работать должным образом.)

person Hylke    schedule 17.12.2020
comment
У меня был recyclerView внутри RelativeLayout с высотой 0dp, положением между двумя представлениями. Как ни странно, установка высоты на matchParent сделала свое дело. (у меня также есть набор «adjustPan») - person DoruChidean; 26.01.2021

У меня была та же проблема, и я не хочу устанавливать для windowSoftInputMode значение «adjustResize». Вышеупомянутые ответы не работают для меня.

editText.clearFocused();
hideKeyboard();

// update your adapter ... 

parent.requestLayout();

Сбросьте фокус родительского макета, и recylerView будет обновлен правильно.

person Yuda    schedule 09.03.2020

Попробуйте это

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.scrollToPosition(yourPosition);
person SahdevRajput74    schedule 24.11.2017

У меня была та же проблема: когда открывается клавиатура, я прокручиваю recyclerView до последнего элемента в recyclerView, поэтому никакие элементы не будут скрыты. Я думаю, что это намного проще, чем то, что вы предлагаете. Таким образом, код будет следующим:

  recyclerView.postDelayed(new Runnable() {
            @Override
            public void run() {
                recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount() - 1);
            }
        }, 300);
person Sami Kanafani    schedule 24.11.2017
comment
Я уже сделал это. Я знаю, что это легко, но я не хочу этого. Мне нужно прокрутить вверх именно так, как он должен прокручиваться вверх. - person Ariful Hoque Maruf; 24.11.2017

Запишите это в свой манифест

    <activity
        android:name=".yourActivity"
        android:windowSoftInputMode="adjustResize" >
    </activity>
person SahdevRajput74    schedule 24.11.2017