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

一、应用场景

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

二、使用步骤

  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()

效果
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/93878.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/93878.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/93878.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java HTTPS 请求失败排查与证书导入全过程

文章目录Java HTTPS 请求失败排查与证书导入全过程问题背景问题初步分析排查过程查看目标地址证书导入证书验证证书是否导入成功重启应用进一步验证:是否真的是证书问题?1. 浏览器访问2. 抓包工具验证(如 Charles、Wireshark)补充…

android APT技术

1,背景 对于注解的使用,想必大家都不陌生,它出现在我们的源码中,以及大部分框架中,比如ButterKnife、Arouter、Retrofit,但它们是有区别的,其中前2个是编译时注解,最后一个是运行时注…

MySQL 和 PostgreSQL综合比对分析汇总

面对大数据项目或其它类型项目中,面对关系型数据库选择一直是很总要的一点,本文针对MySQL 和 PostgreSQL进行综合比对分析汇总,内容仅供参考。MySQL 和 PostgreSQL 是两款主流的开源关系型数据库(RDBMS),但…

Linux---make和makefile

一、基本概念1.是什么make是一条命令,makefile是一个文件2.对应在vs中按一下f5就能运行代码,在Linux中make就相当于f5,使用makefile来封装从而实现我, 想要的功能3.使用①创建makefile文件②编辑makefile解释:test.exe…

【DAB收音机】DAB收音机协议及其他资料汇总

目录[ETSI DAB标准协议文档](https://www.etsi.org/standards)Other DAB资料DAB收音机相关的专利DAB收音机相关的期刊及学位论文DAB开源项目代码仓库qt-dab工具welle.io工具dablin工具【eti广播工具】⚙️ 项目对比与选型建议Other 收音机资料Other资料ETSI DAB标准协议文档 官…

RabbitMQ的特点和消息可靠性保障

掌握RabbitMQ的核心知识,需从其特点和消息可靠性保障(尤其是消息丢失解决方案)两方面入手,以下是详细说明: 一、RabbitMQ的核心特点 RabbitMQ是基于AMQP(Advanced Message Queuing Protocol)协议…

项目升级啦

公司要新做一个医疗行业的业务,经过业务端和产品端的评估该业务与公司已有的产品线关联不大,用户后续也不想在老系统那台老爷车上继续使用,话说老系统到现在差不多10年了,中间经历过的前后端开发者形形色色,维护者换了…

Android中页面生命周期变化

一、Activity切换的生命周期变化(A启动B)1. 标准流程(B完全覆盖A)完整生命周期路径:Activity A:onPause():失去焦点,仍部分可见onStop():完全不可见(当B完全覆…

自动驾驶控制算法——PID算法

自动驾驶控制算法——PID算法 文章目录自动驾驶控制算法——PID算法一、PID 是什么?二、PID 原理2.1 **比例环节(P)**2.2 **积分环节(I)**2.3 **微分环节(D)**2.4 特点总结2.5 案例分析 —— 小…

Spring Boot 异步执行方式全解析:@Async、CompletableFuture 与 TaskExecutor 对比

在 Spring Boot 开发中,异步执行是提升系统性能的重要手段,尤其适用于处理耗时操作(如日志记录、邮件发送、数据同步等)。本文将深入对比 Spring Boot 中三种主流的异步实现方式 ——Async注解、手动CompletableFuture和直接使用T…

高效微调2:Prompt-Tuning原理与实战

高效微调2:Prompt-Tuning原理与实战 Prompt-Tuning原理介绍 代码 Prompt-Tuning原理介绍 Prompt-Tuning Prompt-Tuning的思想:冻结主模型全部参数,在训练数据前加入一小段Prompt,只训练Prompt的表示层,即一个Embedding模块。其中,Prompt.又存在两种形式,一种是hard promp…

使用BART模型和T5模型实现文本改写

BART模型BART(Bidirectional and Auto-Regressive Transformers)是由 Facebook AI Research(FAIR)在 2019 年提出的序列到序列(seq2seq)预训练模型,论文发表于《BART: Denoising Sequence-to-Se…

电商前端Nginx访问日志收集分析实战

使用FileBeatLogstashES实现分布式日志收集 在大型项目中 ,往往服务都是分布在非常多不同的机器上 ,每个机器都会打印自己的log日志 但是 ,这样分散的日志 ,本来就无法进行整体分析。再加上微服务的负载均衡体系 ,甚至…

TwinCAT3示例项目1

目录一、需求分析二、程序编写1.实现1盏灯的自控(IF、TOF)2. 添加模式控制(Case、枚举)3. 添加多盏灯(FOR、数组)4. 添加多组灯(二维数组)END项目结合了,FB,I…

如何在 VMware Workstation 虚拟机中利用 Nvidia 显卡的硬件加速功能

这篇文章详细介绍了如何在 VMware Workstation 虚拟机中利用 Nvidia 显卡的硬件加速功能,通过 PCI 设备直通(Pass-Through)技术将显卡分配给虚拟机使用: 在 VMware Workstation 虚拟机中利用 Nvidia 显卡的硬件加速功能 1. 检查…

设计模式(二十二)行为型:策略模式详解

设计模式(二十二)行为型:策略模式详解策略模式(Strategy Pattern)是 GoF 23 种设计模式中最具实用性和广泛影响力的行为型模式之一,其核心价值在于定义一系列算法或行为,并将每个算法封装到独立…

AI+向量化

要理解 Java 如何结合 AI 与向量化,我们需要从向量化的核心概念、AI 中向量化的作用、Java 生态中的实现工具以及具体实践案例四个维度展开。以下是详细解析:一、核心概念:向量化与 AI 的关系向量化(Vectorization)是将…

Bootstap Vue 之b-form-radio-group 不显示选中状态问题

代码类似&#xff1a;<b-form-radio-groupclass"mt-2"required:disabled"dfrmDisabled"v-model"childDikeForm.SafetyAppraisalRank":options"[一, 二, 三, 四]"name"rankradioopt"></b-form-radio-group>经过测…

Shell 脚本实战:基于 for 循环的批量操作三例(账户创建、网络检测与密码管理)

一、编写脚本for1.sh,使用for循环创建20账户&#xff0c;账户名前缀由用户从键盘输入&#xff0c;账户初始密码由用户输入&#xff0c;例如:test1、test2、test3、......、test10实现思路通过read命令获取用户输入的账户前缀和初始密码&#xff1b;加入非空校验&#xff1a;若前…

PBR技术

一 、PBR的概述1.定义策略路由&#xff1a; PBR 是一种覆盖路由器默认路由决策机制的技术。它允许管理员根据策略&#xff08;而不仅仅是目标地址&#xff09;来设置数据包的下一跳 IP 地址、出站接口、IP 优先级/DSCP 值等。路由策略&#xff1a;是指在路由器或三层设备上&…