Xamarin Forms: почему ListView не может сохранить положение прокрутки при изменении вкладки

Я использую BottomNavigationBarXF, чтобы переопределить TabLayout по умолчанию для Android. Однако, как указано в заголовке, ListView не может сохранять положение прокрутки при смене табуляции. Когда пользователь переключается обратно с другой вкладки, ListView, кажется, обновляется/обновляется при касании, перемещая дисплей обратно в самое верхнее положение.

Что случилось? Из-за чего это может быть и как решить?

* Я сделал простую демонстрацию, чтобы проиллюстрировать проблему: https://ufile.io/t33g7


person Michael Yuwono    schedule 26.01.2018    source источник
comment
Вам удалось решить проблему?   -  person pfedotovsky    schedule 03.11.2019


Ответы (1)


Я предполагаю, что это связано с «кладбищем строк», всякий раз, когда вы используете представление списка, вы повторно используете набор строк, скажем, на устройстве видны 15 строк, Android продолжит отслеживать состояния эти 15 рядов. Всякий раз, когда вы прокручиваете, строка удаляется из очереди и вводится новая строка. Если вы затем прокручиваете обратно вверх, Android будет повторно использовать строку из кладбища строк, где он хранит строки, которые были видимыми, но больше не видны. Это делается для того, чтобы сохранить низкий уровень использования памяти и сократить время рендеринга, поэтому первая визуализация строки будет занимать больше времени, а последующие повторные рендеринг строки будут выполняться быстрее.

Это означает, что для отслеживания смещения прокрутки вам нужно будет проделать некоторую работу самостоятельно. Мой совет: используйте общий класс со статическими свойствами, которые отслеживают состояние пользовательского интерфейса. Затем, когда вы выполняете переключение вкладок, вы устанавливаете свойство, которое отслеживает абсолютную позицию y представления списка. Чтобы получить это значение, вам нужно знать, сколько элементов, которые были видимы ранее, больше не видны, умножьте это значение на ListItemHeight и добавьте headerHeight. В пользовательском представлении списка вы можете использовать FirstVisiblePosition, чтобы получить положение первого видимого элемента адаптера так

var pos = this.FirstVisiblePosition;
if(pos > 0)
{ 
   absoluteY += (pos - 1) * itemHeight + header‌​Height;
}

Где absoluteY - это смещение прокрутки списка, вы просто добавляете к нему, как я сделал здесь, если у вас нет itemHeight и headerHeight заранее, используйте FindViewById и получайте их высоты таким образом.

Надеюсь, это имеет смысл. Кстати, все это работает под Android Xamarin, поэтому вам нужно будет проделать некоторую работу, чтобы выяснить, как это переводится в формы (никогда не используемые формы)

person Trevor Hart    schedule 26.01.2018