第一篇搞定了UI,这一篇来处理下事件,ANDROID WHEEL有响应onscroll和onfling事件,这个该如何处理?这里有几个小知识点:
1.ontouchevent中调用GestureDetector.onTouchEvent(event)这个方法作为返回值,所以调用顺序就是ontouchevent–>onscroll或者ontouchevent–>onfling。
2.View.post(Runnable)也是修改UI的一种方式。
好了,上代码。

public class Wheel extends View implements GestureDetector.OnGestureListener,IFlingRunnable.FlingRunnableView {    private int mTicksCount = 18;    private float mTicksSize = 7.0f;    private float mIndicatorX = 0;    private Bitmap mIndicator;    private Bitmap mTickBitmap;    private Shader mShader3;    private Matrix mDrawMatrix = new Matrix();    int mOriginalDeltaX = 0;    private Paint mPaint;    int mWidth, mHeight;    float mTickSpace = 30;    private Easing mTicksEasing = new Sine();    private GestureDetector mGestureDetector;    private boolean mToLeft;    private int mMaxX, mMinX;    private int mWheelSizeFactor = 2;    private IFlingRunnable mFlingRunnable;    private int mAnimationDuration = 200;    private boolean mIsFirstScroll;    private int mTouchSlop;//这个值是判断是否为scroll的一个阈值,一般为8dp    public Wheel(Context context) {        this(context, null);    }    public Wheel(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public Wheel(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context, attrs, defStyleAttr);    }    public void init(Context context, AttributeSet attrs, int defStyleAttr) {        Log.d("111", "wheel init");        //构造一个Runnable,VIEW.POST(Runnable)这个方法        mFlingRunnable = new Fling8Runnable( this, mAnimationDuration );        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Wheel, defStyleAttr, 0);        mTicksCount = a.getInteger(R.styleable.Wheel_ticks, 18);        mWheelSizeFactor = a.getInteger(R.styleable.Wheel_numRotations, 2);        a.recycle();        mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);        mGestureDetector = new GestureDetector(context, this);        mGestureDetector.setIsLongpressEnabled(false);        setFocusable(true);        setFocusableInTouchMode(true);        mTouchSlop = ViewConfiguration.get( context ).getScaledTouchSlop();    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        mWidth = right - left;        mHeight = bottom - top;        mTickSpace = (float) mWidth / mTicksCount;        mTicksSize = mWidth / mTicksCount / 4.0f;        mTicksSize = Math.min(Math.max(mTicksSize, 3.5f), 6.0f);        mIndicatorX = (float) mWidth / 2.0f;        mIndicator = makeBitmapIndicator((int) Math.ceil(mTicksSize), bottom - top);        mTickBitmap = makeTickerBitmap((int) Math.ceil(mTicksSize), bottom - top);        mShader3 = new BitmapShader(makeBitmap3(right - left, bottom - top), Shader.TileMode.CLAMP, Shader.TileMode.REPEAT);        mMaxX = mWidth * mWheelSizeFactor;        mMinX = -mMaxX;    }    private Bitmap makeBitmap3(int width, int height) {        Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);        Canvas c = new Canvas(bm);        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);        int colors[] = {0xdd000000, 0x00000000, 0x00000000, 0xdd000000};        float positions[] = {0f, 0.2f, 0.8f, 1f};        LinearGradient gradient = new LinearGradient(0, 0, width, 0, colors, positions, Shader.TileMode.REPEAT);        p.setShader(gradient);        p.setDither(true);        c.drawRect(0, 0, width, height, p);        return bm;    }    @Override    protected void onDraw(Canvas canvas) {        final int w = mWidth;        int total = mTicksCount;        float x2;        float scale, scale2;        mPaint.setShader(null);        for (int i = 0; i < total; i++) {            float x = (mOriginalDeltaX + (((float) i / total) * w));            if (x < 0) {                x = w - (-x % w);            } else {                x = x % w;            }            scale = (float) mTicksEasing.easeInOut(x, 0, 1.0, mWidth);            scale2 = (float) (Math.sin(Math.PI * (x / mWidth)));            mDrawMatrix.reset();            mDrawMatrix.setScale(scale2, 1);            mDrawMatrix.postTranslate((int) (scale * mWidth) - (mTicksSize / 2), 0);            canvas.drawBitmap(mTickBitmap, mDrawMatrix, mPaint);        }        float indicatorx = (mIndicatorX + mOriginalDeltaX);        if (indicatorx < 0) {            indicatorx = (mWidth * 2) - (-indicatorx % (mWidth * 2));        } else {            indicatorx = indicatorx % (mWidth * 2);        }        if (indicatorx > 0 && indicatorx < mWidth) {            x2 = (float) mTicksEasing.easeInOut(indicatorx, 0, mWidth, w);            scale2 = (float) (Math.sin(Math.PI * (indicatorx / mWidth)));            mDrawMatrix.reset();            mDrawMatrix.setScale(scale2, 1);            mDrawMatrix.postTranslate(x2 - (mTicksSize / 2), 0);            canvas.drawBitmap(mIndicator, mDrawMatrix, mPaint);        }        mPaint.setShader(mShader3);        canvas.drawPaint(mPaint);    }    private Bitmap makeTickerBitmap(int width, int height) {        float ellipse = width / 2;        Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);        Canvas c = new Canvas(bm);        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);        p.setDither(true);        p.setColor(0xFF888888);        float h = (float) height;        float y = (h + 10.0f) / 10.0f;        float y2 = y * 2.5f;        RectF rect = new RectF(0, y, width, height - y2);        c.drawRoundRect(rect, ellipse, ellipse, p);        p.setColor(0xFFFFFFFF);        rect = new RectF(0, y2, width, height - y);        c.drawRoundRect(rect, ellipse, ellipse, p);        p.setColor(0xFFCCCCCC);        rect = new RectF(0, y + 2, width, height - (y + 2));        c.drawRoundRect(rect, ellipse, ellipse, p);        return bm;    }    private Bitmap makeBitmapIndicator(int width, int height) {        float ellipse = width / 2;        float h = (float) height;        float y = (h + 10.0f) / 10.0f;        float y2 = y * 2.5f;        Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);        Canvas c = new Canvas(bm);        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);        p.setDither(true);        p.setColor(0xFF666666);        RectF rect = new RectF(0, y, width, height - y2);        c.drawRoundRect(rect, ellipse, ellipse, p);        p.setColor(0xFFFFFFFF);        rect = new RectF(0, y2, width, height - y);        c.drawRoundRect(rect, ellipse, ellipse, p);        rect = new RectF(0, y + 2, width, height - (y + 2));        int colors[] = {0xFF0076E7, 0xFF00BBFF, 0xFF0076E7};        float positions[] = {0f, 0.5f, 1f};        LinearGradient gradient = new LinearGradient(0, 0, width, 0, colors, positions, Shader.TileMode.REPEAT);        p.setShader(gradient);        c.drawRoundRect(rect, ellipse, ellipse, p);        return bm;    }    @Override    public boolean onTouchEvent(MotionEvent event) {        Log.d("111", "onTouchEvent");        return mGestureDetector.onTouchEvent(event);    }    @Override    public boolean onDown(MotionEvent e) {        //返回值为true        mIsFirstScroll = true;        return true;    }    @Override    public void onShowPress(MotionEvent e) {    }    @Override    public boolean onSingleTapUp(MotionEvent e) {        return false;    }    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        Log.d("111", "onScroll");        if ( mIsFirstScroll ) {            if ( distanceX > 0 )                distanceX -= mTouchSlop;            else                distanceX += mTouchSlop;        }        mIsFirstScroll = false;        float delta = -1 * distanceX;        mToLeft = delta < 0;        if (!mToLeft) {            if (mOriginalDeltaX + delta > mMaxX) {                delta /= (((float) mOriginalDeltaX + delta) - mMaxX) / 10;            }        } else {            if (mOriginalDeltaX + delta < mMinX) {                delta /= -(((float) mOriginalDeltaX + delta) - mMinX) / 10;            }        }        trackMotionScroll((int) (mOriginalDeltaX + delta));        return true;    }    @Override    public void onLongPress(MotionEvent e) {    }    @Override    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {        Log.d("111", "onFling");        boolean toleft = velocityX < 0;        if ( !toleft ) {            if ( mOriginalDeltaX > mMaxX ) {                mFlingRunnable.startUsingDistance( mOriginalDeltaX, mMaxX - mOriginalDeltaX );                return true;            }        } else {            if ( mOriginalDeltaX < mMinX ) {                mFlingRunnable.startUsingDistance( mOriginalDeltaX, mMinX - mOriginalDeltaX );                return true;            }        }        mFlingRunnable.startUsingVelocity( mOriginalDeltaX, (int) velocityX / 2 );        return true;    }    @Override    public void scrollIntoSlots() {    }    @Override    public void trackMotionScroll(int newX) {        mOriginalDeltaX = newX;        invalidate();    }    @Override    public int getMinX() {        return mMinX;    }    @Override    public int getMaxX() {        return mMaxX;    }}

下面是IFlingRunnable

package thepoor.com.testmywheel;abstract class IFlingRunnable implements Runnable {    public static interface FlingRunnableView {        boolean removeCallbacks(Runnable action);        boolean post(Runnable action);        void scrollIntoSlots();        void trackMotionScroll(int newX);        int getMinX();        int getMaxX();    }    protected int mLastFlingX;    protected boolean mShouldStopFling;    protected FlingRunnableView mParent;    protected int mAnimationDuration;    protected static final String LOG_TAG = "fling";    public IFlingRunnable(FlingRunnableView parent, int animationDuration ) {        mParent = parent;        mAnimationDuration = animationDuration;    }    public int getLastFlingX() {        return mLastFlingX;    }    protected void startCommon() {        mParent.removeCallbacks( this );    }    public void stop( boolean scrollIntoSlots ) {        mParent.removeCallbacks( this );        endFling( scrollIntoSlots );    }    public void startUsingDistance( int initialX, int distance ) {        if ( distance == 0 ) return;        startCommon();        mLastFlingX = initialX;        _startUsingDistance( mLastFlingX, distance );        mParent.post( this );    }    public void startUsingVelocity( int initialX, int initialVelocity ) {        if ( initialVelocity == 0 ) return;        startCommon();        mLastFlingX = initialX;        _startUsingVelocity( mLastFlingX, initialVelocity );        mParent.post( this );    }    protected void endFling( boolean scrollIntoSlots ) {        forceFinished( true );        mLastFlingX = 0;        if ( scrollIntoSlots ) {            mParent.scrollIntoSlots();        }    }    @Override    public void run() {        mShouldStopFling = false;        final boolean more = computeScrollOffset();        int x = getCurrX();        mParent.trackMotionScroll( x );        if ( more && !mShouldStopFling ) {            mLastFlingX = x;            mParent.post( this );        } else {            endFling( true );        }    }    public abstract boolean springBack( int startX, int startY, int minX, int maxX, int minY, int maxY );    protected abstract boolean computeScrollOffset();    protected abstract int getCurrX();    public abstract float getCurrVelocity();    protected abstract void forceFinished( boolean finished );    protected abstract void _startUsingVelocity( int initialX, int velocity );    protected abstract void _startUsingDistance( int initialX, int distance );    public abstract boolean isFinished();}

下面是Fling8Runnable

package thepoor.com.testmywheel;import android.view.View;import android.view.animation.DecelerateInterpolator;import android.widget.Scroller;class Fling8Runnable extends IFlingRunnable {    private Scroller mScroller;    public Fling8Runnable(FlingRunnableView parent, int animationDuration ) {        super( parent, animationDuration );        mScroller = new Scroller( ( (View) parent ).getContext(), new DecelerateInterpolator() );    }    @Override    public float getCurrVelocity() {        return mScroller.getCurrVelocity();    }    @Override    public boolean isFinished() {        return mScroller.isFinished();    }    @Override    protected void _startUsingVelocity( int initialX, int velocity ) {        mScroller.fling( initialX, 0, velocity, 0, mParent.getMinX(), mParent.getMaxX(), 0, Integer.MAX_VALUE );    }    @Override    protected void _startUsingDistance( int initialX, int distance ) {        mScroller.startScroll( initialX, 0, distance, 0, mAnimationDuration );    }    @Override    protected void forceFinished( boolean finished ) {        mScroller.forceFinished( finished );    }    @Override    protected boolean computeScrollOffset() {        return mScroller.computeScrollOffset();    }    @Override    protected int getCurrX() {        return mScroller.getCurrX();    }    @Override    public boolean springBack( int startX, int startY, int minX, int maxX, int minY, int maxY ) {        return false;    }}

更多相关文章

  1. Android(安卓)dispatchTouchEvent介绍
  2. android 自定义log打印
  3. 上官网学android之五(Managing the Activity Lifecycle)
  4. android:用getIdentifier()获取资源Id
  5. Android(安卓)Sensor Framework(狠详)
  6. Android(安卓)API之onLayout, onMeasure
  7. android 模拟按键事件
  8. DialogFragment 报错汇总
  9. Android(安卓)UI开发详解之ActionBar

随机推荐

  1. Android(安卓)弧形列表转盘的实现(二),列表
  2. android中的解析
  3. 【Touch&input 】处理控制器操作(16)
  4. Android(安卓)百度地图—反地理编码—获
  5. 一篇文章带你了解 Android的 JIT 、AOT、
  6. 一个Demo学完Android中所有的服务
  7. Android上如何让应用截获系统按键
  8. Android开发第1-2课:运行你的app
  9. android原生POST、httpClient4.X实现向PH
  10. 第三部分:Android(安卓)应用程序接口指南-