Перейти к содержимому

Горизонтальный и вертикальный скролл в андроиде


  • Please log in to reply
Сообщений в теме: 7

#1
HotHeart

HotHeart

    .Ex3NDR//HotHeart

  • Forum Team
  • PipPipPip
  • 1 392 сообщений
  • Телефон: T-Mobile G1; Nook
Вводное слово
Наверное, каждый задавался себе вопросом - как же необходимо скроллить, что бы ощущения были такие же как в приложениях Maps и Browser. Самое удивительное, что нету доступного API для этого!Вот я хочу вам представить готовый рецепт, основанный на коде WebView.

Для этого будем использовать два класса - Scroller и VelocityTracker.

Обработка нажатий
Первое, что нам нужно сделать - начать считать скорость и сохранять её. Приведу сразу код:

//Экземпляр VelocityTracker 
//для подсчета скоростей
VelocityTracker mVelocityTracker;

//Переменные для сохранения координат, полученных при предыдущих
//вызовах onTouchEvent
int oldX = -1, oldY = -1;

//Переменные для смещения посчитанного
int dx = 0, dy = 0;

@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN: {
//Получаем новый экземпляр VelocityTracker.obtain()
//Я не пробовал получать иначе, но в исходниках
//было именно так. Скорее всего можно
//просто вызывать VelocityTracker.clear();
mVelocityTracker = VelocityTracker.obtain();

oldX = (int) ev.getX();
oldY = (int) ev.getY();
return true;
}
case MotionEvent.ACTION_MOVE: {
//Необходимо вызывать этот код в ACTION_MOVE, ACTION_UP и
//возможно еще в ACTION_DOWN
mVelocityTracker.addMovement(ev);

int deltaX = (int) (oldX - ev.getX());
int deltaY = (int) (oldY - ev.getY());

oldX = (int) ev.getX();
oldY = (int) ev.getY();

//Делаем скролл на нужное смещение.
//Этот метод только для ACTION_MOVE.
mScroller.startScroll(dx, dy, -deltaX, -deltaY);
return true;
}
case MotionEvent.ACTION_UP: {
mVelocityTracker.addMovement(ev);

//Считаем скорость. 1000 пикселей в секунду -
//средняя ожидаемая скорость.
//В сырцах было именно 1000 и я
//не стал менять это значение
mVelocityTracker.computeCurrentVelocity(1000);

//Получаем скорость текущую
int vx = (int) mVelocityTracker.getXVelocity();
int vy = (int) mVelocityTracker.getYVelocity();

//Перед этим кодом был следующий коммент:
//Сделаем это более похожим на карты.
//Там скорость обрезается в два раза.
vx = vx * 3 / 4;
vy = vy * 3 / 4;

//Специальный метод для скролла, когда мы отпустили палец
mScroller.fling(dx, dy, vx, vy, 0, 1500, 0, 1500);

//Уничтожаем наш VelocityTracker
mVelocityTracker.recycle();

return true;
}

}
return true;
}

Думаю, что из исходника все ясно)
Отрисовка с использованием смещений скролла
Теперь нам необходимо посчитать скролл и выводить что-то на экран. в моем случае - это просто картинка:
@Override
protected void onDraw(Canvas canvas) {
//Считаем скролл
mScroller.computeScrollOffset();

//Получаем координаты
dx = mScroller.getCurrX();
dy = mScroller.getCurrY();

//Выводим картинку
canvas.drawBitmap(bmp, dx, dy, new Paint());

//Повторяем цикл
invalidate();
}

В результате получили почти полноценный скролл:
Изображение

Оригинал
Мой блог об андроиде - http://stepa.name/

#2
pashtet

pashtet

    Активный участник

  • Пользователи
  • PipPipPip
  • 485 сообщений
  • Город:Москва
  • Телефон: G1
Занятно :)
Почти паштет. Ну не почти, но всё равно паштет.

#3
tum0rc0re

tum0rc0re

    Активный участник

  • Пользователи
  • PipPipPip
  • 3 221 сообщений
  • Город:Москва
  • Телефон: Galaxy Nexus, Motorola XOOM, G1, SE XPERIA X10
гы, интересно, а как ты картинкой показываешь скрол )) не понял :) картинка же двигаться наверно должна )) а она статична, ну та что в посте :blink: ааа, ну еще спасибо )) пригодится по-любому :)
[Samsung Galaxy Nexus user and developer] - 4.0.2,
[Motorola XOOM Wi-Fi user and developer] - 4.0.4,
[G1 developer] - 2.2 [CyanogenMod 6]
[SonyEricsson XPERIA X10 developer] - 2.3.3
[Nook Wi-Fi] - 1.5

Мой G+: https://plus.google....921729601/posts
Мои проекты - http://jqsoft.ru/, http://jqsoft.blogspot.com/, http://androidbook.wordpress.com/
Мой блог - http://maximyudin.blogspot.com/
Twitter - http://twitter.com/maxim_yudin
Facebook - http://www.facebook.com/maxim.yudin

#4
HotHeart

HotHeart

    .Ex3NDR//HotHeart

  • Forum Team
  • PipPipPip
  • 1 392 сообщений
  • Телефон: T-Mobile G1; Nook
Мне просто кот понравился)
Видео что ли мне делать на эту тему?)
Мой блог об андроиде - http://stepa.name/

#5
thevery

thevery

    Активный участник

  • Forum Team
  • PipPipPip
  • 5 792 сообщений
  • Город:Spb
  • Телефон: HTC Sensation и много других

canvas.drawBitmap(bmp, dx, dy, new Paint());


paint имхо лучше один раз статически проинициализировать, а не создавать каждый раз, да и числовые значения перенести в константы.

#6
HotHeart

HotHeart

    .Ex3NDR//HotHeart

  • Forum Team
  • PipPipPip
  • 1 392 сообщений
  • Телефон: T-Mobile G1; Nook
>>да и числовые значения перенести в константы.

В этой строчке не было константы в исходниках WebView:
mVelocityTracker.computeCurrentVelocity(1000);
и с этим я согласен - больше негде юзать этот метод.

3/4 гупо куда-то выносить, а максимальная ширина и высота - значения для тестов в реальном приложении все норм.
Мой блог об андроиде - http://stepa.name/

#7
neurobulka

neurobulka

    Новичок

  • Пользователи
  • Pip
  • 1 сообщений
класс, спасибо :)
только почему-то картинка доходит до левого-верхнего угла и дальше не скролится.
я так понимаю, что в методе onDraw() dx,dy всегда положительные, как это исправить?

#8
HotHeart

HotHeart

    .Ex3NDR//HotHeart

  • Forum Team
  • PipPipPip
  • 1 392 сообщений
  • Телефон: T-Mobile G1; Nook
Необходимо изменить ограничения в вызове метода:
mScroller.fling(dx, dy, vx, vy, MIN_X, MAX_X, MIN_Y, MAX_Y);


Ну вот как-то так)
Мой блог об андроиде - http://stepa.name/




Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных