以下內容在 夜神模擬器 上進行。
一、應用場景
一些針對手勢的操作,比如滑動、長按、拖動等。可以將這些基本手勢組合成一個相對復雜的手勢。
二、使用步驟
-
創建觸摸輸入設備(模擬手指操作)
touch_input = PointerInput(interaction.POINTER_TOUCH, "touch")
-
創建動作構建器
action_builder = ActionBuilder(driver, mouse=touch_input)
-
構建動作
-
用perform執行完整動作鏈
action_builder.perform()
三、PointerActions方法詳解
按住Ctrl+左鍵點擊pointer_action
,再從跳轉文件Ctrl+左鍵點擊PointerActions
,跳轉PointerActions類查看其方法詳細內容
作用:將指針(如手指)移動到屏幕指定坐標(x, y),x:目標位置的 X 坐標(相對于屏幕左上角,單位像素)
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(button=MouseButton.LEFT)
支持基于元素或坐標的移動,還可通過參數控制移動過程中的觸摸細節(如壓力、角度等):
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,
)
-
基于元素的移動
以元素為基準,通過 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 )
-
基于絕對坐標的移動
action.pointer_action.move_to(x=500, y=300)
-
結合按下 / 抬起實現滑動
移動過程中保持按下狀態,實現滑動效果:# 從元素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()
是實現連續、精細手勢的核心方法,尤其適合需要模擬人手自然滑動的場景(如滾動列表、拖拽控件等):
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,
)
- 基礎相對移動
# 假設指針當前在(100, 200)位置
action.pointer_action.move_by(x=200, y=100) # 向右移動200px,向下移動100px→新位置(300, 300)
- 按下并連續滑動
按下并連續滑動(分兩步向上移動):
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() # 抬起(結束滑動)
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) # 直接定位到絕對坐標
直接對元素或指定坐標位置執行點擊:
action.pointer_action.click(element) # 直接點擊元素
若未傳入 element
,需先通過 move_to_location()
定位到坐標,再調用 click()
。
模擬上下文點擊(通常指鼠標右鍵點擊),主要用于觸發元素的上下文菜單(如桌面端網頁或應用中右鍵點擊元素彈出的菜單)。在移動設備上,此方法通常等效于長按操作(因為移動設備無鼠標右鍵,長按是觸發上下文菜單的常見方式)。
常用于拖拽、長按觸發菜單等需要持續按壓的場景:
# 拖拽流程:按住→移動→抬起
action.pointer_action.click_and_hold(element=app_icon) # 按住圖標
action.pointer_action.move_by(x=200, y=300) # 向右下方移動
action.pointer_action.release() # 抬起(釋放圖標)
用于結束之前通過 click_and_hold()
、pointer_down()
等方法開始的 “按下” 狀態,與 pointer_up
功能基本一致。
double_click(el可選)
,若無element,則需先定位到目標坐標,再執行雙擊:
# 定位圖片元素并雙擊(如放大圖片)
image = driver.find_element('xpath', '//android.widget.ImageView[@index="0"]')
action.pointer_action.double_click(element=image) # 雙擊圖片
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()
效果: