如何生成变焦/捏手势进行测试为Android [英] How to generate zoom/pinch gesture for testing for Android

查看:280
本文介绍了如何生成变焦/捏手势进行测试为Android的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图生成变焦/捏手势进行测试,我曾尝试使用Android API MotionEvent.obtain(),却发现这是很难实现的变焦/捏事件。

我引用从API <一href="http://developer.android.com/reference/android/view/MotionEvent.html#obtain(long,%20long,%20int,%20int,%20android.view.MotionEvent.PointerProperties[],%20android.view.MotionEvent.PointerCoords[],%20int,%20int,%20float,%20float,%20int,%20int,%20int,%20int)"相对=nofollow> MotionEvent.obtain 。你能告诉我正确的方法?

下面是我的实现:

  //变焦,我们需要四点坐标位置:START0,启动1,END0,END1

仪器仪表研究所;

//动作下来事件
MotionEvent事件= MotionEvent.obtain(停机时间,eventTime,MotionEvent.ACTION_DOWN,1,prop_start0,pointerCoords_start0,0,0,0,0,0,0,0,0);
inst.sendPointerSync(事件);

//行动指针2按下事件
事件= MotionEvent.obtain(停机时间,eventTime,MotionEvent.ACTION_POINTER_2_DOWN,2,properties_start0_1,pointerCoords_start0_1,0,0,0,0,0,0,0,0);
inst.sendPointerSync(事件);

//动作移动事件
持续时间= 1000; // 1000毫秒
event_interval = 10;连续的事件10毫秒之间//时间间隔
moveEventNum =持续时间/ event_interval;
stepx0 =(end0.x  -  start0.x)/ moveEventNum;
stepy0 =(end0.y  -  start0.y)/ moveEventNum;
stepx1 =(end1.x  -  start1.x)/ moveEventNum;
stepy1 =(end1.y  -  start1.y)/ moveEventNum;

move_event0 = START0;
move_event1 =启动1;
的for(int i = 0; I&LT; moveEventNum;我++){
       // [这里生成中间分]
       mov_event0.x + = stepx0;
       mov_event0.y + = stepy0;
       mov_event1.x + = stepx1;
       mov_event1.y + = stepy1;

      eventTime + = event_interval;

      事件= MotionEvent.obtain(停机时间,eventTime,MotionEvent.ACTION_MOVE,2,properties_move_event,pointerCoords_move_event0_1,0,0,0,0,0,0,0,0);

     inst.sendPointerSync(事件);
}

事件= MotionEvent.obtain(停机时间,eventTime,MotionEvent.ACTION_POINTER_2_UP,2,properties_end0_1,pointerCoords_end0_1,0,0,0,0,0,0,0,0);
inst.sendPointerSync(事件);

事件= MotionEvent.obtain(停机时间,eventTime,MotionEvent.ACTION_UP,1,END1,pointerCoords_end1,0,0,0,0,0,0,0,0);
inst.sendPointerSync(事件);
 

解决方案

嗯,我已经找到了问题。

问题:

在使用获得()API,我们必须设置点pressure和大小在每个事件。

有关

 获得(很长很长,INT,INT,android.view.MotionEvent.PointerProperties [],
android.view.MotionEvent.PointerCoords [],INT,整数,浮点,浮点,INT,INT,INT,INT)
 

在PointerCoords [],我们必须设置pressure和大小为1,默认值为0。

有关

 公共静态MotionEvent获得(长时间停机,长eventTime,INT动作,
         浮动的x,浮动Y,INT亚状态)

     创建一个新的MotionEvent,填充在基本运动值的子集。
    那些在这里没有规定有:设备ID(通常为0),pressure和大小(始终为1),
x和y precision(始终为1),和edgeFlags(始终为0)。

由于默认的pressure和尺寸是1,所以我们并不需要进行设置。
 

我创建的手势提示:

