Android, как я могу получить текущий positon на recycliewiew, который пользователь прокрутил к элементу
в моем RecyclerView
у меня есть некоторые элементы, которые пользователь может прокручивать и видеть, что теперь я хочу сохранить эту позицию и прокрутить, что после этого, этот ниже код возвращает 0 всегда, и я не могу сохранить это
recyclerMarketLists.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
recyclerViewCurrentScrolledPosition = recyclerMarketLists.getScrollY();
Log.e("Y: ", recyclerViewCurrentSceolledPosition + "");
}
});
Logcat:
07-07 18:28:30.919 2124-2124/com.sample.presentationproject E/Y:: 0
Ответы
Ответ 1
Вы пытаетесь получить информацию о неправильном объекте. Это не RecyclerView
ни Adapter
ответственность, но RecyclerView LayoutManager.
Вместо универсального ViewTreeObserver.OnScrollChangedListener()
я бы рекомендовал добавить вместо него RecyclerView.OnScrollListener
и использовать onScrollStateChanged(RecyclerView recyclerView, int newState)
который дает вам newState
, для извлечения его позиции необходимо использовать SCROLL_STATE_IDLE
. Имея в виду:
yourRecyclerView.getLayoutManager().findFirstVisibleItemPosition();
Как отметил Рик ван Велзен, вам, вероятно, нужно привести ваш LayoutManager
к LinearLayoutManager
или GridLayoutManager
(вы должны привести к правильному типу, который вы используете), чтобы получить доступ к этим findVisibleXXXX()
.
По указанному методу обратного вызова. Надеюсь, я сделал это достаточно ясно для вас, вы можете найти документацию по классам здесь:
RecyclerView.OnScrollListener
yigit (Google) ответ на видимых позициях
Ответ 2
Спасибо за решение Joaquim Ley. Это помогает создавать horizontal
пейджер recyclerView
без использования какой-либо библиотеки.
Init recyclerView
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vocabulary_list);
// Set up the recyclerView with the sections adapter.
mRecyclerView = findViewById(R.id.list);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
mRecyclerView.setAdapter(new VocabularyListAdapter<>(vocabularyList));
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE){
int position = getCurrentItem();
onPageChanged(position);
}
}
});
PagerSnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(mRecyclerView);
}
public boolean hasPreview() {
return getCurrentItem() > 0;
}
public boolean hasNext() {
return mRecyclerView.getAdapter() != null &&
getCurrentItem() < (mRecyclerView.getAdapter().getItemCount()- 1);
}
public void preview() {
int position = getCurrentItem();
if (position > 0)
setCurrentItem(position -1, true);
}
public void next() {
RecyclerView.Adapter adapter = mRecyclerView.getAdapter();
if (adapter == null)
return;
int position = getCurrentItem();
int count = adapter.getItemCount();
if (position < (count -1))
setCurrentItem(position + 1, true);
}
private int getCurrentItem(){
return ((LinearLayoutManager)mRecyclerView.getLayoutManager())
.findFirstVisibleItemPosition();
}
private void setCurrentItem(int position, boolean smooth){
if (smooth)
mRecyclerView.smoothScrollToPosition(position);
else
mRecyclerView.scrollToPosition(position);
}
Ответ 3
Я сделал 7 изменений в MainActivity и получил идеальные по пикселям результаты. Мой просмотрщик ВСЕГДА запоминает свое предыдущее состояние при возврате к нему из какого-либо другого действия (например, DetailActivity).
Шаг 1: Инициализируйте layoutManager следующим образом:
// Initialize the layout manager
moviePosterLayoutManager = (moviePosterRecyclerView.getLayoutManager() == null) ?
new GridLayoutManager(this, numberOfColumns) : moviePosterRecyclerView.getLayoutManager();
// create a new layoutManager // reuse the existing layoutManager
Шаг 2: Внутри вашего класса MainActivity создайте переменную STATIC для хранения состояния вашего менеджера компоновки при переходе между действиями:
private static Parcelable layoutManagerState;
Шаг 3. Также создайте эту константу внутри MainActivity():
public static final String KEY_LAYOUT_MANAGER_STATE = "layoutManagerState";
Шаг 4. Внутри метода onCreate для MainActivity выполните следующий тест (т.е.
protected void onCreate(@Nullable final Bundle savedInstanceState) {....
if (layoutManagerState != null) {
//moviePosterLayoutManager
moviePosterLayoutManager.onRestoreInstanceState(layoutManagerState);
moviePosterRecyclerView.setLayoutManager(moviePosterLayoutManager);
} else {
moviePosterRecyclerView.setLayoutManager(moviePosterLayoutManager);
moviePosterRecyclerView.scrollToPosition(moviePosition);
// the default position
}
Шаг 5: В вашем методе onSaveInstanceState обязательно сохраните layoutManagerState как пригодный для распаковки следующий код:
protected void onSaveInstanceState (Bundle outState) {
layoutManagerState = moviePosterLayoutManager.onSaveInstanceState();
// Save currently selected layout manager.
outState.putParcelable(KEY_LAYOUT_MANAGER_STATE,layoutManagerState);
}
Шаг 6: Поместите подобный код в метод onResume() MainActivity:
protected void onResume() {
super.onResume();
if (layoutManagerState != null) {
moviePosterLayoutManager.onRestoreInstanceState(layoutManagerState);
}
}
Шаг 7: Помните, что весь этот код был помещен в мой файл MainActivity.java. Важно помнить, что layoutManager отвечает за поддержание позиции прокрутки представления рециркулятора. Таким образом, сохранение состояния layoutManager имеет первостепенное значение. Код может быть модульным и помещен в пользовательское представление переработчика, но я обнаружил, что это проще для меня реализовать.
Ответ 4
Для аналогичного требования плюс некоторые действия, которые необходимо выполнить при изменении состояния прокрутки, я сделал это с помощью специального прослушивателя прокрутки:
'class OnScrollListener (закрытое действие val:() → Unit): RecyclerView.OnScrollListener() {
private var actionExecuted: Boolean = false
private var oldScrollPosition: Int = 0
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
when (newState) {
RecyclerView.SCROLL_STATE_DRAGGING -> actionExecuted = false
RecyclerView.SCROLL_STATE_SETTLING -> actionExecuted = false
RecyclerView.SCROLL_STATE_IDLE -> {
val scrolledPosition =
(recyclerView.layoutManager as? LinearLayoutManager)?.findFirstVisibleItemPosition() ?: return
if (scrolledPosition != RecyclerView.NO_POSITION && scrolledPosition != oldScrollPosition && !actionExecuted) {
action.invoke()
actionExecuted = true
oldScrollPosition = scrolledPosition
}
}
}
}
} '
Это происходит из-за ранее существовавшей ошибки в RecyclerView onScroll, которая вызывает срабатывание обратного вызова 2-3 раза или даже больше. И если есть какое-то действие, которое будет выполнено несколько раз.