gesturedetector прокрутка

163
21 января 2020, 16:00

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

public void gestureDetector() {
    gestureDetector = new GestureDetector(new GestureDetector.GestureListener() {
        @Override
        public boolean touchDown(float x, float y, int pointer, int button) { //если палец на экране
            smoothScroll = false;
            return false;
        }
        @Override
        public boolean pan(float x, float y, float deltaX, float deltaY) {
            smoothScroll = true;
            //если позиция камеры не уходит за пределы, то мы продолжаем передавать -deltaY
            if (camera.position.y < HEIGHT/2 && deltaY < 0) { //если позиция камеры ушла за предел и скроллинг идет вниз, мы не даем ему идти дальше
                deltaY = 0;
                smoothScroll = false;
            } else if (camera.position.y > 2000 + HEIGHT/2 && deltaY > 0) { //если позиция камеры ушла за предел и скроллинг идет вверх, мы не даем ему идти дальше
                deltaY = 0;
                smoothScroll = false;
            }
            if (deltaY > 30f) deltaY = 30f; //ограничитель скорости прокрутки
            if (deltaY < -30f) deltaY = -30f; //ограничитель скорости прокрутки
            pan = deltaY; //передаем последующей прокрутке значение текущей скорости прокрутки
            camera.translate(0, deltaY); //ручное перемещение камеры
            camerast.translate(0, -deltaY);
            camera.update(); //обновление камеры
            camerast.update();
            return true;
        }
}

private void smoothScroll() {
    if (!gestureDetector.isPanning()) { //если он не перемещается
        if (smoothScroll) {
            if ((int) pan == 0) { //если скорость прокрутки примерно равна нулю, то останавливаем ее
                    pan = 0;
                    smoothScroll = false;
                }
            if (pan > 0) {
                pan = pan - Gdx.graphics.getDeltaTime() * 25;
            } else if (pan < 0) {
                pan = pan + Gdx.graphics.getDeltaTime() * 25;
            }
            if (camera.position.y < HEIGHT/2 && pan < 0) { //если позиция камеры ушла за предел и скроллинг идет вниз, мы не даем ему идти дальше
                pan = 0;
                smoothScroll = false;
            } else if (camera.position.y > 2000 + HEIGHT/2 && pan > 0) { //если позиция камеры ушла за предел и скроллинг идет вверх, мы не даем ему идти дальше
                pan = 0;
                smoothScroll = false;
            }
            camera.translate(0, pan); //перемещение камеры
            camerast.translate(0, -pan);
            camera.update(); //обновление камер
            camerast.update();
        }
    }
}
Answer 1

Не совсем понятен вопрос. Интересует что конкретно? Конкретных формул не смогу подсказать, но посоветую использовать SimpleGestureListener

private static class MoveListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onDown (MotionEvent motionEvent) {
            return true;
        }
        @Override
        public boolean onScroll (MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
              //двигаемся на вектор (v;v1)(если прокрутка только вертикальная, на (0;v1)). Без анимации
              return true
        }
        @Override
        public boolean onFling (MotionEvent p1, MotionEvent p2, final float v, final float v1) {
            //реагируем на "бросок". Нужно запустить анимацию, которая будет скролить с вектором скорости (v,v1), которая будет плавно уменьшаться
            return true;
        }
    }

При создании View создаем GestureDetector, который будет обрабатывать события

private GestureDetector move_gesture = new GestureDetector (getContext (), new MoveListener ());

и в onTochEvent обрабатываем события нашим GestureDetector

@Override
public boolean onTouchEvent (MotionEvent event) {
    return move_listener != null && move_gesture.onTouchEvent (event);
}

В onScroll просто перемещаем вью, этот метод вызывается 30-60 раз в секунду(каждый кадр), анимировать нет смысла.

В onFling создаем, например, ValueAnimator, который меняет значение от 1f до 0f и скролит вьюшку на вектор скорости, полученный в onFling, умноженный на значение аниматора. Меняя интерполятор аниматора будете менять инерцию броска. Еще стоит ограничить максимальный начальный вектор скорости, т.к. он может достигать огромных значений при долэной сноровке. Но это уже путем экспериментов установите

READ ALSO
Анимация появления текстового символа

Анимация появления текстового символа

У меня есть svg изображение буквы А которая составлена из трех элементов: двух параллелограммов и прямоугольника - перекладины

267
Yii2 темизация. Как подставить только CSS?

Yii2 темизация. Как подставить только CSS?

Всем приветЕсть уже готовый проект

139
Сгруппировать элементы массива

Сгруппировать элементы массива

Имеется массив объектов

204
Создать конструктор объектов

Создать конструктор объектов

Снова прошу помощи у сообщества/*2

154