2012-07-04 2 views
5

В Gingerbread у меня не было проблем с использованием функции smoothScrollToPosition() для прокрутки по десяткам предметов за раз. После того как мой Nexus S был обновлен до Ice Cream Sandwich, я заметил, что независимо от того, что я ввел в smoothScrollToPosition(), он будет прокручивать всего пару сотен пикселей в любом направлении, а затем останавливаться.smoothScrollToPosition() только прокручивает часть в Android ICS?

Это известная проблема с ICS? Я заметил это с Galaxy Nexus. Я просмотрел несколько других вопросов и попробовал несколько различных трюков, например, отключить вызовы notifyDataSetChanged() и опубликовать smoothScrollToPosition() как задержанную runnable, но, к сожалению, он не хочет прокручивать больше, чем сто пикселей или около того до остановки. :(

+2

У меня такая же проблема. http://code.google.com/p/android/issues/detail?id=37278 – bigstones

+1

Я разместил там обходной путь. – bigstones

+0

Кажется, что исправлено в Jellybean. –

ответ

12

Появляется проблема с продолжительностью, необходимой для завершения анимации, эта же проблема присутствует с smoothScrollBy (int distance, int duration), при беглом взгляде smoothScrollToPosition() - дружественная оболочка вокруг smoothScrollBy() который делает много работы. smoothScrollBy(), в свою очередь, притворяется «бегущим жестом», как если бы пользователь совершил движение.

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

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

В любом случае это не поможет вам решить эту проблему, но кто-то, возможно, это интересно :)

Если вы знаете, что статические высоты ячейки, однако, вы можете написать свой собственный метод для вычисления расстояния и продолжительности, чтобы пройти для smoothScrollBy() самостоятельно и иметь статическое количество времени для перемещения расстояния X. Если вы этого не сделаете, достаточно будет использовать широко распространенное решение bigstones, которое действительно работает из-за высокого SCROLL_DURATION в 1000 мс. Вы можете взять версию ICS и изменить этот атрибут, а не использовать версию 2.2, которая не является основной причиной.

Вы также можете адаптировать эти runnables своим собственным алгоритмом, это не должно быть слишком сложно подстроить.

0

Поскольку ListView использует метод getChildCount(), чтобы получить счет позиции в исходном коде AbsListView.java. но в ListView метод getChildCount() не может правильно подсчитать. Возможно, вам следует использовать метод setSelection().

2

Это то, что я сделал для решения проблемы. По сути, мы хотим продолжать называть smoothscrolling, пока вы не достигнете нужного элемента (в этом случае я просто хочу прокрутить вверх, что является элементом 0).

//There is a known bug where smoothScrollToPosition(..) may not reach the top, 
      //if the list is very large, keep scrolling until you reach the top element 
      newsFeed.setOnScrollListener(new OnScrollListener() { 
       @Override 
       public void onScrollStateChanged(AbsListView view, int scrollState) { 

       } 

       @Override 
       public void onScroll(AbsListView view, int firstVisibleItem, 
         int visibleItemCount, int totalItemCount) { 
        if(firstVisibleItem != 0) { 
         newsFeed.smoothScrollToPosition(0); 
        } 
        else { 
         //We are done 
         newsFeed.setOnScrollListener(null); 
        } 
       } 
      }); 
      newsFeed.smoothScrollToPosition(0); 
0

У меня проблема с ICS.

У меня есть активность списка сообщений чата, каждый раз после отправки сообщения мне нужно прокручивать список вниз до нуля. Поэтому после того, как я вызвал notifyDataSetChanged(), я назвал метод smoothScrollToPosition(). В других версиях сборки для Android он работает хорошо. Но на ICS это очень странно. Если мой список внизу, я протестировал 3 случая.если я добавлю один новый элемент в список, он не будет прокручиваться. Если я добавлю два новых элемента в список -> он будет прокручиваться хорошо. И если я прокручу список в несколько пикселей, после добавления одного нового элемента, он будет хорошо прокручиваться. После многих поисков и тестов Google я чувствую беспомощность по этому поводу. Наконец, каждый раз, когда я устанавливаю данные в listview, я добавляю пустое представление (1px) в последнюю позицию, хотя это не очень хороший метод, но он работает для меня.

2

Если ваша цель - прокрутить вверх, рассмотрите возможность использования smoothScrollToPositionFromTop(0,0). вместо.