appium2.0+同时实现多点触控和单点触控的多种方法

发布于:2025-07-31 ⋅ 阅读:(22) ⋅ 点赞:(0)

若未了解单点触控,可先大概了解一下动作构建器Actionbuilder的PointerActions操作
appium2.0+之PointerActions详解

以下放大图片的示例在夜神模拟器上进行。

一、多点触控

1. 多点触控核心实现逻辑

(1)创建一个用于管理用户交互动作的 动作链对象/动作构建对象
(2)多指针创建:通过add_pointer_input创建多个 touch 类型的虚拟手指
(3) 定义多个虚拟手指的同步动作序列
(4)统一执行perform,实现多点触控

2. 执行时间逻辑

动作按 “时间轴” 执行,而非代码顺序,在同一个ActionBuilderActionChains中,两个手指(finger1finger2)是否会 “同时运行”,不取决于代码的编写顺序,而取决于动作的 “时间线设置”—— 即通过duration(持续时间)和pause(暂停时间)定义的动作时序。同一时间点的动作会 “并行执行”,不同时间点的动作会 “串行执行”。

二、单点触控+多点触控案例

代码执行前准备

  • 命令行启动appium服务(版本2.19.0):
appium --address 127.0.0.1 --log-level debug --use-drivers uiautomator2
  • 模拟器打开,命令行adb devices显示设备已连接
    在这里插入图片描述

1. 方法1:建立两个Actionbuilder对象

逻辑:建立两个Actionbuilder对象,一个用来单点触控,一个用来多点触控

#!/usr/bin/env python
# encoding: utf-8
'''
@Author  : 草木零
@Software: PyCharm
@File    : class04_multiTouch.py
@Time    : 2025/7/29 14:22
@desc   : 多点触控示例,放大图片
多点触控核心实现:
通过创建两个PointerInput对象模拟两个手指(finger1和finger2)
actionbuilder通过add_pointer_input添加多个触控设备
手指添加操作,最后perform,实现多点触控
'''
from time import sleep
from appium import webdriver
from appium.options.android import UiAutomator2Options  # 导入 Android 选项类
from selenium.webdriver.common.actions.action_builder import ActionBuilder

# 手机/模拟器,配置信息
desired_caps = {
    "platformName": "Android",
    "platformVersion": "7.1.2",
    "deviceName": "127.0.0.1:62001",
    "appPackage": "com.android.gallery3d",
    # 获取包名、界面名:adb shell dumpsys window|findstr mCurrentFocus
    "appActivity": "com.android.gallery3d.app.GalleryActivity",
    "noReset": False
}

# 显式传入 options 参数(适用于必须使用高版本 Selenium 的场景)
# 将 desired_caps 转换为 Options 实例
options = UiAutomator2Options().load_capabilities(desired_caps)

# 传入 options 参数
driver = webdriver.Remote(
    command_executor='http://127.0.0.1:4723',
    options=options  # 必须传入 options,替代原来的 desired_capabilities
)

# 获取窗口尺寸
window_size = driver.get_window_size() #返回dict格式的当前窗口屏幕尺寸
width = window_size['width']  # 获取宽度
height = window_size['height']  # 获取高度
# 第一根手指的移动位置
startX1 = width*0.6
startY1 = height*0.4
endX1 = width*0.9
endY1 = height*0.1
# 第二根手指移动位置
startX2 = width*0.4
startY2 = height*0.6
endX2 = width*0.1
endY2 = height*0.9

# 分为两个builder(推荐两个builder统一使用touch类型),第一个用来先执行单击操作后perform,第二个builder做多点触控两个手指同时操作
# 创建单点触控的builder
singleBuilder = ActionBuilder(driver)
singleAct = singleBuilder.add_pointer_input('touch', 'singleAct')

# 创建双指多点触控的Builder
zoomBuilder = ActionBuilder(driver)
finger1 = zoomBuilder.add_pointer_input('touch', 'finger1')
finger2 = zoomBuilder.add_pointer_input('touch', 'finger2')

sleep(3) #待页面稳定
# 单击选择中间的图片
singleAct.create_pointer_move(duration=0, x=width*0.5, y=height*0.5)
singleAct.create_pointer_down() #按下
singleAct.create_pause(0.1) #间隔
singleAct.create_pointer_up(0) #抬起左键,0左键,1滚轮,2右键
singleAct.create_pause(1) #间隔1s
singleBuilder.perform()

# 多点触控操作
# 手指1操作
finger1.create_pointer_move(duration=0, x=startX1, y=startY1) # 手指1移动到起点
finger1.create_pointer_down()
finger1.create_pause(0.2) #按下后短暂停留,单位s
finger1.create_pointer_move(500, endX1, endY1)
finger1.create_pointer_up(0) #抬起

# 手指2操作
# 注意,finger2的开始执行时间不取决于代码的编写顺序,而取决于动作的 “时间线设置”,
# duration=0即在时间轴上0开始执行,因为finger1的时间轴开始也是0,这样就实现两根手指同时开始动作,若finger2的duration=1000,那就是在时间轴1s是才开始finger2的执行
finger2.create_pointer_move(duration=0, x=startX2, y=startY2) # 手指2移动到起点,duration单位为ms
finger2.create_pointer_down()
finger2.create_pause(0.2) #按下后短暂停留,单位s
finger2.create_pointer_move(500, endX2, endY2)
finger2.create_pointer_up(button=0) #抬起 button=0为抬起左键,1为滚轮,2为右键


# 执行完整动作链
zoomBuilder.perform()
sleep(2)
driver.quit()

2. 方法2:单点触控通过Actionchains,多点触控通过Actionbuilder实现

用下面的代码替换掉方法1里单点触控的代码即可:

# 创建单点触控的动作链
singleChains = ActionChains(driver)
# 通过Actionchains单击选择中间的图片
imgEl = driver.find_element('id', 'android:id/content')
singleChains.click(imgEl)
singleChains.pause(1) #暂停1s
singleChains.perform()

完整代码

'''
@Author  : 草木零
@Software: PyCharm
@File    : class05_actionChains.py
@Time    : 2025/7/30 11:39
@desc   : 先通过Actionchains实现单点触控,再通过Actionbuilder实现多点触控
'''
from time import sleep
from appium import webdriver
from appium.options.android import UiAutomator2Options  # 导入 Android 选项类
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver import ActionChains
# 手机/模拟器,配置信息
desired_caps = {
    "platformName": "Android",
    "platformVersion": "7.1.2",
    "deviceName": "127.0.0.1:62001",
    "appPackage": "com.android.gallery3d",
    # 获取包名、界面名:adb shell dumpsys window|findstr mCurrentFocus
    "appActivity": "com.android.gallery3d.app.GalleryActivity",
    "noReset": False
}

# 显式传入 options 参数(适用于必须使用高版本 Selenium 的场景)
# 将 desired_caps 转换为 Options 实例
options = UiAutomator2Options().load_capabilities(desired_caps)

# 传入 options 参数
driver = webdriver.Remote(
    command_executor='http://127.0.0.1:4723',
    options=options  # 必须传入 options,替代原来的 desired_capabilities
)

# 获取窗口尺寸
window_size = driver.get_window_size() #返回dict格式的当前窗口屏幕尺寸
width = window_size['width']  # 获取宽度
height = window_size['height']  # 获取高度
# 第一根手指的移动位置
startX1 = width*0.6
startY1 = height*0.4
endX1 = width*0.9
endY1 = height*0.1
# 第二根手指移动位置
startX2 = width*0.4
startY2 = height*0.6
endX2 = width*0.1
endY2 = height*0.9

# 创建单点触控的动作链
singleChains = ActionChains(driver)

# 创建双指多点触控的Builder
zoomBuilder = ActionBuilder(driver)
finger1 = zoomBuilder.add_pointer_input('touch', 'finger1')
finger2 = zoomBuilder.add_pointer_input('touch', 'finger2')

sleep(3) #待页面稳定
# 通过Actionchains单击选择中间的图片
imgEl = driver.find_element('id', 'android:id/content')
singleChains.click(imgEl)
singleChains.pause(1) #暂停1s
# 执行动作链
singleChains.perform()

# 多点触控操作
# 手指1操作
finger1.create_pointer_move(duration=0, x=startX1, y=startY1) # 手指1移动到起点
finger1.create_pointer_down()
finger1.create_pause(0.2) #按下后短暂停留,单位s
finger1.create_pointer_move(500, endX1, endY1)
finger1.create_pointer_up(0) #抬起

# 手指2操作
# 注意,finger2的开始执行时间不取决于代码的编写顺序,而取决于动作的 “时间线设置”,
# duration=0即在时间轴上0开始执行,因为finger1的时间轴开始也是0,这样就实现两根手指同时开始动作,若finger2的duration=1000,那就是在时间轴1s是才开始finger2的执行
finger2.create_pointer_move(duration=0, x=startX2, y=startY2) # 手指2移动到起点,duration单位为ms
finger2.create_pointer_down()
finger2.create_pause(0.2) #按下后短暂停留,单位s
finger2.create_pointer_move(500, endX2, endY2)
finger2.create_pointer_up(button=0) #抬起 button=0为抬起左键,1为滚轮,2为右键

# 执行完整动作链
zoomBuilder.perform()
sleep(2)
driver.quit()

3. 方法3:创建两个动作链Actionchains对象

用下面的代码替换方法2中关于多点触控的代码即可:

# 创建双指多点触控的Actionchains实例
zoomChains = ActionChains(driver)
finger1 = zoomChains.w3c_actions.add_pointer_input('touch', 'finger1')
finger2 = zoomChains.w3c_actions.add_pointer_input('touch', 'finger2')
# ......省略的中间代码,其实这里finger1/2可调用的方法同Actionbuilder创建的手指是一样的(点开两者的add_pointer_input查看底层代码就知道是一样的返回),所以其他地方不用改

