Подтвердить что ты не робот

Android: smoothScrollToPosition() работает неправильно

Я пытаюсь сгладить прокрутку до последнего элемента списка после добавления элемента в arrayadapter, связанный с listview. Проблема в том, что он просто прокручивается до произвольной позиции

arrayadapter.add(item);
//DOES NOT WORK CORRECTLY:
listview.smoothScrollToPosition(arrayadapter.getCount()-1);

//WORKS JUST FINE:
listview.setSelection(arrayadapter.getCount()-1);
4b9b3361

Ответ 1

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

Поэтому вы должны сделать что-то вроде:

    getListView().post(new Runnable() {
        @Override
        public void run() {
            getListView().smoothScrollToPosition(pos);
        }
    });

Ответ 2

(Скопировано из моего ответа: smoothScrollToPositionFromTop() не всегда работает так, как должно)

Это известная ошибка. См. https://code.google.com/p/android/issues/detail?id=36062

Однако я применил это обходное решение, которое касается всех случаев краев, которые могут возникнуть:

Сначала вызовите smothScrollToPositionFromTop(position), а затем, когда прокрутка завершена, вызовите setSelection(position). Последний вызов корректирует неполную прокрутку, перепрыгивая прямо в нужное положение. При этом у пользователя все еще создается впечатление, что он прокручивается в эту позицию.

Я реализовал это обходное решение в двух вспомогательных методах:

smoothScrollToPosition()

public static void smoothScrollToPosition(final AbsListView view, final int position) {
    View child = getChildAtPosition(view, position);
    // There no need to scroll if child is already at top or view is already scrolled to its end
    if ((child != null) && ((child.getTop() == 0) || ((child.getTop() > 0) && !view.canScrollVertically(1)))) {
        return;
    }

    view.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(final AbsListView view, final int scrollState) {
            if (scrollState == SCROLL_STATE_IDLE) {
                view.setOnScrollListener(null);

                // Fix for scrolling bug
                new Handler().post(new Runnable() {
                    @Override
                    public void run() {
                        view.setSelection(position);
                    }
                });
            }
        }

        @Override
        public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,
                                 final int totalItemCount) { }
    });

    // Perform scrolling to position
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            view.smoothScrollToPositionFromTop(position, 0);
        }
    });
}

getChildAtPosition()

public static View getChildAtPosition(final AdapterView view, final int position) {
    final int index = position - view.getFirstVisiblePosition();
    if ((index >= 0) && (index < view.getChildCount())) {
        return view.getChildAt(index);
    } else {
        return null;
    }
}

Ответ 3

Вам следует использовать метод setSelection().

Ответ 4

Метод выбора набора, упомянутый Ларсом, работает, но анимация была слишком нервной для наших целей, поскольку она пропускает все, что осталось. Другим решением является повторный вызов метода до тех пор, пока первая видимая позиция не станет вашим индексом. Это лучше всего сделать быстро и с лимитом, так как это будет бороться с прокруткой пользователя в противном случае.

private  void DeterminedScrollTo(Android.Widget.ListView listView, int index, int attempts = 0) {
    if (listView.FirstVisiblePosition != index && attempts < 10) {
        attempts++;
        listView.SmoothScrollToPositionFromTop (index, 1, 100);
        listView.PostDelayed (() => {
            DeterminedScrollTo (listView, index, attempts);
        }, 100);
    }
}

Решение находится в С# через. Xamarin, но должен легко перевестись на Java.

Ответ 5

Вы вызываете arrayadapter.notifyDataSetChanged() после вызова arrayadapter.add()? Также, конечно, smoothScrollToPosition и setSelection - это методы, доступные в ListView not arrayadapter, как вы уже упоминали выше.

В любом случае посмотрите, помогает ли это: smoothScrollToPosition после notifyDataSetChanged не работает в android

Ответ 6

final Handler handler = new Handler();
//100ms wait to scroll to item after applying changes
handler.postDelayed(new Runnable() {
@Override
public void run() {
   listView.smoothScrollToPosition(selectedPosition);
}}, 100);

Ответ 7

Используйте LayoutManager для плавной прокрутки

layoutManager.smoothScrollToPosition(recyclerView, new RecyclerView.State(), position);