ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# Flick ~~~ package io.appium.android.bootstrap.handler; import com.android.uiautomator.core.UiDevice; import io.appium.android.bootstrap.*; import io.appium.android.bootstrap.exceptions.InvalidCoordinatesException; import io.appium.android.bootstrap.utils.Point; import org.json.JSONException; import java.util.Hashtable; /** * This handler is used to flick elements in the Android UI. * * Based on the element Id, flick that element. * */ public class Flick extends CommandHandler { private Point calculateEndPoint(final Point start, final Integer xSpeed, final Integer ySpeed) { final UiDevice d = UiDevice.getInstance(); final Point end = new Point(); final double speedRatio = (double) xSpeed / ySpeed; double xOff; double yOff; final double value = Math.min(d.getDisplayHeight(), d.getDisplayWidth()); if (speedRatio < 1) { yOff = value / 4; xOff = value / 4 * speedRatio; } else { xOff = value / 4; yOff = value / 4 / speedRatio; } xOff = Integer.signum(xSpeed) * xOff; yOff = Integer.signum(ySpeed) * yOff; end.x = start.x + xOff; end.y = start.y + yOff; return end; } /* * @param command The {@link AndroidCommand} used for this handler. * * @return {@link AndroidCommandResult} * * @throws JSONException * * @see io.appium.android.bootstrap.CommandHandler#execute(io.appium.android. * bootstrap.AndroidCommand) */ @Override public AndroidCommandResult execute(final AndroidCommand command) throws JSONException { Point start = new Point(0.5, 0.5); Point end = new Point(); Double steps; final Hashtable<String, Object> params = command.params(); final UiDevice d = UiDevice.getInstance(); if (command.isElementCommand()) { AndroidElement el; try { el = command.getElement(); start = el.getAbsolutePosition(start); final Integer xoffset = (Integer) params.get("xoffset"); final Integer yoffset = (Integer) params.get("yoffset"); final Integer speed = (Integer) params.get("speed"); steps = 1250.0 / speed + 1; end.x = start.x + xoffset; end.y = start.y + yoffset; } catch (final Exception e) { return getErrorResult(e.getMessage()); } } else { try { final Integer xSpeed = (Integer) params.get("xSpeed"); final Integer ySpeed = (Integer) params.get("ySpeed"); final Double speed = Math.min(1250.0, Math.sqrt(xSpeed * xSpeed + ySpeed * ySpeed)); steps = 1250.0 / speed + 1; start = getDeviceAbsPos(start); end = calculateEndPoint(start, xSpeed, ySpeed); } catch (final InvalidCoordinatesException e) { return getErrorResult(e.getMessage()); } } steps = Math.abs(steps); Logger.debug("Flicking from " + start.toString() + " to " + end.toString() + " with steps: " + steps.intValue()); final boolean res = d.swipe(start.x.intValue(), start.y.intValue(), end.x.intValue(), end.y.intValue(), steps.intValue()); if (res) { return getSuccessResult(res); } else { return getErrorResult("Flick did not complete successfully"); } } } ~~~ 代码的步骤和swipe类似,而且最终调用的也是UiDevice.swipe方法,那么我们来看看到底区别在什么地方。首先它也分控件和坐标,分别分析: # 控件 首先将控件的中心点作为起始坐标,然后根据提供的参数xoffset和yoffset来获取位移数据,speed参数用来计算步骤。 ~~~ steps = 1250.0 / speed + 1; end.x = start.x + xoffset; end.y = start.y + yoffset; ~~~ 起始坐标加上位移就是结束坐标,这个steps的设置还是有点让人摸不着头脑的,我这个1250我且认为是最大位移吧,speed代表每一步走的路程。用1250/speed得到使用多少步到结束点,再加上初始值的那个点就得到steps的值啦。至此起始点坐标、结束点坐标、步骤的值都设置完毕。 # 坐标 严格来说,不能说成坐标,应该算坐标位移,因为才传入的参数其实坐标系的速度xSpeed和ySpeed。x轴移动xSpeed距离,y轴移动ySpeed坐标。然后获取坐标值和steps值。 其中它用1250和位移的平方做了一次比较,取出最小值来计算steps。起始坐标点定位屏幕的中心点坐标。然后再调用end = calculateEndPoint(start, xSpeed, ySpeed);方法获取结束点坐标。 ~~~ private Point calculateEndPoint(final Point start, final Integer xSpeed, final Integer ySpeed) { final UiDevice d = UiDevice.getInstance(); final Point end = new Point(); final double speedRatio = (double) xSpeed / ySpeed; double xOff; double yOff; final double value = Math.min(d.getDisplayHeight(), d.getDisplayWidth()); if (speedRatio < 1) { yOff = value / 4; xOff = value / 4 * speedRatio; } else { xOff = value / 4; yOff = value / 4 / speedRatio; } xOff = Integer.signum(xSpeed) * xOff; yOff = Integer.signum(ySpeed) * yOff; end.x = start.x + xOff; end.y = start.y + yOff; return end; } ~~~ 首先计算位移比speedRatio(x的位移/y的位移),然后获取屏幕宽和高中最小的一个数复制给value.如果speedRatio 最后调用UiDevice.swipe和Swipe中是一样的啦。没什么特别的 # 总结 特别想知道1250代表的是什么。不然老觉得还没理解这个方法的意思。哎