# 执行完整动作链
zoomChains.perform()

完整代码

#!/usr/bin/env python
# encoding: utf-8
'''
@Author  : 草木零
@Software: PyCharm
@File    : class05_actionChains02.py
@Time    : 2025/7/30 12:03
@desc   : 通过Actionchains实现多点触控,放大图片
操作:建立一个Actionchains实例来管理单点触控的操作,再建立另一个Actionchains实例来管理多点触控的操作
'''
from time import sleep
from appium import webdriver
from appium.options.android import UiAutomator2Options  # 导入 Android 选项类
from selenium.webdriver import ActionChains


# 手机/模拟器,配置信息
desired_caps = {
    "platformName": "Android",
    "platformVersion": "7.1.2",
    "deviceName": "127.0.0.1:62001",
    "appPackage": "com.android.gallery3d",
    # 获取包名、界面名:adb shell dumpsys window|findstr mCurrentFocus
    "appActivity": "com.android.gallery3d.app.GalleryActivity",
    "noReset": False
}

# 显式传入 options 参数(适用于必须使用高版本 Selenium 的场景)
# 将 desired_caps 转换为 Options 实例
options = UiAutomator2Options().load_capabilities(desired_caps)

# 传入 options 参数
driver = webdriver.Remote(
    command_executor='http://127.0.0.1:4723',
    options=options  # 必须传入 options,替代原来的 desired_capabilities
)

# 获取窗口尺寸
window_size = driver.get_window_size() #返回dict格式的当前窗口屏幕尺寸
width = window_size['width']  # 获取宽度
height = window_size['height']  # 获取高度
# 第一根手指的移动位置
startX1 = width*0.6
startY1 = height*0.4
endX1 = width*0.9
endY1 = height*0.1
# 第二根手指移动位置
startX2 = width*0.4
startY2 = height*0.6
endX2 = width*0.1
endY2 = height*0.9

# 创建单点触控的动作链
singleChains = ActionChains(driver)

# 创建双指多点触控的Actionchains实例
zoomChains = ActionChains(driver)
finger1 = zoomChains.w3c_actions.add_pointer_input('touch', 'finger1')
finger2 = zoomChains.w3c_actions.add_pointer_input('touch', 'finger2')

sleep(3) #待页面稳定
# 通过Actionchains单击选择中间的图片
imgEl = driver.find_element('id', 'android:id/content')
singleChains.click(imgEl)
singleChains.pause(1) #暂停1s
# 执行动作链
singleChains.perform()

# 多点触控操作
# 手指1操作
finger1.create_pointer_move(duration=0, x=startX1, y=startY1) # 手指1移动到起点
finger1.create_pointer_down()
finger1.create_pause(0.2) #按下后短暂停留,单位s
finger1.create_pointer_move(500, endX1, endY1)
finger1.create_pointer_up(0) #抬起

# 手指2操作
# 注意,finger2的开始执行时间不取决于代码的编写顺序,而取决于动作的 “时间线设置”,
# duration=0即在时间轴上0开始执行,因为finger1的时间轴开始也是0,这样就实现两根手指同时开始动作,若finger2的duration=1000,那就是在时间轴1s是才开始finger2的执行
finger2.create_pointer_move(duration=0, x=startX2, y=startY2) # 手指2移动到起点,duration单位为ms
finger2.create_pointer_down()
finger2.create_pause(0.2) #按下后短暂停留,单位s
finger2.create_pointer_move(500, endX2, endY2)
finger2.create_pointer_up(button=0) #抬起 button=0为抬起左键,1为滚轮,2为右键

# 执行完整动作链
zoomChains.perform()
sleep(2)
driver.quit()

三、扩展:ActionChains部分底层代码

from selenium.webdriver import ActionChains

pycharm中按住Ctrl+左键点击from selenium.webdriver import ActionChains中的ActionChains,可查看ActionChains的实现代码,发现它还是使用的 ActionBuilder 类来实现,如下图:
在这里插入图片描述

Actionchains封装的方法

在这里插入图片描述

如果Actionchains中已实现的封装方法不够用,我们再通过w3c_actionspointer_action里的方法来实现,前面已细讲PointerActions类。
appium2.0+之PointerActions详解
下面展示如何从ActionChains是如何从高到低看到PointerAction的。

ActionChains(driver).w3c_actions中的一些方法

图片:
在这里插入图片描述

其中ActionChains(driver).w3c_actions.add_pointer_input()里的类型kind有三种:mouse(鼠标),touch(触屏),pen(笔触)
在这里插入图片描述

w3c_actions.pointer_action中实现的方法

所以一层层走下来,如果Actionchains类中已封装实现的方法不够满足我们的需求,是可以通过更底层的ActionChains(driver).w3c_actions.pointer_action的方法来实现所求的,而PointerActions类前面已具体讲解使用方法
appium2.0+之PointerActions详解
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到