Как предотвратить прокрутку списка при обновлении / обновлении / изменении dataProvider? - PullRequest
1 голос
/ 01 июля 2011

У меня есть простой список и протокол фонового обновления.

Когда список прокручивается вниз, обновление прокручивает его обратно вверх. Я хочу остановить это.

Я попытался перехватить событие COLLECTION_CHANGE и

validateNow();   //  try to get the component to reset to the new data

list.ensureIndexIsVisible(previousIndex);    //  actually, I search for the previous data id in the IList, but that's not important

Это невозможно, потому что список сбрасывает себя после изменения (в DataGroup.commitProperties).

Я ненавижу использовать Timer, ENTER_FRAME или callLater (), но, похоже, не могу найти способ.

Единственные другие альтернативы, которые я вижу, это подклассифицировать List, чтобы он мог перехватить событие dataProviderChanged, которое выбрасывает DataGroup в скине.

Есть идеи?

Ответы [ 4 ]

4 голосов
/ 03 января 2012

На самом деле гораздо лучшее решение для этого - расширить DataGroup. Вам нужно переопределить это.

Все решения, представленные здесь, создают мерцание, когда полоса прокрутки сбрасывается в 0 и возвращается к предыдущему значению. Это выглядит неправильно. Это решение работает без каких-либо мерцаний, и, что лучше всего, вы просто меняете DataGroup на FixedDataGroup в своем коде, и оно работает, никаких других изменений в коде не требуется;).

Наслаждайтесь, ребята.

public class FixedDataGroup extends spark.components.DataGroup
{
    private var _dataProviderChanged:Boolean;
    private var _lastScrollPosition:Number = 0;

    public function FixedDataGroup()
    {
        super();
    }

    override public function set dataProvider(value:IList):void
    {
        if ( this.dataProvider != null && value != this.dataProvider )
        {
            dataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE, onDataProviderChanged);
        }
        super.dataProvider = value;

        if ( value != null )
        {
            value.addEventListener(CollectionEvent.COLLECTION_CHANGE, onDataProviderChanged);
        }
    }

    override protected function commitProperties():void
    {
        var lastScrollPosition:Number = _lastScrollPosition;

        super.commitProperties();

        if ( _dataProviderChanged )
        {
            verticalScrollPosition = lastScrollPosition;
        }
    }

    private function onDataProviderChanged(e:CollectionEvent):void
    {
        _dataProviderChanged = true;
        invalidateProperties();
    }

    override public function set verticalScrollPosition(value:Number):void
    {
        super.verticalScrollPosition = value;
        _lastScrollPosition = value;
    }


}
2 голосов
/ 01 июля 2011

Я попытаюсь объяснить мой подход ... Если вы все еще не уверены, дайте мне знать, и я дам вам также исходный код.

1) Создайте переменную для хранения текущей позиции прокрутки области просмотра.2) Добавьте прослушиватель событий для Event.CHANGE и MouseEvent.MOUSE_WHEEL на скроллере и обновите переменную, созданную на шаге 1, текущей позицией прокрутки;3) Добавьте прослушиватель событий в свой видовой экран для FlexEvent.UpdateComplete и установите позицию прокрутки для сохраненной переменной.

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

2 голосов
/ 01 июля 2011

Я сталкивался с этой проблемой раньше и решил ее с помощью шаблона прокси-сервера данных с сопоставителем. Напишите средство сравнения для вашей коллекции, которое поддерживает ваш список, обновляя только измененные объекты и обновляя только атрибуты для существующих объектов. Цель состоит в том, чтобы избежать создания новых объектов при обновлении источника данных.

Если у вас есть новые данные для списка (после обновления), циклически просматривайте список новых объектов данных, копируя атрибуты из этих объектов в объекты в коллекции, поддерживающей ваш список. Обычно вы будете сопоставлять объекты на основе идентификатора. Любые объекты в новом списке, которые не существовали в старом, добавляются. Ваше положение прокрутки обычно не изменяется, и любые варианты выбора обычно сохраняются.

Вот пример.

for each(newObject:Object in newArrayValues){
  var found:Boolean = false;
  for each(oldObject:Object in oldArrayValues){
    if(oldObject.id == newObject.id){
      found = true;
      oldObject.myAttribute = newObject.myAttribute;
      oldObject.myAttribute2 = newObject.myAttribute2;
    }
  }
  if(!found){
    oldArrayValues.addItem(newObject);
  }
}
0 голосов
/ 01 июля 2011

Мое решение этой проблемы было нацелено на конкретную ситуацию, но у нее есть преимущество, заключающееся в том, что она очень проста, поэтому, возможно, вы сможете извлечь из нее то, что соответствует вашим потребностям. Так как я не знаю точно, какую проблему вы пытаетесь решить, я дам вам мое описание:

У меня был список, который постепенно загружал данные с сервера. Когда пользователь прокручивает страницу вниз и следующая группа элементов будет добавлена ​​в поставщик данных, положение прокрутки вернется к началу.

Решить эту проблему было так же просто, как остановить распространение события COLLECTION_CHANGE, чтобы List его не перехватил.

myDataProvider.addEventListener(
    CollectionEvent.COLLECTION_CHANGE, preventRefresh
);

private function preventRefresh(event:CollectionEvent):void {
    event.stopImmediatePropagation();
}

Вы должны знать, что это эффективно предотвращает перерисовку компонента List, поэтому любые добавленные элементы не будут отображаться. Это не было проблемой для меня, так как элементы будут добавлены в конец списка (вне области просмотра), и когда пользователь будет прокручивать, список будет автоматически перерисован, и новые элементы будут отображаться. Возможно, в вашей ситуации вы можете вызвать перерисовку в случае необходимости.

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

...