Identificar triple toque en vista personalizada

Quiero dibujar círculo, siempre que el usuario toque en una vista personalizada, y basado en los cambios de color del círculo de contador de visitas.

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

El problema es que, he hecho una vista personalizada que contará el evento de toque basado en el tiempo, pero algún tiempo se pierda el primer toque. Que causan el problema en vista.

El siguiente código muestra todo mi esfuerzo para hacer una vista personalizada por encima.

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(); } } } 

Por favor ayúdame a solucionar este problema.

Este código hará lo que necesite. He simplificado tu clase.

 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(); } } } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.