Android 识别自定义视图上的三次点击
我想画一个圆圈,每当用户点击自定义视图时,根据点击次数,圆圈的颜色会发生变化Android 识别自定义视图上的三次点击,android,canvas,android-widget,touch-event,Android,Canvas,Android Widget,Touch Event,我想画一个圆圈,每当用户点击自定义视图时,根据点击次数,圆圈的颜色会发生变化 Single Tap : YELLOW CIRCLE Double Tap : GREEN CIRCLE Triple Tap : RED COLOR 问题是,我创建了一个自定义视图,它将根据时间统计点击事件,但有时它会错过第一次点击。这导致了问题的出现 下面的代码显示了我为创建上述自定义视图所做的所有努力 TripleTapView package com.slk.car_rating_app; import j
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();
}
}
}
package com.slk.car\u rating\u应用程序;
导入java.util.ArrayList;
导入java.util.Date;
导入android.annotation.SuppressLint;
导入android.content.Context;
导入android.graphics.Canvas;
导入android.graphics.Color;
导入android.graphics.Paint;
导入android.graphics.PointF;
导入android.graphics.RectF;
导入android.os.CountDownTimer;
导入android.view.MotionEvent;
导入android.view.view;
公共类TripleTapView扩展了视图{
//以毫秒为单位设置点击延迟
受保护的静态最终长抽头最大延迟=500L;
//在边界内捕获攻丝的半径
最终静态整数半径=30;
//使用抽头计数存储所有点
public ArrayList point=new ArrayList();
//访问视图的上下文
语境;
油漆;
private long ThistTime=0,prevTime=0;
私有布尔值firstTap=true,doubleTap=false;;
浮动stopX、stopY、startX、startY;
RectF区域;
TapCounter TapCounter=新的TapCounter(TAP_MAX_DELAY,TAP_MAX_DELAY);
公共TripleTapView(上下文){
超级(上下文);
this.context=上下文;
油漆=新油漆();
油漆。设置颜色(颜色。绿色);
paint.setAntiAlias(真);
绘制。设置抖动(真);
绘制.设置样式(绘制.样式.填充);
绘制.设置行程连接(绘制.连接.圆形);
油漆固定行程盖(油漆固定行程盖圆形);
油漆。设置行程宽度(2);
}
@SuppressLint(“DrawAllocation”)
@凌驾
受保护的void onDraw(最终画布){
super.onDraw(帆布);
用于(自定义点温度:点){
//用于根据点击次数更改点击圆颜色
开关(点温度计数){
案例1:
油漆。设置颜色(颜色。黄色);
打破
案例2:
油漆。设置颜色(颜色。绿色);
打破
案例3:
油漆。设置颜色(颜色。红色);
打破
}
画布画圈(点x、点y、点10、油漆);
}
}
@凌驾
公共布尔onTouchEvent(运动事件){
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:
stopX=event.getX();
stopY=event.getY();
如果(第一次点击){
addFirstTap();
}else if(双击){
prevTime=这次;
ThistTime=新日期().getTime();
如果(这次>上次){
如果((ThistTime-prevTime)prevTime){
如果((ThistTime-prevTime)prevTime){
如果((ThistTime-prevTime)prevTime){
如果((thisTime-prevTime)这段代码可以满足您的需要。我简化了您的类
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();
}
}
}
import java.util.ArrayList;
导入android.content.Context;
导入android.graphics.Canvas;
导入android.graphics.Color;
导入android.graphics.Paint;
导入android.graphics.PointF;
导入android.graphics.RectF;
导入android.os.CountDownTimer;
导入android.view.MotionEvent;
导入android.view.view;
公共类TripleTapView扩展了视图{
//以毫秒为单位设置点击延迟
受保护的静态最终长抽头最大延迟=500L;
//在边界内捕获攻丝的半径
专用最终静态整数半径=30;
//使用抽头计数存储所有点
public ArrayList_points=new ArrayList();
语境(Context)语境;;
油漆;
TapCounter\u TapCounter=新的TapCounter(TAP\u MAX\u DELAY,TAP\u MAX\u DELAY);
公共TripleTapView(上下文){
超级(上下文);
_上下文=上下文;
_油漆=新油漆();
_paint.setAntiAlias(真);
_绘制。设置抖动(真);
_绘制.设置样式(绘制.样式.填充);
_绘制.设置行程连接(绘制.连接.圆形);
_油漆固定行程盖(油漆固定行程盖圆形);
_油漆。设置行程宽度(2);
}
@凌驾
受保护的void onDraw(最终画布){
super.onDraw(帆布);
用于(自定义点温度:_点){
//用于根据点击次数更改点击圆颜色
开关(点温度计数){
案例1:
_油漆。设置颜色(颜色。黄色);
打破
案例2:
_油漆。设置颜色(颜色。绿色);
打破
案例3:
_油漆。设置颜色(颜色。红色);
打破
}
画布绘制圆(点x、点y、点10、,
_油漆);
}
}
私人住宅区;
私有整数_lastTapCount=0;
@凌驾
公共布尔onTouchEvent(运动事件){
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:
_tapCounter.resetCounter();
float x=event.getX();
float y=event.getY();
如果(_lastTapArea!=null){
if(_lastTapArea.contains(x,y)){
如果(_lastTapCount<3){
_lastTapCount++;
}否则{
addPoint(_lastTapArea.centerX(),
_lastTapArea.centerY(),_lastTapCount);
_lastTapCount=1;
}
}否则{
添加点(_lastTapArea.centerX(),_lastTapArea.centerY(),
_最后计数);
_lastTapCount=1;
_lastTapArea=新的矩形(x-半径,y-半径,
x+半径,y+半径);