/* * 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 com.keju.maomao.view.wheel.widget; import android.content.Context; import android.os.Handler; import android.os.Message; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; 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 public 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 maxY = 3; 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; } } }