Я создал чат и, как мессенджер facebook, внизу есть EditText, а выше - RecyclerView сообщений. Когда открывается клавиатура, я хочу прокрутить RecyclerView ровно настолько, насколько он должен прокручиваться вверх. Чтобы быть более конкретным, давайте предположим, что в RecyclerView есть 5 сообщений, и в настоящее время 3-е сообщение находится чуть выше EditText. Поэтому, когда клавиатура открыта, я хочу оставить третье сообщение чуть выше EditText, как и раньше. Я искал, но не смог найти. Если это дублирующий вопрос, я буду признателен, если кто-нибудь может предоставить ссылку.
Прокрутите RecyclerView вверх соответственно при открытии клавиатуры
Ответы (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
Это работа для меня.
Поздний ответ, но, возможно, кто-то найдет его полезным.
Если это приложение для чата, я полагаю, вы хотите начать строить список снизу. Например, есть пустой чат, и после того, как вы добавите пару сообщений, вы ожидаете, что они окажутся внизу списка. Позже, по мере того как сообщений будет становиться все больше и больше, старые сообщения будут подниматься вверх, а новые будут внизу, прямо над EditText
.
Предполагая, что самые новые сообщения находятся первыми в вашем списке/массиве, вы можете просто установить LinearLayoutManager
в обратном порядке.
layoutManager.reverseLayout = true
Я не могу объяснить, почему, но похоже, что RecyclerView
всегда пытается сохранить положение прокрутки верхней границы. Поэтому, когда отображается клавиатура, доступное вертикальное пространство сжимается, и RecyclerView
просто пытается сохранить свою верхнюю часть такой же, как и раньше. Сделав его обратным макетом, вы можете добиться желаемого поведения.
Я искал правильное решение, и я нашел его, я думаю.
Когда вы размещаете свой 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 дочерних представлений, иначе он не будет работать должным образом.)
У меня была та же проблема, и я не хочу устанавливать для windowSoftInputMode значение «adjustResize». Вышеупомянутые ответы не работают для меня.
editText.clearFocused();
hideKeyboard();
// update your adapter ...
parent.requestLayout();
Сбросьте фокус родительского макета, и recylerView будет обновлен правильно.
Попробуйте это
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.scrollToPosition(yourPosition);
У меня была та же проблема: когда открывается клавиатура, я прокручиваю recyclerView до последнего элемента в recyclerView, поэтому никакие элементы не будут скрыты. Я думаю, что это намного проще, чем то, что вы предлагаете. Таким образом, код будет следующим:
recyclerView.postDelayed(new Runnable() {
@Override
public void run() {
recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount() - 1);
}
}, 300);
Запишите это в свой манифест
<activity
android:name=".yourActivity"
android:windowSoftInputMode="adjustResize" >
</activity>