UiScrollable.java revision 3d50587be8ff021369c90554d814839335b445b0
1e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/* 2e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Copyright (C) 2012 The Android Open Source Project 3e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 4e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License"); 5e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * you may not use this file except in compliance with the License. 6e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * You may obtain a copy of the License at 7e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 8e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * http://www.apache.org/licenses/LICENSE-2.0 9e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 10e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Unless required by applicable law or agreed to in writing, software 11e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS, 12e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See the License for the specific language governing permissions and 14e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * limitations under the License. 15e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 16e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupackage com.android.uiautomator.core; 17e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 18e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.graphics.Rect; 19e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.util.Log; 20e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.view.accessibility.AccessibilityNodeInfo; 21e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 22e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/** 233d50587be8ff021369c90554d814839335b445b0Adam Momtaz * UiScrollable is a {@link UiCollection} and provides support for searching for items in a 243d50587be8ff021369c90554d814839335b445b0Adam Momtaz * scrollable UI elements. Used with horizontally or vertically scrollable UI. 25e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 26e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupublic class UiScrollable extends UiCollection { 27e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String LOG_TAG = UiScrollable.class.getSimpleName(); 28e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 29e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // More steps slows the swipe and prevents contents from being flung too far 30e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final int SCROLL_STEPS = 55; 31e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 32e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final int FLING_STEPS = 5; 33e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 34e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Restrict a swipe's starting and ending points inside a 10% margin of the target 35e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final double DEFAULT_SWIPE_DEADZONE_PCT = 0.1; 36e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 37e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Limits the number of swipes/scrolls performed during a search 38e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static int mMaxSearchSwipes = 30; 39e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 40e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Used in ScrollForward() and ScrollBackward() to determine swipe direction 41e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected boolean mIsVerticalList = true; 42e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 43e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private double mSwipeDeadZonePercentage = DEFAULT_SWIPE_DEADZONE_PCT; 44e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 45e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 463d50587be8ff021369c90554d814839335b445b0Adam Momtaz * UiScrollable is a {@link UiCollection} and as such requires a {@link UiSelector} to 473d50587be8ff021369c90554d814839335b445b0Adam Momtaz * identify the container UI element of the scrollable collection. Further operations on 483d50587be8ff021369c90554d814839335b445b0Adam Momtaz * the items in the container will require specifying UiSelector as an item selector. 493d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 504ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * @param container a {@link UiSelector} selector 51e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 524ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiScrollable(UiSelector container) { 53e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // wrap the container selector with container so that QueryController can handle 54e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // this type of enumeration search accordingly 55e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu super(container); 56e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 57e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 58e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 59e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Set the direction of swipes when performing scroll search 60e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 61e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void setAsVerticalList() { 62e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mIsVerticalList = true; 63e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 64e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 65e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 66e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Set the direction of swipes when performing scroll search 67e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 68e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void setAsHorizontalList() { 69e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mIsVerticalList = false; 70e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 71e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 72e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 73e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Used privately when performing swipe searches to decide if an element has become 74e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * visible or not. 753d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 76e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param selector 77e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if found else false 78e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 794ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz protected boolean exists(UiSelector selector) { 80e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(getQueryController().findAccessibilityNodeInfo(selector) != null) { 81e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return true; 82e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 83e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 84e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 85e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 86e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 874ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * Searches for child UI element within the constraints of this UiScrollable {@link UiSelector} 883d50587be8ff021369c90554d814839335b445b0Adam Momtaz * container. It looks for any child matching the <code>childPattern</code> argument within its 893d50587be8ff021369c90554d814839335b445b0Adam Momtaz * hierarchy with a matching content-description text. The returned UiObject will represent the 903d50587be8ff021369c90554d814839335b445b0Adam Momtaz * UI element matching the <code>childPattern</code> and not the sub element that matched the 913d50587be8ff021369c90554d814839335b445b0Adam Momtaz * content description.</p> 923d50587be8ff021369c90554d814839335b445b0Adam Momtaz * By default this operation will perform scroll search while attempting to find the UI element 934ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * See {@link #getChildByDescription(UiSelector, String, boolean)} 943d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 954ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * @param childPattern {@link UiSelector} selector of the child pattern to match and return 96e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text String of the identifying child contents of of the <code>childPattern</code> 97e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link UiObject} pointing at and instance of <code>childPattern</code> 98e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 99e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 100e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 1014ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiObject getChildByDescription(UiSelector childPattern, String text) 102e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throws UiObjectNotFoundException { 103e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getChildByDescription(childPattern, text, true); 104e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 105e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 106e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1073d50587be8ff021369c90554d814839335b445b0Adam Momtaz * See {@link #getChildByDescription(UiSelector, String)} 1083d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 1094ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * @param childPattern {@link UiSelector} selector of the child pattern to match and return 110e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text String may be a partial match for the content-description of a child element. 111e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param allowScrollSearch set to true if scrolling is allowed 112e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link UiObject} pointing at and instance of <code>childPattern</code> 113e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 114e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 1154ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiObject getChildByDescription(UiSelector childPattern, String text, 1164ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz boolean allowScrollSearch) throws UiObjectNotFoundException { 117e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (text != null) { 118e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (allowScrollSearch) { 1194ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz scrollIntoView(new UiSelector().descriptionContains(text)); 120e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 121e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return super.getChildByDescription(childPattern, text); 122e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 123e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException("for description= \"" + text + "\""); 124e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 125e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 126e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1274ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * Searches for child UI element within the constraints of this UiScrollable {@link UiSelector} 128e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * selector. It looks for any child matching the <code>childPattern</code> argument and 129e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * return the <code>instance</code> specified. The operation is performed only on the visible 130e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * items and no scrolling is performed in this case. 1313d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 1324ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * @param childPattern {@link UiSelector} selector of the child pattern to match and return 133e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param instance int the desired matched instance of this <code>childPattern</code> 134e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link UiObject} pointing at and instance of <code>childPattern</code> 135e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 136e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 1374ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiObject getChildByInstance(UiSelector childPattern, int instance) 138e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throws UiObjectNotFoundException { 1394ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz UiSelector patternSelector = UiSelector.patternBuilder(getSelector(), 1404ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz UiSelector.patternBuilder(childPattern).instance(instance)); 141e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return new UiObject(patternSelector); 142e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 143e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 144e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1454ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * Searches for child UI element within the constraints of this UiScrollable {@link UiSelector} 1463d50587be8ff021369c90554d814839335b445b0Adam Momtaz * container. It looks for any child matching the <code>childPattern</code> argument that has 1473d50587be8ff021369c90554d814839335b445b0Adam Momtaz * a sub UI element anywhere within its sub hierarchy that has text attribute 148e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <code>text</code>. The returned UiObject will point at the <code>childPattern</code> 1493d50587be8ff021369c90554d814839335b445b0Adam Momtaz * instance that matched the search and not at the text matched sub element</p> 150e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * By default this operation will perform scroll search while attempting to find the UI 151e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * element. 1524ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * See {@link #getChildByText(UiSelector, String, boolean)} 1533d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 1544ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * @param childPattern {@link UiSelector} selector of the child pattern to match and return 155e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text String of the identifying child contents of of the <code>childPattern</code> 156e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link UiObject} pointing at and instance of <code>childPattern</code> 157e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 158e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 159e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 1604ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiObject getChildByText(UiSelector childPattern, String text) 161e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throws UiObjectNotFoundException { 162e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getChildByText(childPattern, text, true); 163e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 164e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 165e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1663d50587be8ff021369c90554d814839335b445b0Adam Momtaz * See {@link #getChildByText(UiSelector, String)} 1673d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 1684ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * @param childPattern {@link UiSelector} selector of the child pattern to match and return 169e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text String of the identifying child contents of of the <code>childPattern</code> 170e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param allowScrollSearch set to true if scrolling is allowed 171e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link UiObject} pointing at and instance of <code>childPattern</code> 172e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 173e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 1744ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiObject getChildByText(UiSelector childPattern, String text, boolean allowScrollSearch) 175e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throws UiObjectNotFoundException { 176e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 177e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (text != null) { 178e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (allowScrollSearch) { 1794ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz scrollIntoView(new UiSelector().text(text)); 180e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 181e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return super.getChildByText(childPattern, text); 182e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 183e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException("for text= \"" + text + "\""); 184e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 185e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 186e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1873d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Performs a swipe Up on the UI element until the requested content-description 1883d50587be8ff021369c90554d814839335b445b0Adam Momtaz * is visible or until swipe attempts have been exhausted. See {@link #setMaxSearchSwipes(int)} 1893d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 190e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text to look for anywhere within the contents of this scrollable. 191e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if item us found else false 192e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 193e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollDescriptionIntoView(String text) { 1944ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return scrollIntoView(new UiSelector().description(text)); 195e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 196e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 197e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1984ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * Perform a scroll search for a UI element matching the {@link UiSelector} selector argument. 1993d50587be8ff021369c90554d814839335b445b0Adam Momtaz * See {@link #scrollDescriptionIntoView(String)} and {@link #scrollTextIntoView(String)}. 2003d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 2014ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * @param selector {@link UiSelector} selector 202e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if the item was found and now is in view else false 203e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 2044ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public boolean scrollIntoView(UiSelector selector) { 205e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // if we happen to be on top of the text we want then return here 206e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (exists(getSelector().childSelector(selector))) { 207e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return (true); 208e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 209e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // we will need to reset the search from the beginning to start search 210e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu scrollToBeginning(mMaxSearchSwipes); 211e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (exists(getSelector().childSelector(selector))) { 212e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return (true); 213e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 214e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu for (int x = 0; x < mMaxSearchSwipes; x++) { 215e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(!scrollForward()) { 216e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 217e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 218e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 219e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(exists(getSelector().childSelector(selector))) { 220e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return true; 221e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 222e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 223e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 224e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 225e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 226e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 227e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 2283d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Performs a swipe up on the UI element until the requested text is visible 2293d50587be8ff021369c90554d814839335b445b0Adam Momtaz * or until swipe attempts have been exhausted. See {@link #setMaxSearchSwipes(int)} 2303d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 231e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text to look for 232e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if item us found else false 233e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 234e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollTextIntoView(String text) { 2354ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return scrollIntoView(new UiSelector().text(text)); 236e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 237e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 238e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 239e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #getChildByDescription(String, boolean)} and {@link #getChildByText(String, boolean)} 240e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * use an arguments that specifies if scrolling is allowed while searching for the UI element. 241e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * The number of scrolls allowed to perform a search can be modified by this method. 242e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * The current value can be read by calling {@link #getMaxSearchSwipes()} 2433d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 2443d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param swipes is the number of search swipes until abort 245e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 246e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void setMaxSearchSwipes(int swipes) { 247e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mMaxSearchSwipes = swipes; 248e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 249e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 250e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 251e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #getChildByDescription(String, boolean)} and {@link #getChildByText(String, boolean)} 252e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * use an arguments that specifies if scrolling is allowed while searching for the UI element. 253e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * The number of scrolls currently allowed to perform a search can be read by this method. 254e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See {@link #setMaxSearchSwipes(int)} 2553d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 256e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return max value of the number of swipes currently allowed during a scroll search 257e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 258e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public int getMaxSearchSwipes() { 259e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return mMaxSearchSwipes; 260e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 261e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 262e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 263e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenience version of {@link UiScrollable#scrollForward(int)}, performs a fling 264e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 265e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 266e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 267e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean flingForward() { 268e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollForward(FLING_STEPS); 269e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 270e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 271e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 272e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenience version of {@link UiScrollable#scrollForward(int)}, performs a regular scroll 273e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 274e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 275e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 276e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollForward() { 277e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollForward(SCROLL_STEPS); 278e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 279e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 280e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 281e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Perform a scroll forward. If this list is set to vertical (see {@link #setAsVerticalList()} 282e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * default) then the swipes will be executed from the bottom to top. If this list is set 283e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * to horizontal (see {@link #setAsHorizontalList()}) then the swipes will be executed from 2843d50587be8ff021369c90554d814839335b445b0Adam Momtaz * the right to left. Caution is required on devices configured with right to left languages 2853d50587be8ff021369c90554d814839335b445b0Adam Momtaz * like Arabic and Hebrew. 286e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 287e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param steps use steps to control the speed, so that it may be a scroll, or fling 288e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 289e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 290e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollForward(int steps) { 291e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.d(LOG_TAG, "scrollForward() on selector = " + getSelector()); 292e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 293e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 294e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Object Not Found 295e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 296e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 297e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = new Rect();; 298e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu node.getBoundsInScreen(rect); 299e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 300e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int downX = 0; 301e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int downY = 0; 302e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int upX = 0; 303e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int upY = 0; 304e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 305e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scrolling is by default assumed vertically unless the object is explicitly 306e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // set otherwise by setAsHorizontalContainer() 307e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(mIsVerticalList) { 308e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int swipeAreaAdjust = (int)(rect.height() * getSwipeDeadZonePercentage()); 309e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scroll vertically: swipe down -> up 310e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downX = rect.centerX(); 311e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downY = rect.bottom - swipeAreaAdjust; 312e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upX = rect.centerX(); 313e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upY = rect.top + swipeAreaAdjust; 314e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 315e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int swipeAreaAdjust = (int)(rect.width() * getSwipeDeadZonePercentage()); 316e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scroll horizontally: swipe right -> left 317e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // TODO: Assuming device is not in right to left language 318e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downX = rect.right - swipeAreaAdjust; 319e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downY = rect.centerY(); 320e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upX = rect.left + swipeAreaAdjust; 321e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upY = rect.centerY(); 322e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 323e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().scrollSwipe(downX, downY, upX, upY, steps); 324e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 325e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 326e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 3273d50587be8ff021369c90554d814839335b445b0Adam Momtaz * See {@link UiScrollable#scrollBackward(int)} 328e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 329e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 330e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 331e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean flingBackward() { 332e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollBackward(FLING_STEPS); 333e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 334e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 335e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 3363d50587be8ff021369c90554d814839335b445b0Adam Momtaz * See {@link UiScrollable#scrollBackward(int)} 337e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 338e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 339e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 340e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollBackward() { 341e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollBackward(SCROLL_STEPS); 342e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 343e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 344e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 345e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Perform a scroll backward. If this list is set to vertical (see {@link #setAsVerticalList()} 346e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * default) then the swipes will be executed from the top to bottom. If this list is set 347e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * to horizontal (see {@link #setAsHorizontalList()}) then the swipes will be executed from 3483d50587be8ff021369c90554d814839335b445b0Adam Momtaz * the left to right. Caution is required on devices configured with right to left languages 3493d50587be8ff021369c90554d814839335b445b0Adam Momtaz * like Arabic and Hebrew. 350e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 351e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param steps use steps to control the speed, so that it may be a scroll, or fling 352e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 353e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 354e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollBackward(int steps) { 355e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.d(LOG_TAG, "scrollBackward() on selector = " + getSelector()); 356e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 357e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 358e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Object Not Found 359e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 360e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 361e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = new Rect();; 362e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu node.getBoundsInScreen(rect); 363e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 364e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int downX = 0; 365e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int downY = 0; 366e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int upX = 0; 367e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int upY = 0; 368e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 369e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scrolling is by default assumed vertically unless the object is explicitly 370e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // set otherwise by setAsHorizontalContainer() 371e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(mIsVerticalList) { 372e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int swipeAreaAdjust = (int)(rect.height() * getSwipeDeadZonePercentage()); 373e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.d(LOG_TAG, "scrollToBegining() using vertical scroll"); 374e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scroll vertically: swipe up -> down 375e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downX = rect.centerX(); 376e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downY = rect.top + swipeAreaAdjust; 377e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upX = rect.centerX(); 378e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upY = rect.bottom - swipeAreaAdjust; 379e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 380e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int swipeAreaAdjust = (int)(rect.width() * getSwipeDeadZonePercentage()); 381e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.d(LOG_TAG, "scrollToBegining() using hotizontal scroll"); 382e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scroll horizontally: swipe left -> right 383e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // TODO: Assuming device is not in right to left language 384e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downX = rect.left + swipeAreaAdjust; 385e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downY = rect.centerY(); 386e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upX = rect.right - swipeAreaAdjust; 387e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upY = rect.centerY(); 388e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 389e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().scrollSwipe(downX, downY, upX, upY, steps); 390e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 391e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 392e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 393e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Scrolls to the beginning of a scrollable UI element. The beginning could be the top most 3943d50587be8ff021369c90554d814839335b445b0Adam Momtaz * in case of vertical lists or the left most in case of horizontal lists. Caution is required 3953d50587be8ff021369c90554d814839335b445b0Adam Momtaz * on devices configured with right to left languages like Arabic and Hebrew. 396e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 397e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param steps use steps to control the speed, so that it may be a scroll, or fling 398e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on scrolled else false 399e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 400e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollToBeginning(int maxSwipes, int steps) { 401e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.d(LOG_TAG, "scrollToBeginning() on selector = " + getSelector()); 402e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // protect against potential hanging and return after preset attempts 403e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu for(int x = 0; x < maxSwipes; x++) { 404e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(!scrollBackward(steps)) { 405e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu break; 406e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 407e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 408e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return true; 409e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 410e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 411e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4123d50587be8ff021369c90554d814839335b445b0Adam Momtaz * See {@link UiScrollable#scrollToBeginning(int, int)} 413e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 414e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param maxSwipes 415e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on scrolled else false 416e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 417e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollToBeginning(int maxSwipes) { 418e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollToBeginning(maxSwipes, SCROLL_STEPS); 419e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 420e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 421e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4223d50587be8ff021369c90554d814839335b445b0Adam Momtaz * See {@link UiScrollable#scrollToBeginning(int, int)} 423e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 424e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param maxSwipes 425e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on scrolled else false 426e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 427e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean flingToBeginning(int maxSwipes) { 428e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollToBeginning(maxSwipes, FLING_STEPS); 429e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 430e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 431e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 432e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Scrolls to the end of a scrollable UI element. The end could be the bottom most 4333d50587be8ff021369c90554d814839335b445b0Adam Momtaz * in case of vertical controls or the right most for horizontal controls. Caution 4343d50587be8ff021369c90554d814839335b445b0Adam Momtaz * is required on devices configured with right to left languages like Arabic and Hebrew. 435e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 436e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param steps use steps to control the speed, so that it may be a scroll, or fling 437e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on scrolled else false 438e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 439e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollToEnd(int maxSwipes, int steps) { 440e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // protect against potential hanging and return after preset attempts 441e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu for(int x = 0; x < maxSwipes; x++) { 442e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(!scrollForward(steps)) { 443e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu break; 444e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 445e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 446e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return true; 447e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 448e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 449e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4503d50587be8ff021369c90554d814839335b445b0Adam Momtaz * See {@link UiScrollable#scrollToEnd(int, int) 451e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 452e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param maxSwipes 453e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on scrolled else false 454e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 455e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollToEnd(int maxSwipes) { 456e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollToEnd(maxSwipes, SCROLL_STEPS); 457e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 458e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 459e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4603d50587be8ff021369c90554d814839335b445b0Adam Momtaz * See {@link UiScrollable#scrollToEnd(int, int)} 461e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 462e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param maxSwipes 463e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on scrolled else false 464e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 465e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean flingToEnd(int maxSwipes) { 466e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollToEnd(maxSwipes, FLING_STEPS); 467e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 468e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 469e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public double getSwipeDeadZonePercentage() { 470e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return mSwipeDeadZonePercentage; 471e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 472e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 473e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void setSwipeDeadZonePercentage(double swipeDeadZonePercentage) { 474e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mSwipeDeadZonePercentage = swipeDeadZonePercentage; 475e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 476e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu} 477