1。下面真正的手势序列,因为我们要模拟真实的手势

  • 覆盖的onTouchEvent()来检查收到的真实事件 应用。这些事件也可以用于实际对比 用户触摸事件,并产生触摸事件以浏览器 例如:

    一)@覆盖公共布尔的onTouchEvent(MotionEvent事件){     Log.i(web视图,event.toString()+ event.getAction());布尔RT    = super.onTouchEvent(事件);回到室温; }

  • 手动触摸屏,以获得的onTouchEvent真正的手势序列()的一个)。发生事件时,我们可以按照事件序列。 - 如果我们不按照手势事件序列中,仪表事件可能会被拒绝

  • 下面是缩放手势的一个有效的事件序列,(停机时间是相同的所有事件)

    我。一个起点ACTION_DOWN

    二。两个起点ACTION_POINTER_2_DOWN

    两个中间点iii.ACTION_MOVE

    四。的两个端点ACTION_POINTER_2_UP

    诉一个端点的ACTION_UP

2。使用该API MotionEvent.obtain正确

  • 有两种最常用的获得()API。

公共静态MotionEvent获得(长时间停机,长eventTime,INT动作,          漂浮的x,浮Y,INT亚状态)

公共静态MotionEvent获得(很长很长,INT,INT,android.view.MotionEvent.PointerProperties [], android.view.MotionEvent.PointerCoords [],INT,整数,浮点,浮点,INT,INT,INT,INT)

第一种通常用于单点手势,像一扔,滚动,点击等参数(pressure,大小,X presion公司,Y presion公司),该功能都集为1。

和第二个是一个更一般的,并可以用于多点触摸事件生成。而对于第二个,我们要设置pressure,大小中的每个触摸点pointerCoords为1。

下面是例子生成缩放手势:

 公共静态无效generateZoomGesture(仪器仪表研究所,
        长的startTime,布尔ifMove,GestureInfo.Point startPoint1,
        GestureInfo.Point startPoint2,GestureInfo.Point端点1,
        GestureInfo.Point端点2,INT持续时间){

    如果(研究所== NULL || startPoint1 == NULL
            || (ifMove&安培;&安培;端点1 == NULL)){
        返回;
    }

    长eventTime = startTime时;
    长时间停机= startTime时;
    MotionEvent事件;
    浮eventX1,eventY1,eventX2,eventY2;

    eventX1 = startPoint1.x;
    eventY1 = startPoint1.y;
    eventX2 = startPoint2.x;
    eventY2 = startPoint2.y;

    //指定属性的两个触摸点
    PointerProperties []属性=新PointerProperties [2];
    PointerProperties PP1 =新PointerProperties();
    pp1.id = 0;
    pp1.toolType = MotionEvent.TOOL_TYPE_FINGER;
    PointerProperties PP2 =新PointerProperties();
    pp2.id = 1;
    pp2.toolType = MotionEvent.TOOL_TYPE_FINGER;

    特性[0] = PP1;
    性能[1] = PP2;

    //指定的两个触摸点的坐标位置
    //注意:必须设置pressure和大小值,或者它不工作
    PointerCoords [] pointerCoords =新PointerCoords [2];
    PointerCoords PC1 =新PointerCoords();
    pc1.x = eventX1;
    pc1.y = eventY1;
    。PC1 pressure = 1;
    pc1.size = 1;
    PointerCoords PC2 =新PointerCoords();
    pc2.x = eventX2;
    pc2.y = eventY2;
    。PC2 pressure = 1;
    pc2.size = 1;
    pointerCoords [0] = PC1;
    pointerCoords [1] = PC2;

    ////////////////////////////////////////////////// ////////////
    //事件缩放手势序列
    // 1.发送ACTION_DOWN的一个起点事件
    两个起点// 2。发送ACTION_POINTER_2_DOWN
    // 3。发送两个中间点ACTION_MOVE
    // 4.重复步骤3用更新的中点(X,Y),
    //直至到达终点
    两个端点// 5.发送ACTION_POINTER_2_UP
    一个端点的// 6,发送ACTION_UP
    ////////////////////////////////////////////////// ////////////

    // 步骤1
    事件= MotionEvent.obtain(停机时间,eventTime,
                MotionEvent.ACTION_DOWN,1,性能,
                pointerCoords,0,0,1,1,0,0,0,0);

    inst.sendPointerSync(事件);

    //第2步
    事件= MotionEvent.obtain(停机时间,eventTime,
                MotionEvent.ACTION_POINTER_2_DOWN,2,
                性能,pointerCoords,0,0,1,1,0,0,0,0);

    inst.sendPointerSync(事件);

    //步骤3,4
    如果(ifMove){
        INT moveEventNumber = 1;
        moveEventNumber =持续时间/ EVENT_MIN_INTERVAL;

        浮stepX1,stepY1,stepX2,stepY2;

        stepX1 =(endPoint1.x  -  startPoint1.x)/ moveEventNumber;
        stepY1 =(endPoint1.y  -  startPoint1.y)/ moveEventNumber;
        stepX2 =(endPoint2.x  -  startPoint2.x)/ moveEventNumber;
        stepY2 =(endPoint2.y  -  startPoint2.y)/ moveEventNumber;

        的for(int i = 0; I&LT; moveEventNumber;我++){
            //更新移动事件
            eventTime + = EVENT_MIN_INTERVAL;
            eventX1 + = stepX1;
            eventY1 + = stepY1;
            eventX2 + = stepX2;
            eventY2 + = stepY2;

            pc1.x = eventX1;
            pc1.y = eventY1;
            pc2.x = eventX2;
            pc2.y = eventY2;

            pointerCoords [0] = PC1;
            pointerCoords [1] = PC2;

            事件= MotionEvent.obtain(停机时间,eventTime,
                        MotionEvent.ACTION_MOVE,2,属性
                        pointerCoords,0,0,1,1,0,0,0,0);

            inst.sendPointerSync(事件);
        }
    }

    //第5步
    pc1.x = endPoint1.x;
    pc1.y = endPoint1.y;
    pc2.x = endPoint2.x;
    pc2.y = endPoint2.y;
    pointerCoords [0] = PC1;
    pointerCoords [1] = PC2;

    eventTime + = EVENT_MIN_INTERVAL;
    事件= MotionEvent.obtain(停机时间,eventTime,
                MotionEvent.ACTION_POINTER_2_UP,2,属性
                pointerCoords,0,0,1,1,0,0,0,0);
    inst.sendPointerSync(事件);

    //第6步
    eventTime + = EVENT_MIN_INTERVAL;
    事件= MotionEvent.obtain(停机时间,eventTime,
                MotionEvent.ACTION_UP,1,性能,
                pointerCoords,0,0,1,1,0,0,0,0);
    inst.sendPointerSync(事件);
}
 

I'm trying to generate zoom/pinch gesture for testing, I have tried to use the Android API MotionEvent.obtain(), but found it is hard to implement the zoom/pinch events.

I referenced the API from MotionEvent.obtain. Can you tell me the correct method?

Here is my implementation:

//for zoom, we need four points coordinations: start0, start1, end0, end1

Instrumentation inst;

// action down event
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, 1, prop_start0, pointerCoords_start0, 0,  0, 0, 0, 0, 0, 0, 0 );
inst.sendPointerSync(event);

// action pointer 2 down event
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_POINTER_2_DOWN, 2, properties_start0_1, pointerCoords_start0_1, 0, 0, 0, 0, 0, 0, 0, 0);
inst.sendPointerSync(event);

// action move events
duration = 1000; //1000 ms
event_interval = 10;//time interval between consecutive events 10ms 
moveEventNum = duration / event_interval; 
stepx0 = (end0.x - start0.x)/moveEventNum;
stepy0 = (end0.y - start0.y)/moveEventNum;
stepx1 = (end1.x - start1.x)/moveEventNum;
stepy1 = (end1.y - start1.y)/moveEventNum;

move_event0= start0;
move_event1 = start1;
for ( int i = 0; i < moveEventNum; i++) {
       //  [generate middle points here ]
       mov_event0.x += stepx0;
       mov_event0.y += stepy0;
       mov_event1.x += stepx1;
       mov_event1.y += stepy1;

      eventTime += event_interval;

      event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, 2, properties_move_event, pointerCoords_move_event0_1, 0, 0, 0, 0, 0, 0, 0, 0); 

     inst.sendPointerSync(event);
}

event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_POINTER_2_UP, 2, properties_end0_1, pointerCoords_end0_1, 0, 0, 0, 0, 0, 0, 0, 0);
inst.sendPointerSync(event);

event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, 1, end1, pointerCoords_end1, 0, 0, 0, 0, 0, 0, 0, 0 );
inst.sendPointerSync(event);

解决方案

well, i have found the issue.

ISSUE:

When using the obtain() API, we have to set the pressure and size of the points in each event.

For

obtain(long, long, int, int, android.view.MotionEvent.PointerProperties[], 
android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int)

the PointerCoords[], we have to set the pressure and size to 1, the default values are 0.

For

public static MotionEvent obtain (long downTime, long eventTime, int action,
         float x, float y, int metaState)

     Create a new MotionEvent, filling in a subset of the basic motion values. 
    Those not specified here are: device id (always 0), pressure and size (always 1), 
x and y precision (always 1), and edgeFlags (always 0).

since the default pressure and size are 1, so we don't need to set them.

My tips for creating gestures:

1. following the real gesture sequence, since we want to simulate the real gestures

  • override the onTouchEvent() to check the real events received by application. These events can also be used for comparison of real user touch events and generated touch events Take browser for example:

    a) @Override public boolean onTouchEvent(MotionEvent event) { Log.i("WebView", event.toString() + event.getAction()); boolean rt = super.onTouchEvent(event); return rt; }

  • manually touch screen to get the real gesture sequence from onTouchEvent() in a). We can follow the event sequence when generating events. -- If we don’t follow the gesture event sequence, the instrumented events may be rejected.

  • Here is a valid event sequence of zoom gesture, (the downTime is the same for all the events)

    i. ACTION_DOWN of one start point

    ii. ACTION_POINTER_2_DOWN of two start points

    iii.ACTION_MOVE of two middle points

    iv. ACTION_POINTER_2_UP of two end points

    v. ACTION_UP of one end point

2. use the API MotionEvent.obtain correctly

  • There are two most used obtain() API.

public static MotionEvent obtain (long downTime, long eventTime, int action, float x, float y, int metaState)

AND

public static MotionEvent obtain(long, long, int, int, android.view.MotionEvent.PointerProperties[], android.view.MotionEvent.PointerCoords[], int, int, float, float, int, int, int, int)

The first one is usually used for single point gestures, like fling, scroll, click etc. The parameters (pressure, size, xPresion, yPresion) for this function are all set to 1.

And the second one is a more general one, and can be used for multi-touch events generation. While for the second one, we have to set the pressure, size in pointerCoords of each touch point to 1.

Here is the example to generate the zoom gesture:

public static void generateZoomGesture(Instrumentation inst,
        long startTime, boolean ifMove, GestureInfo.Point startPoint1,
        GestureInfo.Point startPoint2, GestureInfo.Point endPoint1,
        GestureInfo.Point endPoint2, int duration) {

    if (inst == null || startPoint1 == null
            || (ifMove && endPoint1 == null)) {
        return;
    }

    long eventTime = startTime;
    long downTime = startTime;
    MotionEvent event;
    float eventX1, eventY1, eventX2, eventY2;

    eventX1 = startPoint1.x;
    eventY1 = startPoint1.y;
    eventX2 = startPoint2.x;
    eventY2 = startPoint2.y;

    // specify the property for the two touch points
    PointerProperties[] properties = new PointerProperties[2];
    PointerProperties pp1 = new PointerProperties();
    pp1.id = 0;
    pp1.toolType = MotionEvent.TOOL_TYPE_FINGER;
    PointerProperties pp2 = new PointerProperties();
    pp2.id = 1;
    pp2.toolType = MotionEvent.TOOL_TYPE_FINGER;

    properties[0] = pp1;
    properties[1] = pp2;

    //specify the coordinations of the two touch points
    //NOTE: you MUST set the pressure and size value, or it doesn't work
    PointerCoords[] pointerCoords = new PointerCoords[2];
    PointerCoords pc1 = new PointerCoords();
    pc1.x = eventX1;
    pc1.y = eventY1;
    pc1.pressure = 1;
    pc1.size = 1;
    PointerCoords pc2 = new PointerCoords();
    pc2.x = eventX2;
    pc2.y = eventY2;
    pc2.pressure = 1;
    pc2.size = 1;
    pointerCoords[0] = pc1;
    pointerCoords[1] = pc2;

    //////////////////////////////////////////////////////////////
    // events sequence of zoom gesture
    // 1. send ACTION_DOWN event of one start point
    // 2. send ACTION_POINTER_2_DOWN of two start points
    // 3. send ACTION_MOVE of two middle points
    // 4. repeat step 3 with updated middle points (x,y),
    //      until reach the end points
    // 5. send ACTION_POINTER_2_UP of two end points
    // 6. send ACTION_UP of one end point
    //////////////////////////////////////////////////////////////

    // step 1
    event = MotionEvent.obtain(downTime, eventTime, 
                MotionEvent.ACTION_DOWN, 1, properties, 
                pointerCoords, 0,  0, 1, 1, 0, 0, 0, 0 );

    inst.sendPointerSync(event);

    //step 2
    event = MotionEvent.obtain(downTime, eventTime, 
                MotionEvent.ACTION_POINTER_2_DOWN, 2, 
                properties, pointerCoords, 0, 0, 1, 1, 0, 0, 0, 0);

    inst.sendPointerSync(event);

    //step 3, 4
    if (ifMove) {
        int moveEventNumber = 1;
        moveEventNumber = duration / EVENT_MIN_INTERVAL;

        float stepX1, stepY1, stepX2, stepY2;

        stepX1 = (endPoint1.x - startPoint1.x) / moveEventNumber;
        stepY1 = (endPoint1.y - startPoint1.y) / moveEventNumber;
        stepX2 = (endPoint2.x - startPoint2.x) / moveEventNumber;
        stepY2 = (endPoint2.y - startPoint2.y) / moveEventNumber;

        for (int i = 0; i < moveEventNumber; i++) {
            // update the move events
            eventTime += EVENT_MIN_INTERVAL;
            eventX1 += stepX1;
            eventY1 += stepY1;
            eventX2 += stepX2;
            eventY2 += stepY2;

            pc1.x = eventX1;
            pc1.y = eventY1;
            pc2.x = eventX2;
            pc2.y = eventY2;

            pointerCoords[0] = pc1;
            pointerCoords[1] = pc2;

            event = MotionEvent.obtain(downTime, eventTime,
                        MotionEvent.ACTION_MOVE, 2, properties, 
                        pointerCoords, 0, 0, 1, 1, 0, 0, 0, 0);

            inst.sendPointerSync(event);
        }
    }

    //step 5
    pc1.x = endPoint1.x;
    pc1.y = endPoint1.y;
    pc2.x = endPoint2.x;
    pc2.y = endPoint2.y;
    pointerCoords[0] = pc1;
    pointerCoords[1] = pc2;

    eventTime += EVENT_MIN_INTERVAL;
    event = MotionEvent.obtain(downTime, eventTime,
                MotionEvent.ACTION_POINTER_2_UP, 2, properties, 
                pointerCoords, 0, 0, 1, 1, 0, 0, 0, 0);
    inst.sendPointerSync(event);

    // step 6
    eventTime += EVENT_MIN_INTERVAL;
    event = MotionEvent.obtain(downTime, eventTime, 
                MotionEvent.ACTION_UP, 1, properties, 
                pointerCoords, 0, 0, 1, 1, 0, 0, 0, 0 );
    inst.sendPointerSync(event);
}

这篇关于如何生成变焦/捏手势进行测试为Android的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