【问题标题】:Identify triple tap on custom view识别自定义视图上的三次点击
【发布时间】:2013-03-29 12:06:02
【问题描述】:

每当用户点击自定义视图时,我想绘制圆形,并根据点击计数圆形颜色变化。

Single Tap : YELLOW CIRCLE
Double Tap : GREEN CIRCLE
Triple Tap : RED COLOR

问题是,我制作了一个自定义视图,该视图将根据时间计算点击事件,但有时它会错过第一次点击。这导致了问题。

以下代码显示了我在自定义视图上所做的所有努力。

TripleTapView

package com.slk.car_rating_app;

import java.util.ArrayList;
import java.util.Date;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.CountDownTimer;
import android.view.MotionEvent;
import android.view.View;

public class TripleTapView extends View {
    // Set the tap delay in milliseconds
    protected static final long TAP_MAX_DELAY = 500L;
    // Radius to capture tap within bound
    final static int RADIUS = 30;
    // Store all points with tap count
    public ArrayList<CustomPoint> point = new ArrayList<CustomPoint>();
    // Context to access view
    Context context;
    Paint paint;
    private long thisTime = 0, prevTime = 0;
    private boolean firstTap = true, doubleTap = false;;
    float stopX, stopY, startX, startY;
    RectF area_rect;
    TapCounter tapCounter = new TapCounter(TAP_MAX_DELAY, TAP_MAX_DELAY);

