所谓的TP测试,就是测试TP有没有问题,一般都是通过划线来检验。很多公司用的都是类似于下面的,在方格上面移动手指,方格变成色,说明这个地方的TP没有问题。
但是存在这样的问题,当手指移动速度过快时,有些方格没有变颜色,这给工厂生产测试时带来了一定的麻烦,因为他们测试的速度比较快,又要去重新划线,浪费时间。
我研究了一下这部分的源码,发现主要原因是View的onTouchEvent响应速度不够快。onTouchEvent要隔一段时间才会响应一次,如果滑的速度太快,就可能出现上一个方格的还没来及判断,就判断下一个了。这样说可能比较模糊,我把源码贴出来。
public class SimpleView6 extends View{
private int mov_x;//声明起点坐标
private int mov_y;
private float down_x;
private float down_y;
private float up_x;
private float up_y;
private Paint paintRed;//声明画笔
private Paint paint;
private int crossCount = 11;
private int verticalCount = 15;
private float gap = 2.0f;
float rectWidth;
float rectHeight;
int totalCount;
Context mContext;
boolean[] states;
private Canvas canvas;//画布
private Bitmap bitmap;//位图
private int blcolor;
public SimpleView6(Context context) {
super(context);
bitmap = Bitmap.createBitmap(LCM_WIDTH, LCM_HEIGHT, Bitmap.Config.ARGB_8888); //设置位图的宽高
paintRed=new Paint(Paint.DITHER_FLAG);//创建一个画笔
canvas=new Canvas();
canvas.setBitmap(bitmap);
mContext = context;
paintRed.setStyle(Paint.Style.STROKE);//设置非填充
paintRed.setStrokeWidth(5);//笔宽5像素
paintRed.setColor(Color.RED);//设置为红笔
paintRed.setAntiAlias(true);//锯齿不显示
paint = new Paint();
paint.setStyle(Paint.Style.FILL);//设置非填充
paint.setStrokeWidth(1);//笔宽5像素
paint.setColor(Color.GRAY);//设置为红笔
paint.setAntiAlias(true);//锯齿不显示
rectWidth = (LCM_WIDTH-(crossCount+1)*gap)/crossCount;
rectHeight = (LCM_HEIGHT-(verticalCount+1)*gap)/(verticalCount+2);
totalCount = crossCount*3+verticalCount*3-3+(crossCount-3)*2;
Log.e("lqh","rectWidth="+rectWidth+" verticalCount="+verticalCount+" totalCount="+totalCount);
states = new boolean[totalCount];
for(int i=0; i gap && event.getY() < rectHeight+gap){
for(int i=0; i < crossCount;i++){
if(event.getX()>gap+i*(rectWidth+gap) && event.getX()<(i+1)*(rectWidth+gap)){
states[i]=true;
break;
}
}
}
if(event.getX() > gap && event.getX() < rectWidth+gap
&& event.getY() > gap+rectHeight && event.getY() < LCM_HEIGHT-(gap+rectHeight)){
for(int i=0; i < verticalCount;i++){
if(event.getY()>(gap+rectHeight)+gap+i*(rectHeight+gap) && event.getY()<(gap+rectHeight)+(i+1)*(rectHeight+gap)){
states[i+crossCount]=true;
break;
}
}
}
if(event.getX() > crossCount/2*(gap+rectWidth)+gap
&& event.getX() < crossCount/2*(gap+rectWidth)+rectWidth+gap
&& event.getY() > gap+rectHeight && event.getY()< LCM_HEIGHT-(gap+rectHeight)){
for(int i=0; i < verticalCount;i++){
if(event.getY()>(gap+rectHeight)+gap+i*(rectHeight+gap) && event.getY()<(gap+rectHeight)+(i+1)*(rectHeight+gap)){
states[i+crossCount+verticalCount]=true;
break;
}
}
}
if(event.getX() > (crossCount-1)*(gap+rectWidth)+gap
&& event.getX() < (crossCount-1)*(gap+rectWidth)+rectWidth+gap
&& event.getY() > gap+rectHeight && event.getY()< LCM_HEIGHT-(gap+rectHeight)){
for(int i=0; i < verticalCount;i++){
if(event.getY()>(gap+rectHeight)+gap+i*(rectHeight+gap) && event.getY()<(gap+rectHeight)+(i+1)*(rectHeight+gap)){
states[i+crossCount+verticalCount*2]=true;
break;
}
}
}
if(event.getY() > (verticalCount/2+1)*(rectHeight+gap)+gap
&& event.getY() < (verticalCount/2+1)*(rectHeight+gap)+rectHeight+gap
&& event.getX()>gap+rectWidth && event.getX()< crossCount/2*(gap+rectWidth)){
for(int i=0; i < crossCount/2-1;i++){
if(event.getX()>rectWidth+gap+gap+i*(rectWidth+gap) && event.getX() (verticalCount/2+1)*(rectHeight+gap)+gap
&& event.getY() < (verticalCount/2+1)*(rectHeight+gap)+rectHeight+gap
&& event.getX()>(crossCount/2+1)*(gap+rectWidth) && event.getX()< LCM_WIDTH-(gap+rectWidth)){
for(int i=0; i < crossCount/2-1;i++){
if(event.getX()>(crossCount/2+1)*(rectWidth+gap)+gap+i*(rectWidth+gap)
&& event.getX()<(crossCount/2+1)*(rectWidth+gap)+(i+1)*(rectWidth+gap)){
states[i+crossCount+verticalCount*3+crossCount/2-1]=true;
break;
}
}
}
if(event.getY() > LCM_HEIGHT-(gap+rectHeight) && event.getY() < LCM_HEIGHT){
for(int i=0; i < crossCount;i++){
if(event.getX()>gap+i*(rectWidth+gap) && event.getX()<(i+1)*(rectWidth+gap)){
states[i+crossCount+verticalCount*3+crossCount/2-1+crossCount/2-1]=true;
break;
}
}
}
if(event.getY() > ((verticalCount+2)/4)*(rectHeight+gap)+gap
&& event.getY() < ((verticalCount+2)/4)*(rectHeight+gap)+rectHeight+gap
&& event.getX()>gap+rectWidth && event.getX()< crossCount/2*(gap+rectWidth)){
for(int i=0; i < crossCount/2-1;i++){
if(event.getX()>rectWidth+gap+gap+i*(rectWidth+gap) && event.getX() ((verticalCount+2)/4)*(rectHeight+gap)+gap
&& event.getY() < ((verticalCount+2)/4)*(rectHeight+gap)+rectHeight+gap
&& event.getX()>(crossCount/2+1)*(gap+rectWidth) && event.getX()< LCM_WIDTH-(gap+rectWidth)){
for(int i=0; i < crossCount/2-1;i++){
if(event.getX()>(crossCount/2+1)*(rectWidth+gap)+gap+i*(rectWidth+gap)
&& event.getX()<(crossCount/2+1)*(rectWidth+gap)+(i+1)*(rectWidth+gap)){
states[i+crossCount+verticalCount*3+crossCount/2-1+crossCount/2-1+crossCount+(crossCount-3)/2]=true;
break;
}
}
}
if(event.getY() > ((verticalCount+2)/4*3)*(rectHeight+gap)+gap
&& event.getY() < ((verticalCount+2)/4*3)*(rectHeight+gap)+rectHeight+gap
&& event.getX()>gap+rectWidth && event.getX()< crossCount/2*(gap+rectWidth)){
for(int i=0; i < crossCount/2-1;i++){
if(event.getX()>rectWidth+gap+gap+i*(rectWidth+gap) && event.getX() ((verticalCount+2)/4*3)*(rectHeight+gap)+gap
&& event.getY() < ((verticalCount+2)/4*3)*(rectHeight+gap)+rectHeight+gap
&& event.getX()>(crossCount/2+1)*(gap+rectWidth) && event.getX()< LCM_WIDTH-(gap+rectWidth)){
for(int i=0; i < crossCount/2-1;i++){
if(event.getX()>(crossCount/2+1)*(rectWidth+gap)+gap+i*(rectWidth+gap)
&& event.getX()<(crossCount/2+1)*(rectWidth+gap)+(i+1)*(rectWidth+gap)){
states[i+crossCount+verticalCount*3+crossCount/2-1+crossCount/2-1+crossCount+(crossCount-3)/2+(crossCount-3)/2+(crossCount-3)/2]=true;
break;
}
}
}
boolean isAllTure = true;
for(int i=0; i
所有方格的状态都保存在states这个数组里面,并且按照一定的规律保存。onDraw的时候会判断每个方格的状态,然后绘制。states数组里面的成员,默认都为false,在onTouchEvent的时候让它变成true,可以多看几遍代码就明白了。那么就会出现我上面说的问题,有没有什么方法解决这个问题?我试了很多种办法,最后发现更新了算法。。。
通过线与面是否相交来判断,在onTouchEvent触发的时候当前的点与上一个点连成一条线,这条线与所有的方格进行相交的判断,这样不管滑的多快都不会出现问题。只要这条线经过了这个点,就判定为true,下面来说具体的实现。
首先在初始化的时候把每个方格的坐标有保存在一个ArrayList里面。
ArrayList arrayList =new ArrayList();
PointInfo是每个方格点信息,只要保存左上角和右下角两个点的坐标,就可以确定一个方格的位置。
class PointInfo {
float x1;
float y1;
float x2;
float y2;
public PointInfo(float x1, float y1, float x2, float y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
}
在构造函数里面把所有的方格都保存起来
public SimpleView6(Context context) {
....
for(int i = 0; i < totalCount; i++){
if(i
在onTouchEvent的MotionEvent.ACTION_MOVE时候进行判断的
for (int i = 0; i < totalCount; i++) {
if(isLineIntersectRectangle(mov_x,mov_y,(int)event.getX(),(int)event.getY(),(int)arrayList.get(i).x1,(int)arrayList.get(i).y1,(int)arrayList.get(i).x2,(int)arrayList.get(i).y2)){
Log.d(TAG, "isLineIntersectRectangle: i "+i);
if (!states[i]) {
states[i]= true;
}
}
}
这里最为核心的就是isLineIntersectRectangle这个函数,判断线是否经过了面
/**
* 判断线段是否在矩形内
*
* 先看线段所在直线是否与矩形相交,
* 如果不相交则返回false,
* 如果相交,
* 则看线段的两个点是否在矩形的同一边(即两点的x(y)坐标都比矩形的小x(y)坐标小,或者大),
* 若在同一边则返回false,
* 否则就是相交的情况。
*
*
* @param linePointX1 线段起始点x坐标
* @param linePointY1 线段起始点y坐标
* @param linePointX2 线段结束点x坐标
* @param linePointY2 线段结束点y坐标
* @param rectangleLeftTopX 矩形左上点x坐标
* @param rectangleLeftTopY 矩形左上点y坐标
* @param rectangleRightBottomX 矩形右下点x坐标
* @param rectangleRightBottomY 矩形右下点y坐标
* @return 是否相交
*/
private boolean isLineIntersectRectangle(int linePointX1,int linePointY1,int linePointX2,int linePointY2,int rectangleLeftTopX,int rectangleLeftTopY,int rectangleRightBottomX,int rectangleRightBottomY) {
int lineHeight = linePointY1 - linePointY2;
int lineWidth = linePointX2 - linePointX1;
// 计算叉乘
int c = linePointX1 * linePointY2 - linePointX2 * linePointY1;
if ((lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c <= 0)
|| (lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c >= 0)
|| (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c <= 0)
|| (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c >= 0)) {
if (rectangleLeftTopX > rectangleRightBottomX) {
int temp = rectangleLeftTopX;
rectangleLeftTopX = rectangleRightBottomX;
rectangleRightBottomX = temp;
}
if (rectangleLeftTopY < rectangleRightBottomY) {
int temp = rectangleLeftTopY;
rectangleLeftTopY = rectangleRightBottomY;
rectangleRightBottomY = temp;
}
if ((linePointX1 < rectangleLeftTopX && linePointX2 < rectangleLeftTopX)
|| (linePointX1 > rectangleRightBottomX && linePointX2 > rectangleRightBottomX)
|| (linePointY1 > rectangleLeftTopY && linePointY2 > rectangleLeftTopY)
|| (linePointY1 < rectangleRightBottomY && linePointY2 < rectangleRightBottomY)) {
return false;
} else {
return true;
}
} else {
return false;
}
}
ok,完成了。。。