appium2.0+之PointerActions详解

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

以下内容在 夜神模拟器 上进行。

一、应用场景

一些针对手势的操作,比如滑动、长按、拖动等。可以将这些基本手势组合成一个相对复杂的手势。

二、使用步骤

  1. 创建触摸输入设备(模拟手指操作)

    touch_input = PointerInput(interaction.POINTER_TOUCH, "touch")
    
  2. 创建动作构建器

    action_builder = ActionBuilder(driver, mouse=touch_input)
    
  3. 构建动作
    在这里插入图片描述

  4. 用perform执行完整动作链

    action_builder.perform()
    

三、PointerActions方法详解

按住Ctrl+左键点击pointer_action,再从跳转文件Ctrl+左键点击PointerActions,跳转PointerActions类查看其方法详细内容

在这里插入图片描述

在这里插入图片描述

  • move_to_location(x: int, y: int)

作用:将指针(如手指)移动到屏幕指定坐标(x, y),x:目标位置的 X 坐标(相对于屏幕左上角,单位像素)

  • pointer_down() 按下

pointer_down(
        self,
        button=MouseButton.LEFT,
        width=None,
        height=None,
        pressure=None,
        tangential_pressure=None,
        tilt_x=None,
        tilt_y=None,
        twist=None,
        altitude_angle=None,
        azimuth_angle=None,
    )

对于大多数普通场景(如点击、滑动),无需复杂参数,仅需指定基础动作即可:

action.pointer_action.pointer_down()  
  • pointer_up() 抬起

pointer_up(button=MouseButton.LEFT)
  • move_to():基于元素/坐标移动

支持基于元素或坐标的移动,还可通过参数控制移动过程中的触摸细节(如压力、角度等):

def move_to(
    self,
    element,
    x=0,
    y=0,
    width=None,
    height=None,
    pressure=None,
    tangential_pressure=None,
    tilt_x=None,
    tilt_y=None,
    twist=None,
    altitude_angle=None,
    azimuth_angle=None,
)
  1. 基于元素的移动
    以元素为基准,通过 x/y 设定相对偏移(适合元素位置动态变化的场景):

    # 移动到元素的右上角(元素左上角 + 宽偏移,高0)
    element = driver.find_element('id', 'target_btn')
    action.pointer_action.move_to(
        element=element, 
        x=element.size['width'],  # 相对元素左上角X偏移(等于元素宽度→右上角)
        y=0  # 相对元素左上角Y偏移0
    )
    
  2. 基于绝对坐标的移动

    action.pointer_action.move_to(x=500, y=300)
    
  3. 结合按下 / 抬起实现滑动
    移动过程中保持按下状态,实现滑动效果:

    # 从元素A滑动到元素B
    element_a = driver.find_element('id', 'start_point')
    element_b = driver.find_element('id', 'end_point')
    
    # 移动到A→按下→移动到B→抬起(完成滑动)
    action.pointer_action.move_to(element=element_a)
    action.pointer_action.pointer_down()  # 按下(开始滑动)
    action.pointer_action.move_to(element=element_b)  # 滑动到B
    action.pointer_action.pointer_up()    # 抬起(结束滑动)
    action.perform()
    
  • move_by 基于当前位置移动

基于相对当前位置移动指针设备,move_by() 是实现连续、精细手势的核心方法,尤其适合需要模拟人手自然滑动的场景(如滚动列表、拖拽控件等):

def move_by(
    self,
    x,
    y,
    width=None,
    height=None,
    pressure=None,
    tangential_pressure=None,
    tilt_x=None,
    tilt_y=None,
    twist=None,
    altitude_angle=None,
    azimuth_angle=None,
)
  1. 基础相对移动
# 假设指针当前在(100, 200)位置
action.pointer_action.move_by(x=200, y=100)  # 向右移动200px,向下移动100px→新位置(300, 300)
  1. 按下并连续滑动
    按下并连续滑动(分两步向上移动):
action.pointer_action.pointer_down()  # 按下(开始滑动)
action.pointer_action.move_by(x=0, y=-300)  # 第一步:向上移动300px(y为负)
action.pointer_action.move_by(x=0, y=-300)  # 第二步:再向上移动300px
action.pointer_action.pointer_up()    # 抬起(结束滑动)
  • move_to_location() 直接移动到屏幕指定绝对坐标位置

def move_to_location(
    self,
    x,
    y,
    width=None,
    height=None,
    pressure=None,
    tangential_pressure=None,
    tilt_x=None,
    tilt_y=None,
    twist=None,
    altitude_angle=None,
    azimuth_angle=None,
)

示例:

# 移动到屏幕(300, 500)位置并点击
action.pointer_action.move_to_location(x=300, y=500)  # 直接定位到绝对坐标
  • click() 点击

直接对元素或指定坐标位置执行点击:

action.pointer_action.click(element)  # 直接点击元素

若未传入 element,需先通过 move_to_location() 定位到坐标,再调用 click()

  • context_click()

模拟上下文点击(通常指鼠标右键点击),主要用于触发元素的上下文菜单(如桌面端网页或应用中右键点击元素弹出的菜单)。在移动设备上,此方法通常等效于长按操作(因为移动设备无鼠标右键,长按是触发上下文菜单的常见方式)。

  • click_and_hold() 点击并按住

常用于拖拽、长按触发菜单等需要持续按压的场景:

# 拖拽流程:按住→移动→抬起
action.pointer_action.click_and_hold(element=app_icon)  # 按住图标
action.pointer_action.move_by(x=200, y=300)  # 向右下方移动
action.pointer_action.release()  # 抬起(释放图标)
  • release() 抬起

