Permalink
Browse files

Fixed scrolling issues. Moved the scrolling into a separate class.

git-svn-id: http://android-wheel.googlecode.com/svn/trunk@15 c364614a-9a97-51b3-f556-90fca60df64e
  • Loading branch information...
1 parent 4e66d79 commit 660587a3613b2413b6a1fd2f5533c5c60fd9de54 yuri.kanivets committed Jan 30, 2011
Showing with 336 additions and 172 deletions.
  1. +252 −0 wheel/src/kankan/wheel/widget/WheelScroller.java
  2. +84 −172 wheel/src/kankan/wheel/widget/WheelView.java
@@ -0,0 +1,252 @@
+/*
+ * Android Wheel Control.
+ * https://code.google.com/p/android-wheel/
+ *
+ * Copyright 2011 Yuri Kanivets
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package kankan.wheel.widget;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.animation.Interpolator;
+import android.widget.Scroller;
+
+/**
+ * Scroller class handles scrolling events and updates the
+ */
+public class WheelScroller {
+ /**
+ * Scrolling listener interface
+ */
+ public interface ScrollingListener {
+ /**
+ * Scrolling callback called when scrolling is performed.
+ * @param distance the distance to scroll
+ */
+ void onScroll(int distance);
+
+ /**
+ * Starting callback called when scrolling is started
+ */
+ void onStarted();
+
+ /**
+ * Finishing callback called after justifying
+ */
+ void onFinished();
+
+ /**
+ * Justifying callback called to justify a view when scrolling is ended
+ */
+ void onJustify();
+ }
+
+ /** Scrolling duration */
+ private static final int SCROLLING_DURATION = 400;
+
+ /** Minimum delta for scrolling */
+ public static final int MIN_DELTA_FOR_SCROLLING = 1;
+
+ // Listener
+ private ScrollingListener listener;
+
+ // Context
+ private Context context;
+
+ // Scrolling
+ private GestureDetector gestureDetector;
+ private Scroller scroller;
+ private int lastScrollY;
+ private float lastTouchedY;
+ private boolean isScrollingPerformed;
+
+ /**
+ * Constructor
+ * @param context the current context
+ * @param listener the scrolling listener
+ */
+ public WheelScroller(Context context, ScrollingListener listener) {
+ gestureDetector = new GestureDetector(context, gestureListener);
+ gestureDetector.setIsLongpressEnabled(false);
+
+ scroller = new Scroller(context);
+
+ this.listener = listener;
+ this.context = context;
+ }
+
+ /**
+ * Set the the specified scrolling interpolator
+ * @param interpolator the interpolator
+ */
+ public void setInterpolator(Interpolator interpolator) {
+ scroller.forceFinished(true);
+ scroller = new Scroller(context, interpolator);
+ }
+
+ /**
+ * Scroll the wheel
+ * @param distance the scrolling distance
+ * @param time the scrolling duration
+ */
+ public void scroll(int distance, int time) {
+ scroller.forceFinished(true);
+
+ lastScrollY = 0;
+
+ scroller.startScroll(0, 0, 0, distance, time != 0 ? time : SCROLLING_DURATION);
+ setNextMessage(MESSAGE_SCROLL);
+
+ startScrolling();
+ }
+
+ /**
+ * Stops scrolling
+ */
+ public void stopScrolling() {
+ scroller.forceFinished(true);
+ }
+
+ /**
+ * Handles Touch event
+ * @param event the motion event
+ * @return
+ */
+ public boolean onTouchEvent(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ lastTouchedY = event.getY();
+ scroller.forceFinished(true);
+ clearMessages();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ // perform scrolling
+ int distanceY = (int)(event.getY() - lastTouchedY);
+ if (distanceY != 0) {
+ startScrolling();
+ listener.onScroll(distanceY);
+ lastTouchedY = event.getY();
+ }
+ break;
+ }
+
+ if (!gestureDetector.onTouchEvent(event) && event.getAction() == MotionEvent.ACTION_UP) {
+ justify();
+ }
+
+ return true;
+ }
+
+ // gesture listener
+ private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ // Do scrolling in onTouchEvent() since onScroll() are not call immediately
+ // when user touch and move the wheel
+ return true;
+ }
+
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ lastScrollY = 0;
+ final int maxY = 0x7FFFFFFF;
+ final int minY = -maxY;
+ scroller.fling(0, lastScrollY, 0, (int) -velocityY, 0, 0, minY, maxY);
+ setNextMessage(MESSAGE_SCROLL);
+ return true;
+ }
+ };
+
+ // Messages
+ private final int MESSAGE_SCROLL = 0;
+ private final int MESSAGE_JUSTIFY = 1;
+
+ /**
+ * Set next message to queue. Clears queue before.
+ *
+ * @param message the message to set
+ */
+ private void setNextMessage(int message) {
+ clearMessages();
+ animationHandler.sendEmptyMessage(message);
+ }
+
+ /**
+ * Clears messages from queue
+ */
+ private void clearMessages() {
+ animationHandler.removeMessages(MESSAGE_SCROLL);
+ animationHandler.removeMessages(MESSAGE_JUSTIFY);
+ }
+
+ // animation handler
+ private Handler animationHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ scroller.computeScrollOffset();
+ int currY = scroller.getCurrY();
+ int delta = lastScrollY - currY;
+ lastScrollY = currY;
+ if (delta != 0) {
+ listener.onScroll(delta);
+ }
+
+ // scrolling is not finished when it comes to final Y
+ // so, finish it manually
+ if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) {
+ currY = scroller.getFinalY();
+ scroller.forceFinished(true);
+ }
+ if (!scroller.isFinished()) {
+ animationHandler.sendEmptyMessage(msg.what);
+ } else if (msg.what == MESSAGE_SCROLL) {
+ justify();
+ } else {
+ finishScrolling();
+ }
+ }
+ };
+
+ /**
+ * Justifies wheel
+ */
+ private void justify() {
+ listener.onJustify();
+ setNextMessage(MESSAGE_JUSTIFY);
+ }
+
+ /**
+ * Starts scrolling
+ */
+ private void startScrolling() {
+ if (!isScrollingPerformed) {
+ isScrollingPerformed = true;
+ listener.onStarted();
+ }
+ }
+
+ /**
+ * Finishes scrolling
+ */
+ void finishScrolling() {
+ if (isScrollingPerformed) {
+ listener.onFinished();
+ isScrollingPerformed = false;
+ }
+ }
+}
Oops, something went wrong. Retry.

0 comments on commit 660587a

Please sign in to comment.