Задать вопрос
OlegOleg1980
@OlegOleg1980
программист

Как правильно вычислить offset для вычисления полного смещения текущей позиции (position) от верха контейнера (RecyclerView)?

Есть RecyclerView с CardView в качестве элементов Item.

Хочу реализовать точное сохранение/восстановление позиции элементов Item на экране при событиях onAttach/onDestroy фрагмента с данным экраном.

Позицию первого полностью видимого элемента (position), а также точное смещение (offset) от верха родителя (RecyclerView) можно получить так:

// 
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mContext);

//
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);

// 
mListObjectsRV = (RecyclerView) objectsFragment.findViewById(R.id.objects_recycleview);

// 
mListObjectsRV.setLayoutManager(linearLayoutManager);

// 
mListObjectsRV.setHasFixedSize(true);

//
mListObjectsRV.addOnScrollListener(new RecyclerView.OnScrollListener() {

  /**
   *
   * @param recyclerView
   * @param dx
   * @param dy
   */
  @Override
  public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

    //
    super.onScrolled(recyclerView, dx, dy);

    //
    int position = ((LinearLayoutManager)recyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();

    //
    int offset = recyclerView.computeVerticalScrollOffset();
  }
});


Мы получаем position - позицию первого видимого элемента Item сверху экрана, и offset - полное смещение от верха родителя (RecyclerView) до самого первого элемента Item сверху экрана вне зависимости насколько он виден.

А вот как это смещение при восстановлении состояния фрагмента правильно указать?

Пробовал так:

//
linearLayoutManager.scrollToPositionWithOffset(position, 0);


Это работает для восстановления по позиции первого полностью видимого элемента, а если самый верхний Item виден не полностью, то он не будет первым, и, соответственно, экран восстановится уже без этой части неполностью видимого элемента. Чтобы восстановить положение экрана точно как было в момент сохранения, а именно по положению от верха родителя указанное в offset, нужно как-то вычислить высоту невидимой части самого верхнего элемента Item, и добавить эту высоту во второй параметр scrollToPositionWithOffset(), чтобы было вот так:

//
linearLayoutManager.scrollToPositionWithOffset(position, heightHiddenPartTopItem);


Тогда положение экрана восстановится по положению первого полностью видимого элемента Item с учетом смещения на высоту невидимой части самого верхнего неполностью видимого элемента Item.

Вот, собственно, и вопрос: как вычислить эту самоу высоту невидимой части элемента Item ?

Либо второй вариант: у нас есть точное положение offset от верха родителя, и его нужно как-то указать при восстановлении. Пробовал так:

//
//mListObjectsRV.scrollTo(0, offset);

//
//mListObjectsRV.scrollBy(0, offset);

//
//linearLayoutManager.scrollVerticallyBy(offset, n, null);


Ни один вариант не работает.

Вопрос: как это возможно сделать, и в каком месте должен быть расположен код?
  • Вопрос задан
  • 841 просмотр
Подписаться 1 Простой Комментировать
Решения вопроса 1
zagayevskiy
@zagayevskiy Куратор тега Java
Android developer at Yandex
Нужно всё это выкинуть и использовать LayoutManager.onSaveInstanceState/onRestoreInstanceState.

Сохранять надо в onSaveInstanceState фрагмента. Восстанавливать, например, в onViewCreated
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы