Appium实现图片放大缩小(双指操作)

既然是新用法,肯定是在其他地方不会随处见到的,搞不好还是独一份。

Appium 的放大缩小操作经历了几次大的改版,已经改的面目全非,绝大多数的老教程现在已经失效。最开始 Appium 提供了现成的方法可以直接调用,后来又全部转移到 MultiAction 这个类中,大多数的教程都是基于 MultiAction 这个类实现放大缩小功能。

但是在新版的 Appium 中,MultiAction 这个类被移除了,甚至 TouchAction 这个类也移除了,直接导致现有的教程全部失效。从 2.0 版本后,全部都要使用 w3c action 来代替。 img

# w3c 操作

所谓的 w3c action,是 w3c 给 webdriver 提供的一套底层接口,用于向web浏览器提供虚拟设备输入。从概念上讲,本地发送一系列动作,这些动作对应于每个输入设备在每个时期的状态变化。 img

例如,click 点击由一个输入设备(鼠标)和两个记号组成的动作序列(pointerDown、pointerUp)表示,第一个包含按键向下动作(pointerDown),第二个包含按键向上动作(pointerUp)。

而不论是缩小和放大,都是由两个输入设备(手指1,手指2)和三个记号组成的动作序列表示,每个手指依次执行:

  • pointerDown,两个手指按下

  • pointerMove,两个手指向相反方向移动

  • pointerUp,两个手指抬起。 img

# 现成的参考案例

Appium 本身已经基于 w3c action 封装了两个常用的方法,一个是 swipe ,另一个是 tap 方法,在实现放大缩小功能时,我们不需要自己从 0 到 1 实现,而是借助这两个已经封装完成的方法,修改一下。

首先看 tap 操作的源码: img

  • 第 134 行,初始化了一个虚拟设备,也就是触屏操作当中的一个手指,如果有多个手指,就初始化多次。

  • 第 135 行,手指移动到一个坐标位置

  • 第 136 行,手指按下屏幕

  • 第 137-140 行,手指停顿

  • 第 141 行,手指抬起。

可以发现,tap 的操作完全是基于流程图中的 3 个子操作完成的。因此我们可以使用同样的思路实现方法功能。

# 如何完成放大

  • 1、使用 add_point_input 添加手指,放大需要用到两个手指。

  • 2、使用 create_pointer_move 移动到屏幕的正中间

  • 3、使用 create_pointer_down 按下手指

  • 4、使用 create_pointer_move 往屏幕相反方向移动

  • 5、使用 create_pointer_up 松开手指

具体实现放大功能的代码如下:

def zoom(driver: Remote, step=0.5, duration=None):
    actions = ActionChains(driver)
    actions.w3c_actions.devices = []
    finger1 = actions.w3c_actions.add_pointer_input('touch', f'finger1')
    finger2 = actions.w3c_actions.add_pointer_input('touch', f'finger2')

    width = driver.get_window_size()['width']
    height = driver.get_window_size()['height']

    for finger in [finger1, finger2]:
        finger.create_pointer_move(x=width*0.5, y=height*0.5)
        finger.create_pointer_down(MouseButton.LEFT)
        if duration:
            finger.create_pause(duration / 1000)
        else:
            finger.create_pause(0.1)

    finger1.create_pointer_move(x=width*0.5, y=height*(0.5+step/2))
    finger2.create_pointer_move(x=width * 0.5, y=height * (0.5-step/2))

    finger1.create_pointer_up(MouseButton.LEFT)
    finger2.create_pointer_up(MouseButton.LEFT)

    actions.perform()

调用 zoom 方法实现图片放大操作:

caps = {
    'platformName': 'Android',
    'udid': 'emulator-5554',
    'appPackage': 'com.android.gallery3d',
    'appActivity': '.app.GalleryActivity'
}

driver = Remote(desired_capabilities=caps,
                command_executor='http://127.0.0.1:4723/wd/hub')
driver.implicitly_wait(8)
driver.find_element('id', 'com.android.gallery3d:id/gl_root_view').click()

zoom(driver,step=0.5)
driver.quit()

# 如何完成缩小

实现缩小的时候,代码完全可以使用放大功能的代码,只是两个手指先移动到屏幕两端,往中间缩,整个移动的过程相反。

def pitch(driver: Remote, step=0.5, duration=None):
    actions = ActionChains(driver)
    actions.w3c_actions.devices = []
    finger1 = actions.w3c_actions.add_pointer_input('touch', f'finger1')
    finger2 = actions.w3c_actions.add_pointer_input('touch', f'finger2')

    width = driver.get_window_size()['width']
    height = driver.get_window_size()['height']

    finger1.create_pointer_move(x=width * 0.5, y=height*(0.5+step/2))
    finger2.create_pointer_move(x=width * 0.5, y=height * (0.5-step/2))

    for finger in [finger1, finger2]:
        finger.create_pointer_down(MouseButton.LEFT)
        if duration:
            finger.create_pause(duration / 1000)
        else:
            finger.create_pause(0.1)
        finger.create_pointer_move(x=width * 0.5, y=height *0.5)
        finger.create_pointer_up(MouseButton.LEFT)

    actions.perform()

# 总结

随着 Apppium2.x 发布的临近,appium 很多的操作 API 都有比较大的变化,很多之前很有用的教程可能会逐渐失效。

我在之前也是使用 MultiAction 实现放大缩小,但是为了和新版匹配,还是尽早切换成新用法。在编写这套代码前,我也翻阅了很多资料,想找到现成的代码直接套用,但是没有找到,因此才自己实现。

在实现之前,我首先从源代码的警告提示中获得线索,阅读了appium官方提供的 w3c actions 说明。但我发现这个说明不详细,于是又从官方文档摸到了 w3c actions spec 文档阅读,终于理清楚了它的运行机制。

有了理论的支撑,我便尝试在现有框架的源码实现中找灵感,我发现 tap 方法和 swipe 方法都有非常大的借鉴意义。通过这两个方法的源码,我搞清楚了触控操作的大概实现思路和代码编写套路。

之后如果遇到类似的问题,也有一套行之有效的方法可以照着做了。

本文完,感谢你的耐心阅读,如有需要可加我微信,备注「博客」并说明原因,我们一起进步,下次见。

上次更新: 2022/05/31, 06:34:11
最近更新
01
02-Cypress如何在写代码时获取提示
08-27
02
02-Cypress安装
08-27
03
0-Python怎么才能快速学好
08-27
更多文章>