用于结束之前通过 click_and_hold()pointer_down() 等方法开始的 “按下” 状态,与 pointer_up 功能基本一致。

  • double_click() 双击

double_click(el可选),若无element,则需先定位到目标坐标,再执行双击:

# 定位图片元素并双击(如放大图片)
image = driver.find_element('xpath', '//android.widget.ImageView[@index="0"]')
action.pointer_action.double_click(element=image)  # 双击图片
  • pause(duration: float = 0) 暂停

duration 单位为秒,浮点型。
在动作链中插入 pause() 后,Appium 会在执行到该步骤时暂停指定时长,再继续执行后续动作。主要用于:

  • 模拟长按(按下后暂停一段时间再抬起)。
  • 等待前一个动作生效(如点击按钮后等待页面加载)。
  • 控制手势速度(如滑动过程中减速)。

示例:

# 分步滑动(每步移动+暂停)
action.pointer_action.move_by(x=0, y=-200)  # 第一步上滑
action.pointer_action.pause(0.3)  # 暂停0.3秒
action.pointer_action.move_by(x=0, y=-200)  # 第二步上滑

四、单点触控案例

代码执行前准备

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

1、点击/长按wifi设置

#!/usr/bin/env python
# encoding: utf-8
'''
@Author  : 草木零
@Software: PyCharm
@File    : class03_actionBuilder01.py
@Time    : 2025/7/28 17:04
@desc   : 运行多种方法进行 点击/长按
'''

# 案例1:设置里点击wlan
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.common.actions.pointer_input import PointerInput
from selenium.webdriver.common.actions import interaction

# 手机/模拟器,配置信息
desired_caps = {
    "platformName": "Android",
    "platformVersion": "7.1.2",
    "deviceName": "127.0.0.1:62001",
    "appPackage": "com.android.settings",
    # 获取包名、界面名:adb shell dumpsys window|findstr mCurrentFocus
    "appActivity": "com.android.settings.Settings",
    "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
)

# 获取WLAN元素
wlanEl = driver.find_element('xpath', '//*[@text="WLAN"] ')
# 创建触摸输入设备(模拟手指操作)
touch_input = PointerInput(interaction.POINTER_TOUCH, "touch")
# 创建动作构建器
action_builder = ActionBuilder(driver, mouse=touch_input)

# 例子1:为展示多一点操作搞的复杂示例
# 获取元素中心点坐标
# 元素x轴中心点坐标=元素左上角位置坐标x+元素尺寸宽度的一半
x = wlanEl.location['x'] + wlanEl.size['width'] // 2
y = wlanEl.location['y'] + wlanEl.size['height'] // 2
# 执行点击动作(移动→按下→抬起)
action_builder.pointer_action.move_to_location(x, y) #移动
action_builder.pointer_action.pointer_down() # 左键点击
action_builder.pointer_action.release() #释放鼠标


# 例2:直接一步click点击即可
# action_builder.pointer_action.click(wlanEl) #例1那些操作只用这一步可完成点击效果

# 例3:长按:按下(pointer_down或者click_and_hold)+暂停+抬起
# action_builder.pointer_action.click_and_hold(wlanEl) #点击并按住
# action_builder.pointer_action.pause(2) # 暂停2s
# action_builder.pointer_action.pointer_up() #抬起


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

driver.quit()

2、滑屏解锁

位置:模拟器——设置—安全—设置屏幕锁定——图案
过程:使用了WEditor找元素位置,如果用Android UIAutomator2模式,和appium不要同时开启,用Android adb可以和appium同时开启

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

代码

#!/usr/bin/env python
# encoding: utf-8
'''
@Author  : 草木零
@Software: PyCharm
@File    : class03_actionBuilder02.py
@Time    : 2025/7/29 11:28
@desc   : 手机屏幕图案解锁
'''
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.common.actions.pointer_input import PointerInput
from selenium.webdriver.common.actions import interaction

# 手机/模拟器,配置信息
desired_caps = {
    "platformName": "Android",
    "platformVersion": "7.1.2",
    "deviceName": "127.0.0.1:62001",
    "appPackage": "com.android.settings",
    # 获取包名、界面名:adb shell dumpsys window|findstr mCurrentFocus
    "appActivity": "com.android.settings.ChooseLockPattern",
    "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
)


# 创建触摸输入设备(模拟手指操作)
touch_input = PointerInput(interaction.POINTER_TOUCH, "touch")
# 创建动作构建器
action_builder = ActionBuilder(driver, mouse=touch_input)

# 桌面图案解锁
window_size = driver.get_window_size() #返回dict格式的当前窗口屏幕尺寸
width = window_size['width']  # 获取宽度
height = window_size['height']  # 获取高度
# 各落点位置
startX = width*0.2
startY = height*0.47
midX = width*0.2
midY = height*0.8
endX = width*0.8
endY = height*0.8
action_builder.pointer_action.move_to_location(startX, startY) #移动至起点位置
action_builder.pointer_action.pointer_down()  # 按下
sleep(0.5)  # 按下后短暂停留
action_builder.pointer_action.move_to_location(midX, midY)  # 滑动到中间位置
sleep(0.5)
action_builder.pointer_action.move_to_location(endX, endY)  # 滑动到终点
sleep(0.5)  # 滑动过程
action_builder.pointer_action.pointer_up()  # 抬起
# 执行完整动作链
action_builder.perform()
sleep(3)
driver.quit()

效果
在这里插入图片描述


网站公告

今日签到

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