Poco API精讲之自定义手势start_gesture()
作者:互联网
上期回顾:Poco API精讲之缩放pinch()
以下基于
python3.8;airtestIDE1.2.13;airtest1.2.4;pocoui1.0.85
注意:Poco框架和Airtest框架很多API是同名的,但使用方法完全不一样!!!一定不要搞混了,我初学时也经常搞混,这点一定要注意!
具体Poco框架和Airtest框架是什么关系,可以看之前文章:Airtest Project——UI自动化利器介绍
今天来讲Poco的自定义手势start_gesture(),大家不要和Airtest框架的Android自定义手势弄混了。
Airtest的Android自定义手势详情可以看之前的文章:Airtest API精讲之Android自定义手势
Poco的start_gesture()分两种,一种是基于UI对象的start_gesture()、一种是基于全局操作的start_gesture(),两种API汇总可以看之前的文章
Poco实例(全局操作) API汇总
Poco基于UI对象的start_gesture()
start_gesture()
滑动手势。可用于解锁等复杂手势操作。
返回:
PendingGestureAction实例
源码解析:
# 源码位置:your_python_path\site-packages\poco\proxy.py
def start_gesture(self):
return PendingGestureAction(self.poco, self)
其实这里start_gesture()只是包了个皮,他实际是返回了一个PendingGestureAction实例,手势操作也是由PendingGestureAction实现的。
PendingGestureAction源码:
# 源码位置:your_python_path\site-packages\poco\gesture.py
class PendingGestureAction(object):
def __init__(self, pocoobj, uiproxy_or_pos):
super(PendingGestureAction, self).__init__()
self.pocoobj = pocoobj
self.track = MotionTrack()
if isinstance(uiproxy_or_pos, (list, tuple)):
self.track.start(uiproxy_or_pos)
else:
self.track.start(uiproxy_or_pos.get_position())
def hold(self, t):
self.track.hold(t)
return self
def to(self, pos):
if isinstance(pos, (list, tuple)):
self.track.move(pos)
else:
uiobj = pos
self.track.move(uiobj.get_position())
return self
def up(self):
self.pocoobj.apply_motion_tracks([self.track])
PendingGestureAction类实例参数中,第1个参数是poco实例。
第2个参数可以是屏幕相对坐标或Poco UI对象实例,不过如果是UI对象的话,最终也是通过get_position()获取到屏幕相对坐标。
PendingGestureAction的hold()和to()方法都是对初始化时的MotionTrack类实例积攒手势轨迹坐标。其中to()方法参数支持传入屏幕相对坐标或Poco UI对象实例,不过如果是UI对象的话,最终也是通过get_position()获取到屏幕相对坐标。
__init__、hold()、to()分别调用了MotionTrack类的start()、hold()、move()方法,那我们就继续看下MotionTrack类的部分源码:
# 源码位置:your_python_path\site-packages\poco\utils\track.py
class MotionTrack(object):
def __init__(self, points=None, speed=0.4):
super(MotionTrack, self).__init__()
self.speed = speed
self.timestamp = 0
self.event_points = [] # [ts, (x, y), contact_id], timestamp as arrival time
if points:
for p in points:
self.move(p)
@property
def last_point(self):
if self.event_points:
return self.event_points[-1][1]
return None
def start(self, p):
return self.move(p)
def move(self, p):
if self.last_point:
dt = (Vec2(p) - Vec2(self.last_point)).length / self.speed
self.timestamp += dt
self.event_points.append([self.timestamp, p, 0])
return self
def hold(self, t):
self.timestamp += t
if self.event_points:
self.move(self.last_point)
return self
MotionTrack类就是用来生成滑动轨迹的,start()、hold()、move()方法最终都是把手势滑动的节点坐标计算出来放在了event_points列表。最终滑动时也是根据这个坐标列表来执行的。
我们回过头接着看PendingGestureAction的最后一个方法up(),实际是调用poco实例的apply_motion_tracks(),并把之前的MotionTrack实例传入(记录着滑动坐标列表)。
最后就是按轨迹执行滑动,看下apply_motion_tracks()源码:
# 源码位置:your_python_path\site-packages\poco\pocofw.py
def apply_motion_tracks(self, tracks, accuracy=0.004):
if not tracks:
raise ValueError('Please provide at least one track. Got {}'.format(repr(tracks)))
tb = MotionTrackBatch(tracks)
return self.agent.input.applyMotionEvents(tb.discretize(accuracy))
这里最终还是调用的agent的input中的applyMotionEvents(),以UnityPoco为例,最终调用的也还是Airtest中的方法:
# 源码位置:your_python_path\site-packages\poco\utils\airtest\input.py
def applyMotionEvents(self, events):
if device_platform() != 'Android':
raise NotImplementedError
# Android minitouch/maxtouch only, currently
from airtest.core.android.touch_methods.base_touch import DownEvent, MoveEvent, UpEvent, SleepEvent
mes = []
for e in events:
t = e[0]
if t == 'd':
contact = e[2]
x, y = e[1]
pos = self.get_target_pos(x, y)
me = DownEvent(pos, contact)
elif t == 'm':
contact = e[2]
x, y = e[1]
pos = self.get_target_pos(x, y)
me = MoveEvent(pos, contact)
elif t == 'u':
contact = e[1]
me = UpEvent(contact)
elif t == 's':
how_long = e[1]
me = SleepEvent(how_long)
else:
raise ValueError('Unknown event type {}'.format(repr(t)))
mes.append(me)
current_device().touch_proxy.perform(mes, interval=0)
可以看到最后一行,最终执行的其实还是Airtest框架的perform()方法。
示例:
from airtest.core.api import *
from poco.drivers.unity3d import UnityPoco
auto_setup(__file__)
poco = UnityPoco()
ui1 = poco('测试工程师')
ui2 = poco('小站')
# 按住'测试工程师'1秒,滑到'小站',等待1秒,滑到屏幕中心,等待1秒,抬起
ui1.start_gesture().hold(1).to(ui2).hold(1).to([0.5,0.5]).hold(1).up()
Poco基于全局操作的start_gesture()
start_gesture(pos)
滑动手势。可用于解锁等复杂手势操作。
参数:
pos - 起点
返回:
PendingGestureAction实例
源码解析:
# 源码位置:your_python_path\site-packages\poco\pocofw.py
def start_gesture(self, pos):
return PendingGestureAction(self, pos)
全局操作的start_gesture()与UI对象的start_gesture()源码几乎一样,唯一不一样的就是全局操作的start_gesture()需要传入一个起始点的屏幕相对坐标。
示例:
from airtest.core.api import *
from poco.drivers.unity3d import UnityPoco
auto_setup(__file__)
poco = UnityPoco()
# 滑一个V形状
poco.start_gesture([0.5, 0.5]).hold(1).to([0.6, 0.6]).hold(1).to([0.7, 0.5]).up()
---------------------------------------------------------------------------------
关注微信公众号即可在手机上查阅,并可接收更多测试分享~
标签:自定义,poco,精讲,pos,start,源码,self,gesture 来源: https://www.cnblogs.com/songzhenhua/p/16339614.html