UiScrollable.java revision 18b892c723e812a7e111f102d2b0c0782b116bb6
168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi/* 268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * Copyright (C) 2012 The Android Open Source Project 368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * 468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 568d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * you may not use this file except in compliance with the License. 668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * You may obtain a copy of the License at 768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * 868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * 1068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 1168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 1268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * See the License for the specific language governing permissions and 1468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * limitations under the License. 1568d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi */ 1668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivipackage com.android.uiautomator.core; 17de015407a89018f9422254624e1b75703f38defdGlenn Kasten 1868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Triviimport android.graphics.Rect; 1968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Triviimport android.util.Log; 204ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Triviimport android.view.accessibility.AccessibilityNodeInfo; 214ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi 2201e4a8ff63523bba5c8f919a72e0adb66daf4b98Mathias Agopian/** 2301e4a8ff63523bba5c8f919a72e0adb66daf4b98Mathias Agopian * UiScrollable is a {@link UiCollection} and provides support for searching 2468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * for items in scrollable layout elements. This class can be used with 254ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * horizontally or vertically scrollable controls. 260384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @since API Level 16 2768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi */ 284ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivipublic class UiScrollable extends UiCollection { 294ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi private static final String LOG_TAG = UiScrollable.class.getSimpleName(); 304ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi 314ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi // More steps slows the swipe and prevents contents from being flung too far 32833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten private static final int SCROLL_STEPS = 55; 33833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten 344ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi private static final int FLING_STEPS = 5; 354ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi 36833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten // Restrict a swipe's starting and ending points inside a 10% margin of the target 37833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten private static final double DEFAULT_SWIPE_DEADZONE_PCT = 0.1; 38833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten 39833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten // Limits the number of swipes/scrolls performed during a search 40833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten private static int mMaxSearchSwipes = 30; 41833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten 42833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten // Used in ScrollForward() and ScrollBackward() to determine swipe direction 43833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten private boolean mIsVerticalList = true; 44833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten 45833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten private double mSwipeDeadZonePercentage = DEFAULT_SWIPE_DEADZONE_PCT; 46833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten 47833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten /** 48833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten * Constructor. 4968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * 5037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi * @param container a {@link UiSelector} selector to identify the scrollable 5137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi * layout element. 5249935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * @since API Level 16 5368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi */ 54b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten public UiScrollable(UiSelector container) { 5568d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi // wrap the container selector with container so that QueryController can handle 5668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi // this type of enumeration search accordingly 5768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi super(container); 58b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten } 59b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten 6068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi /** 610384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * Set the direction of swipes to be vertical when performing scroll actions. 620384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @return reference to itself 63b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten * @since API Level 16 64b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten */ 650384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten public UiScrollable setAsVerticalList() { 660384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten Tracer.trace(); 670384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten mIsVerticalList = true; 680384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten return this; 690384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten } 700384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten 710384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten /** 720384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * Set the direction of swipes to be horizontal when performing scroll actions. 730384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @return reference to itself 740384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @since API Level 16 750384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten */ 760384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten public UiScrollable setAsHorizontalList() { 770384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten Tracer.trace(); 780384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten mIsVerticalList = false; 790384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten return this; 800384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten } 810384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten 820384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten /** 830384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * Used privately when performing swipe searches to decide if an element has become 840384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * visible or not. 850384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * 860384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @param selector 870384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @return true if found else false 880384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @since API Level 16 890384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten */ 900384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten protected boolean exists(UiSelector selector) { 910384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten if(getQueryController().findAccessibilityNodeInfo(selector) != null) { 920384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten return true; 930384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten } 940384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten return false; 950384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten } 960384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten 970384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten /** 980384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * Searches for a child element in the present scrollable container. 990384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * The search first looks for a child element that matches the selector 1000384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * you provided, then looks for the content-description in its children elements. 1010384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * If both search conditions are fulfilled, the method returns a {@ link UiObject} 1020384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * representing the element matching the selector (not the child element in its 1030384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * subhierarchy containing the content-description). By default, this method performs a 1040384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * scroll search. 1050384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * See {@link #getChildByDescription(UiSelector, String, boolean)} 1060384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * 1070384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @param childPattern {@link UiSelector} for a child in a scollable layout element 108b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten * @param text Content-description to find in the children of 109b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten * the <code>childPattern</code> match 110b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten * @return {@link UiObject} representing the child element that matches the search conditions 111b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten * @throws UiObjectNotFoundException 11268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * @since API Level 16 11368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi */ 11468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi @Override 11568d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi public UiObject getChildByDescription(UiSelector childPattern, String text) 1162f6d462d89356cdaa77299ca27b60c5cca198d98Gloria Wang throws UiObjectNotFoundException { 117b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten Tracer.trace(childPattern, text); 1180384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten return getChildByDescription(childPattern, text, true); 11968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi } 12091ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten 12191ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten /** 12291ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten * Searches for a child element in the present scrollable container. 12391ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten * The search first looks for a child element that matches the selector 12491ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten * you provided, then looks for the content-description in its children elements. 12591ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten * If both search conditions are fulfilled, the method returns a {@ link UiObject} 1260384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * representing the element matching the selector (not the child element in its 12737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi * subhierarchy containing the content-description). 12891ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten * 12991ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten * @param childPattern {@link UiSelector} for a child in a scollable layout element 1300d1c7e2ccd98bf7e2285c3db98ea263c79b24978Glenn Kasten * @param text Content-description to find in the children of 1310d1c7e2ccd98bf7e2285c3db98ea263c79b24978Glenn Kasten * the <code>childPattern</code> match (may be a partial match) 1320d1c7e2ccd98bf7e2285c3db98ea263c79b24978Glenn Kasten * @param allowScrollSearch set to true if scrolling is allowed 1330d1c7e2ccd98bf7e2285c3db98ea263c79b24978Glenn Kasten * @return {@link UiObject} representing the child element that matches the search conditions 1340d1c7e2ccd98bf7e2285c3db98ea263c79b24978Glenn Kasten * @throws UiObjectNotFoundException 1350d1c7e2ccd98bf7e2285c3db98ea263c79b24978Glenn Kasten * @since API Level 16 13691ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten */ 13737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi public UiObject getChildByDescription(UiSelector childPattern, String text, 13837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi boolean allowScrollSearch) throws UiObjectNotFoundException { 13937dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi Tracer.trace(childPattern, text, allowScrollSearch); 1404ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi if (text != null) { 1414ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi if (allowScrollSearch) { 14291ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten scrollIntoView(new UiSelector().descriptionContains(text)); 14391ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten } 14491ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten return super.getChildByDescription(childPattern, text); 14591ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten } 1460384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten throw new UiObjectNotFoundException("for description= \"" + text + "\""); 14791ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten } 1480384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten 1494ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi /** 1504ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * Searches for a child element in the present scrollable container that 1514ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * matches the selector you provided. The search is performed without 1524ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * scrolling and only on visible elements. 15391ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten * 1544ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @param childPattern {@link UiSelector} for a child in a scollable layout element 1554ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @param instance int number representing the occurance of 1564ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * a <code>childPattern</code> match 15791ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten * @return {@link UiObject} representing the child element that matches the search conditions 1584ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @since API Level 16 1594ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi */ 1604ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi @Override 1610384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten public UiObject getChildByInstance(UiSelector childPattern, int instance) 1620384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten throws UiObjectNotFoundException { 1630384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten Tracer.trace(childPattern, instance); 1640384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten UiSelector patternSelector = UiSelector.patternBuilder(getSelector(), 1650384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten UiSelector.patternBuilder(childPattern).instance(instance)); 1660384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten return new UiObject(patternSelector); 1670384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten } 1680384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten 1694ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi /** 1704ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * Searches for a child element in the present scrollable 17191ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten * container. The search first looks for a child element that matches the 17237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi * selector you provided, then looks for the text in its children elements. 17337dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi * If both search conditions are fulfilled, the method returns a {@ link UiObject} 17481e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten * representing the element matching the selector (not the child element in its 17591ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten * subhierarchy containing the text). By default, this method performs a 1760384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * scroll search. 1770384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * See {@link #getChildByText(UiSelector, String, boolean)} 17891ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten * 1790d1c7e2ccd98bf7e2285c3db98ea263c79b24978Glenn Kasten * @param childPattern {@link UiSelector} selector for a child in a scrollable layout element 1800d1c7e2ccd98bf7e2285c3db98ea263c79b24978Glenn Kasten * @param text String to find in the children of the <code>childPattern</code> match 1810d1c7e2ccd98bf7e2285c3db98ea263c79b24978Glenn Kasten * @return {@link UiObject} representing the child element that matches the search conditions 1820d1c7e2ccd98bf7e2285c3db98ea263c79b24978Glenn Kasten * @throws UiObjectNotFoundException 1835e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten * @since API Level 16 1845e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten */ 1850d1c7e2ccd98bf7e2285c3db98ea263c79b24978Glenn Kasten @Override 18691ff087fb814063f9faa23ab37a61e8fe4e38f45Glenn Kasten public UiObject getChildByText(UiSelector childPattern, String text) 18749935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten throws UiObjectNotFoundException { 18849935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten Tracer.trace(childPattern, text); 18981e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten return getChildByText(childPattern, text, true); 19081e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten } 1910384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten 1920384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten /** 19381e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten * Searches for a child element in the present scrollable container. The 1940384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * search first looks for a child element that matches the 1950384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * selector you provided, then looks for the text in its children elements. 1960384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * If both search conditions are fulfilled, the method returns a {@ link UiObject} 1970384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * representing the element matching the selector (not the child element in its 1980384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * subhierarchy containing the text). 1990384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * 2000384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @param childPattern {@link UiSelector} selector for a child in a scrollable layout element 2010384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @param text String to find in the children of the <code>childPattern</code> match 2020384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @param allowScrollSearch set to true if scrolling is allowed 2030384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @return {@link UiObject} representing the child element that matches the search conditions 2040384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @throws UiObjectNotFoundException 2050384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten * @since API Level 16 2060384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten */ 2070384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten public UiObject getChildByText(UiSelector childPattern, String text, boolean allowScrollSearch) 2080384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten throws UiObjectNotFoundException { 2090384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten Tracer.trace(childPattern, text, allowScrollSearch); 2100384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten if (text != null) { 2110384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten if (allowScrollSearch) { 21281e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten scrollIntoView(new UiSelector().text(text)); 21381e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten } 2140384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten return super.getChildByText(childPattern, text); 2150384250ce4221e4a6a16db2725e1232c71a60965Glenn Kasten } 21668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi throw new UiObjectNotFoundException("for text= \"" + text + "\""); 21781e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten } 21868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi 21968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi /** 22068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * Performs a forward scroll action on the scrollable layout element until 22149935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * the content-description is found, or until swipe attempts have been exhausted. 22249935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * See {@link #setMaxSearchSwipes(int)} 22349935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * 22449935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * @param text content-description to find within the contents of this scrollable layout element. 22549935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * @return true if item is found; else, false 22649935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * @since API Level 16 22749935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten */ 22849935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten public boolean scrollDescriptionIntoView(String text) throws UiObjectNotFoundException { 22949935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten Tracer.trace(text); 23068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi return scrollIntoView(new UiSelector().description(text)); 23149935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten } 23249935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten 23368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi /** 23468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * Perform a forward scroll action to move through the scrollable layout element until 23549935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * a visible item that matches the {@link UiObject} is found. 23649935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * 23749935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * @param obj {@link UiObject} 23868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * @return true if the item was found and now is in view else false 23968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * @since API Level 16 24068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi */ 24168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi public boolean scrollIntoView(UiObject obj) throws UiObjectNotFoundException { 24268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi Tracer.trace(obj.getSelector()); 24368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi return scrollIntoView(obj.getSelector()); 2447ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi } 245ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten 24668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi /** 247513222822545c3e954176476b263df52a47f43a4Glenn Kasten * Perform a scroll forward action to move through the scrollable layout 248513222822545c3e954176476b263df52a47f43a4Glenn Kasten * element until a visible item that matches the selector is found. 24968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * 250e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi * See {@link #scrollDescriptionIntoView(String)} and {@link #scrollTextIntoView(String)}. 25168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * 25268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * @param selector {@link UiSelector} selector 25368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * @return true if the item was found and now is in view; else, false 25468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * @since API Level 16 255e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi */ 2564b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi public boolean scrollIntoView(UiSelector selector) throws UiObjectNotFoundException { 2574b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi Tracer.trace(selector); 2584b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi // if we happen to be on top of the text we want then return here 259a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten UiSelector childSelector = getSelector().childSelector(selector); 260a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten if (exists(childSelector)) { 261a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten return (true); 262a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten } else { 263a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten // we will need to reset the search from the beginning to start search 264a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten scrollToBeginning(mMaxSearchSwipes); 2657c40d3b78c609b2a84acd0dd6e874ab24a73f8d7Glenn Kasten if (exists(childSelector)) { 2667c40d3b78c609b2a84acd0dd6e874ab24a73f8d7Glenn Kasten return (true); 267241b9c06493479dc632a8851097c193b724a2b41Andreas Huber } 268a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten for (int x = 0; x < mMaxSearchSwipes; x++) { 269a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten boolean scrolled = scrollForward(); 270a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten if(exists(childSelector)) { 271a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten return true; 272a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten } 273a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten if (!scrolled) { 274a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten return false; 275a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten } 276485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten } 2774b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi } 2784b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi return false; 27968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi } 2804b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi 2814b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi /** 2824b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * Scrolls forward until the UiObject is fully visible in the scrollable container. 2834b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * Use this method to make sure that the child item's edges are not offscreen. 2844b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * 2855933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten * @param childObject {@link UiObject} representing the child element 2864b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * @return true if the child element is already fully visible, or 2874b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * if the method scrolled successfully until the child became fully visible; 2884b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * otherwise, false if the attempt to scroll failed. 2894b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi * @throws UiObjectNotFoundException 2905933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten * @hide 291a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten */ 2925933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten public boolean ensureFullyVisible(UiObject childObject) throws UiObjectNotFoundException { 2935933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten Rect actual = childObject.getBounds(); 2945933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten Rect visible = childObject.getVisibleBounds(); 2954b0e0b2860ffd5e246b42c8a434833cca2f068b3Jean-Michel Trivi if (visible.width() * visible.height() == actual.width() * actual.height()) { 29668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi // area match, item fully visible 29768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi return true; 29868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi } 299ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten boolean shouldSwipeForward = false; 300b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten if (mIsVerticalList) { 30135ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten // if list is vertical, matching top edge implies obscured bottom edge 30235ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten // so we need to scroll list forward 30335ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten shouldSwipeForward = actual.top == visible.top; 30435ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten } else { 30535ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten // if list is horizontal, matching left edge implies obscured right edge, 30635ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten // so we need to scroll list forward 30735ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten shouldSwipeForward = actual.left == visible.left; 308ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten } 30968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi if (mIsVerticalList) { 31068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi if (shouldSwipeForward) { 31191145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi return swipeUp(10); 31291145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi } else { 31391145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi return swipeDown(10); 31491145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi } 31591145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi } else { 31691145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi if (shouldSwipeForward) { 31791145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi return swipeLeft(10); 31891145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi } else { 31991145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi return swipeRight(10); 32091145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi } 32191145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi } 32291145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi } 32391145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi 32491145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi /** 32570c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi * Performs a forward scroll action on the scrollable layout element until 32668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * the text you provided is visible, or until swipe attempts have been exhausted. 32768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * See {@link #setMaxSearchSwipes(int)} 3284ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * 32985edd878a30caa535b0267d8d6e61b4ccc0d5fd0Glenn Kasten * @param text test to look for 33068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * @return true if item is found; else, false 331e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi * @since API Level 16 33249935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten */ 33349935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten public boolean scrollTextIntoView(String text) throws UiObjectNotFoundException { 334ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten Tracer.trace(text); 335241b9c06493479dc632a8851097c193b724a2b41Andreas Huber return scrollIntoView(new UiSelector().text(text)); 336ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten } 337ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten 33868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi /** 33968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * Sets the maximum number of scrolls allowed when performing a 34049935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * scroll action in search of a child element. 34168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * See {@link #getChildByDescription(UiSelector, String)} and 34206059e5ee1eaf907589c7f8d1320253f92211348Glenn Kasten * {@link #getChildByText(UiSelector, String)}. 34306059e5ee1eaf907589c7f8d1320253f92211348Glenn Kasten * 34406059e5ee1eaf907589c7f8d1320253f92211348Glenn Kasten * @param swipes the number of search swipes to perform until giving up 34506059e5ee1eaf907589c7f8d1320253f92211348Glenn Kasten * @return reference to itself 34606059e5ee1eaf907589c7f8d1320253f92211348Glenn Kasten * @since API Level 16 34706059e5ee1eaf907589c7f8d1320253f92211348Glenn Kasten */ 34868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi public UiScrollable setMaxSearchSwipes(int swipes) { 34985edd878a30caa535b0267d8d6e61b4ccc0d5fd0Glenn Kasten Tracer.trace(swipes); 350e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi mMaxSearchSwipes = swipes; 35168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi return this; 35268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi } 3534ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi 35468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi /** 355e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi * Gets the maximum number of scrolls allowed when performing a 3565933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten * scroll action in search of a child element. 35768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * See {@link #getChildByDescription(UiSelector, String)} and 35868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * {@link #getChildByText(UiSelector, String)}. 3595933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten * 36068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * @return max the number of search swipes to perform until giving up 36168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * @since API Level 16 3624ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi */ 36368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi public int getMaxSearchSwipes() { 364e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi Tracer.trace(); 3655933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten return mMaxSearchSwipes; 36668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi } 36768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi 3685933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten /** 36937dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi * Performs a forward fling with the default number of fling steps (5). 37037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi * If the swipe direction is set to vertical, then the swipes will be 371f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten * performed from bottom to top. If the swipe 372f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten * direction is set to horizontal, then the swipes will be performed from 373f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten * right to left. Make sure to take into account devices configured with 374f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten * right-to-left languages like Arabic and Hebrew. 375f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten * 376f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten * @return true if scrolled, false if can't scroll anymore 377f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten * @since API Level 16 378f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten */ 379f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten public boolean flingForward() throws UiObjectNotFoundException { 380f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten Tracer.trace(); 381f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten return scrollForward(FLING_STEPS); 382f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten } 383f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten 384f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten /** 385f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten * Performs a forward scroll with the default number of scroll steps (55). 386f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten * If the swipe direction is set to vertical, 387f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten * then the swipes will be performed from bottom to top. If the swipe 388f6445d330c05ccc57d1adcc6ee05735a33f78881Glenn Kasten * direction is set to horizontal, then the swipes will be performed from 3897ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi * right to left. Make sure to take into account devices configured with 3907ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi * right-to-left languages like Arabic and Hebrew. 3917ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi * 3924ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @return true if scrolled, false if can't scroll anymore 3934ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @since API Level 16 3947ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi */ 3957ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi public boolean scrollForward() throws UiObjectNotFoundException { 3967ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi Tracer.trace(); 3977ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi return scrollForward(SCROLL_STEPS); 3987ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi } 399a9f22e6f5f53e90daa779e38b22f88e4faa35c95Glenn Kasten 400a9f22e6f5f53e90daa779e38b22f88e4faa35c95Glenn Kasten /** 401a9f22e6f5f53e90daa779e38b22f88e4faa35c95Glenn Kasten * Performs a forward scroll. If the swipe direction is set to vertical, 4027ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi * then the swipes will be performed from bottom to top. If the swipe 40349935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * direction is set to horizontal, then the swipes will be performed from 40449935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten * right to left. Make sure to take into account devices configured with 4057ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi * right-to-left languages like Arabic and Hebrew. 4064ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * 4074ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @param steps number of steps. Use this to control the speed of the scroll action 4084ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @return true if scrolled, false if can't scroll anymore 409c0a40f3efef1706f861777ff68003fe344730055Glenn Kasten * @since API Level 16 4107ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi */ 4117ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi public boolean scrollForward(int steps) throws UiObjectNotFoundException { 412a9f22e6f5f53e90daa779e38b22f88e4faa35c95Glenn Kasten Tracer.trace(steps); 413a9f22e6f5f53e90daa779e38b22f88e4faa35c95Glenn Kasten Log.d(LOG_TAG, "scrollForward() on selector = " + getSelector()); 414a9f22e6f5f53e90daa779e38b22f88e4faa35c95Glenn Kasten AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 415a9f22e6f5f53e90daa779e38b22f88e4faa35c95Glenn Kasten if(node == null) { 416a9f22e6f5f53e90daa779e38b22f88e4faa35c95Glenn Kasten throw new UiObjectNotFoundException(getSelector().toString()); 417a9f22e6f5f53e90daa779e38b22f88e4faa35c95Glenn Kasten } 4187ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi Rect rect = new Rect(); 4197ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi node.getBoundsInScreen(rect); 420e2e8fa36bd7448b59fbcdf141e0b6d21e5401d91Glenn Kasten 4214ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi int downX = 0; 4224ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi int downY = 0; 4234ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi int upX = 0; 4244ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi int upY = 0; 4254ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi 4264ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi // scrolling is by default assumed vertically unless the object is explicitly 4274ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi // set otherwise by setAsHorizontalContainer() 4284ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi if(mIsVerticalList) { 4294ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi int swipeAreaAdjust = (int)(rect.height() * getSwipeDeadZonePercentage()); 4304ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi // scroll vertically: swipe down -> up 4319f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten downX = rect.centerX(); 4329f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten downY = rect.bottom - swipeAreaAdjust; 4339f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten upX = rect.centerX(); 4349f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten upY = rect.top + swipeAreaAdjust; 4359f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten } else { 4369f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten int swipeAreaAdjust = (int)(rect.width() * getSwipeDeadZonePercentage()); 4379f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten // scroll horizontally: swipe right -> left 4389f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten // TODO: Assuming device is not in right to left language 4394ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi downX = rect.right - swipeAreaAdjust; 4404ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi downY = rect.centerY(); 4414ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi upX = rect.left + swipeAreaAdjust; 4424ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi upY = rect.centerY(); 4434ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi } 44437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi return getInteractionController().scrollSwipe(downX, downY, upX, upY, steps); 4454ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi } 4464ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi 447e2e8fa36bd7448b59fbcdf141e0b6d21e5401d91Glenn Kasten /** 448e2e8fa36bd7448b59fbcdf141e0b6d21e5401d91Glenn Kasten * Performs a backwards fling action with the default number of fling 449fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten * steps (5). If the swipe direction is set to vertical, 450fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten * then the swipe will be performed from top to bottom. If the swipe 45137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi * direction is set to horizontal, then the swipes will be performed from 4524ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * left to right. Make sure to take into account devices configured with 4534ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * right-to-left languages like Arabic and Hebrew. 4544ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * 4553610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * @return true if scrolled, and false if can't scroll anymore 4563610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * @since API Level 16 4573610785fa93586ce84a27a27530feb77b8035229Glenn Kasten */ 4583610785fa93586ce84a27a27530feb77b8035229Glenn Kasten public boolean flingBackward() throws UiObjectNotFoundException { 4593610785fa93586ce84a27a27530feb77b8035229Glenn Kasten Tracer.trace(); 4603610785fa93586ce84a27a27530feb77b8035229Glenn Kasten return scrollBackward(FLING_STEPS); 4613610785fa93586ce84a27a27530feb77b8035229Glenn Kasten } 4623610785fa93586ce84a27a27530feb77b8035229Glenn Kasten 4633610785fa93586ce84a27a27530feb77b8035229Glenn Kasten /** 4643610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * Performs a backward scroll with the default number of scroll steps (55). 4653610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * If the swipe direction is set to vertical, 4663610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * then the swipes will be performed from top to bottom. If the swipe 4673610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * direction is set to horizontal, then the swipes will be performed from 4683610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * left to right. Make sure to take into account devices configured with 4693610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * right-to-left languages like Arabic and Hebrew. 4703610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * 4713610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * @return true if scrolled, and false if can't scroll anymore 4723610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * @since API Level 16 4733610785fa93586ce84a27a27530feb77b8035229Glenn Kasten */ 4743610785fa93586ce84a27a27530feb77b8035229Glenn Kasten public boolean scrollBackward() throws UiObjectNotFoundException { 4753610785fa93586ce84a27a27530feb77b8035229Glenn Kasten Tracer.trace(); 4763610785fa93586ce84a27a27530feb77b8035229Glenn Kasten return scrollBackward(SCROLL_STEPS); 4773610785fa93586ce84a27a27530feb77b8035229Glenn Kasten } 4783610785fa93586ce84a27a27530feb77b8035229Glenn Kasten 4793610785fa93586ce84a27a27530feb77b8035229Glenn Kasten /** 4803610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * Performs a backward scroll. If the swipe direction is set to vertical, 4813610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * then the swipes will be performed from top to bottom. If the swipe 4823610785fa93586ce84a27a27530feb77b8035229Glenn Kasten * direction is set to horizontal, then the swipes will be performed from 4834ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * left to right. Make sure to take into account devices configured with 4844ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * right-to-left languages like Arabic and Hebrew. 4854ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * 4864ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @param steps number of steps. Use this to control the speed of the scroll action. 48768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * @return true if scrolled, false if can't scroll anymore 4884ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @since API Level 16 4894ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi */ 4904ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi public boolean scrollBackward(int steps) throws UiObjectNotFoundException { 4914ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi Tracer.trace(steps); 4924ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi Log.d(LOG_TAG, "scrollBackward() on selector = " + getSelector()); 4934ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 4944ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi if (node == null) { 4954ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi throw new UiObjectNotFoundException(getSelector().toString()); 4964ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi } 4974ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi Rect rect = new Rect(); 4984ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi node.getBoundsInScreen(rect); 4994ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi 5004ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi int downX = 0; 5014ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi int downY = 0; 5024ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi int upX = 0; 5034ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi int upY = 0; 5044ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi 5054ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi // scrolling is by default assumed vertically unless the object is explicitly 5064ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi // set otherwise by setAsHorizontalContainer() 5074ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi if(mIsVerticalList) { 5084ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi int swipeAreaAdjust = (int)(rect.height() * getSwipeDeadZonePercentage()); 5094ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi Log.d(LOG_TAG, "scrollToBegining() using vertical scroll"); 5104ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi // scroll vertically: swipe up -> down 5114ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi downX = rect.centerX(); 5124ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi downY = rect.top + swipeAreaAdjust; 5134ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi upX = rect.centerX(); 5144ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi upY = rect.bottom - swipeAreaAdjust; 5154ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi } else { 5164ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi int swipeAreaAdjust = (int)(rect.width() * getSwipeDeadZonePercentage()); 5174ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi Log.d(LOG_TAG, "scrollToBegining() using hotizontal scroll"); 5184ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi // scroll horizontally: swipe left -> right 5194ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi // TODO: Assuming device is not in right to left language 5204ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi downX = rect.left + swipeAreaAdjust; 5214ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi downY = rect.centerY(); 522b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten upX = rect.right - swipeAreaAdjust; 523b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten upY = rect.centerY(); 5244ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi } 5254ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi return getInteractionController().scrollSwipe(downX, downY, upX, upY, steps); 5264ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi } 5274ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi 5284ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi /** 5294ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * Scrolls to the beginning of a scrollable layout element. The beginning 53006059e5ee1eaf907589c7f8d1320253f92211348Glenn Kasten * can be at the top-most edge in the case of vertical controls, or the 531fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten * left-most edge for horizontal controls. Make sure to take into account 532fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten * devices configured with right-to-left languages like Arabic and Hebrew. 53306059e5ee1eaf907589c7f8d1320253f92211348Glenn Kasten * 5344ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @param steps use steps to control the speed, so that it may be a scroll, or fling 53506059e5ee1eaf907589c7f8d1320253f92211348Glenn Kasten * @return true on scrolled else false 53606059e5ee1eaf907589c7f8d1320253f92211348Glenn Kasten * @since API Level 16 537fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten */ 53806059e5ee1eaf907589c7f8d1320253f92211348Glenn Kasten public boolean scrollToBeginning(int maxSwipes, int steps) throws UiObjectNotFoundException { 5395933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten Tracer.trace(maxSwipes, steps); 5405933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten Log.d(LOG_TAG, "scrollToBeginning() on selector = " + getSelector()); 541a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten // protect against potential hanging and return after preset attempts 542a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten for(int x = 0; x < maxSwipes; x++) { 543a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten if(!scrollBackward(steps)) { 5445933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten break; 545fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten } 546b4393ef4ef3edb785746c37fd7b68950e85283aeGlenn Kasten } 547fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten return true; 548fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten } 549fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten 550b4393ef4ef3edb785746c37fd7b68950e85283aeGlenn Kasten /** 55199b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten * Scrolls to the beginning of a scrollable layout element. The beginning 55299b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten * can be at the top-most edge in the case of vertical controls, or the 553b4393ef4ef3edb785746c37fd7b68950e85283aeGlenn Kasten * left-most edge for horizontal controls. Make sure to take into account 55499b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten * devices configured with right-to-left languages like Arabic and Hebrew. 555b4393ef4ef3edb785746c37fd7b68950e85283aeGlenn Kasten * 55699b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten * @param maxSwipes 557b4393ef4ef3edb785746c37fd7b68950e85283aeGlenn Kasten * @return true on scrolled else false 55899b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten * @since API Level 16 559a6c69c7e1665b38da8d6784e65210acbe501b92cSteve Block */ 560fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten public boolean scrollToBeginning(int maxSwipes) throws UiObjectNotFoundException { 561fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten Tracer.trace(maxSwipes); 562fa2bd93c3a9852a1f879663eeff598d13cf8fa81Glenn Kasten return scrollToBeginning(maxSwipes, SCROLL_STEPS); 5634ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi } 5644ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi 5654ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi /** 5661fa5c3206d06bbebdea2dc92f378ce6b8a211e23Glenn Kasten * Performs a fling gesture to reach the beginning of a scrollable layout element. 5674ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * The beginning can be at the top-most edge in the case of vertical controls, or 5684ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * the left-most edge for horizontal controls. Make sure to take into 5694ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * account devices configured with right-to-left languages like Arabic and Hebrew. 5709f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten * 5719f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten * @param maxSwipes 5729f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten * @return true on scrolled else false 5739f07ea788f57654acf29d1321b40162e41eb122bGlenn Kasten * @since API Level 16 5744ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi */ 5754ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi public boolean flingToBeginning(int maxSwipes) throws UiObjectNotFoundException { 5764ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi Tracer.trace(maxSwipes); 5774ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi return scrollToBeginning(maxSwipes, FLING_STEPS); 578833251ab9e5e59a6ea5ac325122cf3abdf7cd944Glenn Kasten } 5794ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi 5804ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi /** 5814ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * Scrolls to the end of a scrollable layout element. The end can be at the 5824ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * bottom-most edge in the case of vertical controls, or the right-most edge for 5834ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * horizontal controls. Make sure to take into account devices configured with 5844ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * right-to-left languages like Arabic and Hebrew. 5854ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * 5864ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @param steps use steps to control the speed, so that it may be a scroll, or fling 5874ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @return true on scrolled else false 5884ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * @since API Level 16 5894ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi */ 5904ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi public boolean scrollToEnd(int maxSwipes, int steps) throws UiObjectNotFoundException { 5914ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi Tracer.trace(maxSwipes, steps); 59291145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi // protect against potential hanging and return after preset attempts 59391145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi for(int x = 0; x < maxSwipes; x++) { 59491145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi if(!scrollForward(steps)) { 59591145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi break; 59691145ef159d3e165a461cbd76341ff8ed3d72baeJean-Michel Trivi } 59768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi } 59868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi return true; 5995933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten } 6005933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten 6015933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten /** 602a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten * Scrolls to the end of a scrollable layout element. The end can be at the 6035933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten * bottom-most edge in the case of vertical controls, or the right-most edge for 604a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten * horizontal controls. Make sure to take into account devices configured with 605a0fa47f72f47fffb80ab2ae791739ce73de1e8f4Glenn Kasten * right-to-left languages like Arabic and Hebrew. 6065933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten * 6075933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten * @param maxSwipes 60868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * @return true on scrolled, else false 609 * @since API Level 16 610 */ 611 public boolean scrollToEnd(int maxSwipes) throws UiObjectNotFoundException { 612 Tracer.trace(maxSwipes); 613 return scrollToEnd(maxSwipes, SCROLL_STEPS); 614 } 615 616 /** 617 * Performs a fling gesture to reach the end of a scrollable layout element. 618 * The end can be at the bottom-most edge in the case of vertical controls, or 619 * the right-most edge for horizontal controls. Make sure to take into 620 * account devices configured with right-to-left languages like Arabic and Hebrew. 621 * 622 * @param maxSwipes 623 * @return true on scrolled, else false 624 * @since API Level 16 625 */ 626 public boolean flingToEnd(int maxSwipes) throws UiObjectNotFoundException { 627 Tracer.trace(maxSwipes); 628 return scrollToEnd(maxSwipes, FLING_STEPS); 629 } 630 631 /** 632 * Returns the percentage of a widget's size that's considered as a no-touch 633 * zone when swiping. The no-touch zone is set as a percentage of a widget's total 634 * width or height, denoting a margin around the swipable area of the widget. 635 * Swipes must start and end inside this margin. This is important when the 636 * widget being swiped may not respond to the swipe if started at a point 637 * too near to the edge. The default is 10% from either edge. 638 * 639 * @return a value between 0 and 1 640 * @since API Level 16 641 */ 642 public double getSwipeDeadZonePercentage() { 643 Tracer.trace(); 644 return mSwipeDeadZonePercentage; 645 } 646 647 /** 648 * Sets the percentage of a widget's size that's considered as no-touch 649 * zone when swiping. 650 * The no-touch zone is set as percentage of a widget's total width or height, 651 * denoting a margin around the swipable area of the widget. Swipes must 652 * always start and end inside this margin. This is important when the 653 * widget being swiped may not respond to the swipe if started at a point 654 * too near to the edge. The default is 10% from either edge. 655 * 656 * @param swipeDeadZonePercentage is a value between 0 and 1 657 * @return reference to itself 658 * @since API Level 16 659 */ 660 public UiScrollable setSwipeDeadZonePercentage(double swipeDeadZonePercentage) { 661 Tracer.trace(swipeDeadZonePercentage); 662 mSwipeDeadZonePercentage = swipeDeadZonePercentage; 663 return this; 664 } 665} 666