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;
严格来说,不能说成坐标,应该算坐标位移,因为才传入的参数其实坐标系的速度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; }
最后调用UiDevice.swipe和Swipe中是一样的啦。没什么特别的
特别想知道1250代表的是什么。不然老觉得还没理解这个方法的意思。哎
原文地址:http://blog.csdn.net/itfootball/article/details/37931445