Stop scrollView в середине прокрутки

У меня есть scrollview с большим количеством контента. Теперь, когда пользователь выполняет сброс или прокрутку вниз, я хочу, чтобы scrollview останавливался в определенном месте просмотра, где я делаю анимацию, а затем пользователь может снова бежать или прокручивать вниз.

Я пробовал отключить scrollview, как упоминалось здесь, но он отключается только тогда, когда scrollview полностью останавливается и не может остановиться посередине броска.

Можно ли остановить остановку прокрутки, когда достигнуто определенное местоположение или определенное значение y?

Ответ 1

У меня была та же проблема, что и у моего решения.

listView.smoothScrollBy(0,0)

Это остановит прокрутку.

Ответ 2

Чтобы остановить бросок в определенной точке, просто позвоните

fling(0)

Если вы беспокоитесь только о бросках, это, по моему мнению, наиболее логичный способ сделать это, потому что velosityY установлена на 0, и поэтому бросок немедленно прекращается.

Вот Javadoc метода броска:

/**
 * Fling the scroll view
 *
 * @param velocityY The initial velocity in the Y direction. Positive
 *                  numbers mean that the finger/cursor is moving down the screen,
 *                  which means we want to scroll towards the top.
 */

Ответ 3

Один подход может заключаться в использовании smoothScrollToPosition, который останавливает любое существующее движение прокрутки. Обратите внимание, что для этого метода требуется уровень API >= 8 (Android 2.2, Froyo).

Обратите внимание, что если текущая позиция находится далеко от желаемой позиции, то гладкая прокрутка займет довольно много времени и выглядит немного рывкой (по крайней мере, в моем тестировании на Android 4.4 KitKat). Я также обнаружил, что комбинация вызова setSelection и smoothScrollToPosition иногда приводит к тому, что позиция "промахивается" немного, это, похоже, происходит только тогда, когда текущая позиция была очень близка к желаемой позиции.

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

Я использовал следующий метод для

private void smartScrollToPosition(ListView listView, int desiredPosition) {
    // If we are far away from the desired position, jump closer and then smooth scroll
    // Note: we implement this ourselves because smoothScrollToPositionFromTop
    // requires API 11, and it is slow and janky if the scroll distance is large,
    // and smoothScrollToPosition takes too long if the scroll distance is large.
    // Jumping close and scrolling the remaining distance gives a good compromise.
    int currentPosition = listView.getFirstVisiblePosition();
    int maxScrollDistance = 10;
    if (currentPosition - desiredPosition >= maxScrollDistance) {
        listView.setSelection(desiredPosition + maxScrollDistance);
    } else if (desiredPosition - currentPosition >= maxScrollDistance) {
        listView.setSelection(desiredPosition - maxScrollDistance);
    }
    listView.smoothScrollToPosition(desiredPosition); // requires API 8
}

В моем обработчике действий для кнопки я я назвал это следующим образом

    case R.id.action_go_to_today:
        ListView listView = (ListView) findViewById(R.id.lessonsListView);
        smartScrollToPosition(listView, 0); // scroll to top
        return true;

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

Ответ 4

Вам нужно отключить обработку ScrollView операции fling. Для этого просто переопределите метод fling в ScrollView и прокомментируйте super.fling(). Дайте мне знать, если это сработает!

public class CustomScrollView extends ScrollView {

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
    {
    return false;
    }

    @Override
    public void fling (int velocityY)
    {
    /*Scroll view is no longer gonna handle scroll velocity.
    * super.fling(velocityY);
     */
    }
 }

Ответ 5

Я пытаюсь добиться аналогичной ситуации. У меня есть частичное решение:

Мне удалось остановить ScrollView с определенной координатой y, переопределив onScrollChanged, а затем вызывая smoothScrollTo. Я разрешаю пользователю продолжать прокрутку вниз по этой точке, сохраняя логическое значение, указывающее, было ли это первым fling/drag или нет. То же самое касается прокрутки снизу вверх - я снова останавливаю свиток в той же точке. И затем разрешите пользователю продолжить прокрутку вверх снова.

Код выглядит примерно так:

boolean beenThereFromTop = false;
boolean beenThereFromBottom = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);

    scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {

        @Override
        public void onScrollChanged() {

            TextView whereToStop = (TextView) findViewById(R.id.whereToStop);
            final int y = whereToStop.getBottom();

            int scrollY = scrollView.getScrollY();

// manage scrolling from top to bottom

            if (scrollY > y) {
                if (!beenThereFromTop) {
                    beenThereFromTop = true;
                    scrollView.post(new Runnable() {
                        @Override
                        public void run() {
                            scrollView.smoothScrollTo(0, y);
                        }
                    });
                }
            }
            if (scrollY < y && beenThereFromTop) {
                beenThereFromTop = false;
            }

// manage scrolling from bottom to top

            if (scrollY < y) {
                if (!beenThereFromBottom) {
                    beenThereFromBottom = true;
                    scrollView.post(new Runnable() {
                        @Override
                        public void run() {
                            scrollView.smoothScrollTo(0, y);
                        }
                    });
                }
            }
            if (scrollY > y && beenThereFromBottom) {
                beenThereFromBottom = false;
            }
        }
    });
}

Ответ 6

Ну, действительно, используя этот метод:

 list.post(new Runnable() 
                        {
                            @Override
                            public void run() 
                            {
                               list.smoothScrollToPositionFromTop(arg2, 150); 
                            }
                        });