Intereting Posts

Android: анимация скроллеров?

Я новичок в разработке Android, и я просто хотел бы немного узнать о виджетах Scroller (android.widget.Scroller). Как это оживить представление? Можно ли получить доступ к объекту Animation, если он существует? Если да, то как? Я прочитал исходный код, но не нашел подсказок, или, может быть, я слишком новичок?

Я просто хотел сделать некоторые операции после того, как Scroller завершит прокрутку, что-то вроде

m_scroller.getAnimation().setAnimationListener(...); 

Solutions Collecting From Web of "Android: анимация скроллеров?"

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

Итак, что хорошего? Ну, он делает все вычисления, например, для вас, что удобно. Итак, что вы обычно делаете, это создать Runnable, который неоднократно спрашивает Скроллер: «Какая должна быть моя позиция прокрутки? Затем вы отправляете то, что запускается на обработчике (обычно на представлении), пока не будет выполнено бросок.

Вот пример из фрагмента, над которым я сейчас работаю:

 private class Flinger implements Runnable { private final Scroller scroller; private int lastX = 0; Flinger() { scroller = new Scroller(getActivity()); } void start(int initialVelocity) { int initialX = scrollingView.getScrollX(); int maxX = Integer.MAX_VALUE; // or some appropriate max value in your code scroller.fling(initialX, 0, initialVelocity, 0, 0, maxX, 0, 10); Log.i(TAG, "starting fling at " + initialX + ", velocity is " + initialVelocity + ""); lastX = initialX; getView().post(this); } public void run() { if (scroller.isFinished()) { Log.i(TAG, "scroller is finished, done with fling"); return; } boolean more = scroller.computeScrollOffset(); int x = scroller.getCurrX(); int diff = lastX - x; if (diff != 0) { scrollingView.scrollBy(diff, 0); lastX = x; } if (more) { getView().post(this); } } boolean isFlinging() { return !scroller.isFinished(); } void forceFinished() { if (!scroller.isFinished()) { scroller.forceFinished(true); } } } 

Детали использования Scroller.startScroll должны быть похожими.

Мы можем расширить класс Scroller затем перехватить соответствующие методы запуска анимации, чтобы отметить, что был запущен, после того, как computeScrollOffset () вернет false, что означает значение завершенности анимации, мы сообщаем слушателю вызывающему:

 public class ScrollerImpl extends Scroller { ...Constructor... private boolean mIsStarted; private OnFinishListener mOnFinishListener; @Override public boolean computeScrollOffset() { boolean result = super.computeScrollOffset(); if (!result && mIsStarted) { try { // Don't let any exception impact the scroll animation. mOnFinishListener.onFinish(); } catch (Exception e) {} mIsStarted = false; } return result; } @Override public void startScroll(int startX, int startY, int dx, int dy) { super.startScroll(startX, startY, dx, dy); mIsStarted = true; } @Override public void startScroll(int startX, int startY, int dx, int dy, int duration) { super.startScroll(startX, startY, dx, dy, duration); mIsStarted = true; } @Override public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY) { super.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY); mIsStarted = true; } public void setOnFinishListener(OnFinishListener onFinishListener) { mOnFinishListener = onFinishListener; } public static interface OnFinishListener { void onFinish(); } } 

Как сказал Билл Филлипс, Scroller – это всего лишь класс Android SDK, который помогает вычислять позиции прокрутки. У меня есть полный рабочий пример здесь:

 public class SimpleScrollableView extends TextView { private Scroller mScrollEventChecker; private int mLastFlingY; private float mLastY; private float mDeltaY; public SimpleScrollableView(Context context) { this(context, null, 0); } public SimpleScrollableView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SimpleScrollableView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { if (mScrollEventChecker != null && !mScrollEventChecker.isFinished()) { return super.onTouchEvent(event); } final int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: mLastY = event.getY(); return true; case MotionEvent.ACTION_MOVE: int movingDelta = (int) (event.getY() - mLastY); mDeltaY += movingDelta; offsetTopAndBottom(movingDelta); invalidate(); return true; case MotionEvent.ACTION_UP: mScrollEventChecker = new Scroller(getContext()); mScrollEventChecker.startScroll(0, 0, 0, (int) -mDeltaY, 1000); post(new Runnable() { @Override public void run() { if (mScrollEventChecker.computeScrollOffset()) { int curY = mScrollEventChecker.getCurrY(); int delta = curY - mLastFlingY; offsetTopAndBottom(delta); // this is the method make this view move invalidate(); mLastFlingY = curY; post(this); } else { mLastFlingY = 0; mDeltaY = 0; } } }); return super.onTouchEvent(event); } return super.onTouchEvent(event); } } 

Приведенный выше демонстрационный вид будет прокручиваться назад до исходной позиции после того, как пользователь выпустит представление. Когда пользователь освобождает представление, запускается метод startScroll (), и мы можем знать, какое значение расстояния должно быть для каждого сообщения.

Полный рабочий пример: репозиторий Github

Большой ответ выше. Скроллер # startScroll (…) действительно работает одинаково.

Например, источник для пользовательской прокрутки TextView по адресу: http://bear-polka.blogspot.com/2009/01/scrolltextview-scrolling-textview-for.html

Устанавливает скроллер в TextView с помощью TextView # setScroller (скроллер).

Источник для TextView SDK по адресу: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/widget/TextView.java#TextView .0mScroller

Показывает, что TextView # setScroller (Scroller) устанавливает поле класса, которое используется в ситуациях, таких как bringPointIntoView (int), где вызывается Scroller # scrollTo (int, int, int, int).

Команда bringPointIntoView () настраивает mScrollX и mScrollY (с некоторым кодом фрагментации SDK), затем вызывает invalidate (). Суть всего в том, что mScrollX и mScrollY используются в таких методах, как onPreDraw (…), чтобы повлиять на позицию рисованного содержимого представления.