    public TripleTapView(Context context) {
        super(context);
        this.context = context;
        paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(2);
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(final Canvas canvas) {
        super.onDraw(canvas);
        for (CustomPoint point_temp : point) {
            // For changing tap circle color based on tap count
            switch (point_temp.count) {
            case 1:
                paint.setColor(Color.YELLOW);
                break;
            case 2:
                paint.setColor(Color.GREEN);
                break;
            case 3:
                paint.setColor(Color.RED);
                break;
            }
            canvas.drawCircle(point_temp.point.x, point_temp.point.y, 10, paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            stopX = event.getX();
            stopY = event.getY();
            if (firstTap) {
                addFirstTap();
            } else if (doubleTap) {
                prevTime = thisTime;
                thisTime = new Date().getTime();
                if (thisTime > prevTime) {
                    if ((thisTime - prevTime) <= TAP_MAX_DELAY) {
                        if (area_rect.contains(stopX, stopY))
                            doubleTap = false;
                        else {
                            addPoint(1);
                            addFirstTap();
                        }
                    } else {
                        addPoint(1);
                        firstTap = true;
                    }
                } else {
                    firstTap = true;
                }
            } else {
                prevTime = thisTime;
                thisTime = new Date().getTime();
                if (thisTime > prevTime) {
                    if ((thisTime - prevTime) <= TAP_MAX_DELAY) {
                        if (area_rect.contains(stopX, stopY)) {
                            addPoint(3);
                            firstTap = true;
                        } else {
                            addPoint(2);
                            addFirstTap();
                        }
                    } else {
                        addPoint(2);
                        firstTap = true;
                    }
                } else {
                    firstTap = true;
                }
            }
        }
        return true;
    }

    void addPoint(int tapCount) {
        point.add(new CustomPoint(new PointF(startX, startY), tapCount));
        invalidate();
    }

    void addFirstTap() {
        thisTime = new Date().getTime();
        firstTap = false;
        doubleTap = true;
        startX = stopX;
        startY = stopY;
        area_rect = new RectF(stopX - RADIUS, stopY - RADIUS, stopX + RADIUS,
                stopY + RADIUS);
        tapCounter.resetCounter();
    }

    class TapCounter extends CountDownTimer {
        public TapCounter(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }

        @Override
        public void onFinish() {
            if (doubleTap) {
                prevTime = thisTime;
                thisTime = new Date().getTime();
                if (thisTime > prevTime) {
                    if ((thisTime - prevTime) <= TAP_MAX_DELAY) {
                        doubleTap = false;
                    } else {
                        addPoint(1);
                        firstTap = true;
                    }
                } else {
                    firstTap = true;
                }
            } else if (!firstTap && !doubleTap) {
                prevTime = thisTime;
                thisTime =  new Date().getTime();
                if (thisTime > prevTime) {
                    if ((thisTime - prevTime) <= TAP_MAX_DELAY) {
                        addPoint(2);
                        firstTap = true;
                    }
                } else {
                    firstTap = true;
                }
            }
        }

        @Override
        public void onTick(long millisUntilFinished) {
        }

        public void resetCounter() {
            start();
        }
    }
}

请帮我解决这个问题。

【问题讨论】:

    标签: android canvas android-widget touch-event


    【解决方案1】:

    此代码将满足您的需求。我简化了你的课程。

    import java.util.ArrayList;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.PointF;
    import android.graphics.RectF;
    import android.os.CountDownTimer;
    import android.view.MotionEvent;
    import android.view.View;
    
    public class TripleTapView extends View {
    
        // Set the tap delay in milliseconds
        protected static final long TAP_MAX_DELAY = 500L;
        // Radius to capture tap within bound
        private final static int RADIUS = 30;
        // Store all points with tap count
        public ArrayList<CustomPoint> _points = new ArrayList<CustomPoint>();
    
        Context _context;
        Paint _paint;
    
        TapCounter _tapCounter = new TapCounter(TAP_MAX_DELAY, TAP_MAX_DELAY);
    
        public TripleTapView(Context context) {
            super(context);
            _context = context;
    
            _paint = new Paint();
            _paint.setAntiAlias(true);
            _paint.setDither(true);
            _paint.setStyle(Paint.Style.FILL);
            _paint.setStrokeJoin(Paint.Join.ROUND);
            _paint.setStrokeCap(Paint.Cap.ROUND);
            _paint.setStrokeWidth(2);
        }
    
        @Override
        protected void onDraw(final Canvas canvas) {
            super.onDraw(canvas);
            for (CustomPoint point_temp : _points) {
                // For changing tap circle color based on tap count
                switch (point_temp.count) {
                case 1:
                    _paint.setColor(Color.YELLOW);
                    break;
                case 2:
                    _paint.setColor(Color.GREEN);
                    break;
                case 3:
                    _paint.setColor(Color.RED);
                    break;
                }
                canvas.drawCircle(point_temp.point.x, point_temp.point.y, 10,
                        _paint);
            }
        }
    
        private RectF _lastTapArea;
        private int _lastTapCount = 0;
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                _tapCounter.resetCounter();
                float x = event.getX();
                float y = event.getY();
    
                if (_lastTapArea != null) {
                    if (_lastTapArea.contains(x, y)) {
                        if (_lastTapCount < 3) {
                            _lastTapCount++;
                        } else {
                            addPoint(_lastTapArea.centerX(),
                                    _lastTapArea.centerY(), _lastTapCount);
                            _lastTapCount = 1;
                        }
                    } else {
                        addPoint(_lastTapArea.centerX(), _lastTapArea.centerY(),
                                _lastTapCount);
                        _lastTapCount = 1;
                        _lastTapArea = new RectF(x - RADIUS, y - RADIUS,
                                x + RADIUS, y + RADIUS);
                    }
                } else {
                    _lastTapCount = 1;
                    _lastTapArea = new RectF(x - RADIUS, y - RADIUS, x + RADIUS, y
                            + RADIUS);
                }
    
                return true;
            }
    
            return false;
        }
    
        void addPoint(float x, float y, int tapCount) {
            _points.add(new CustomPoint(new PointF(x, y), tapCount));
            invalidate();
        }
    
        class TapCounter extends CountDownTimer {
    
            public TapCounter(long millisInFuture, long countDownInterval) {
                super(millisInFuture, countDownInterval);
            }
    
            @Override
            public void onFinish() {
                if (_lastTapArea != null) {
                    if (_lastTapCount > 0)
                        addPoint(_lastTapArea.centerX(), _lastTapArea.centerY(),
                                _lastTapCount);
    
                    _lastTapCount = 0;
                    _lastTapArea = null;
                }
            }
    
            @Override
            public void onTick(long millisUntilFinished) {
            }
    
            public void resetCounter() {
                start();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多