UiScrollable.java revision e54d649fb83a0a44516e5c25a9ac1992c8950e59
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/** 23e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * UiScrollable is a {@link UiCollection} however this class provides additional functionality 24e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * where the tests need to deal with scrollable contents or desire to enumerate lists of 25e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * items. This calls can perform automatic searches within a scrollable container. Whether 26e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * the content scrolls vertically or horizontally can be set by calling 27e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #setAsVerticalList()} which is the default, or {@link #setAsHorizontalList()}. 28e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 29e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupublic class UiScrollable extends UiCollection { 30e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String LOG_TAG = UiScrollable.class.getSimpleName(); 31e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 32e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // More steps slows the swipe and prevents contents from being flung too far 33e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final int SCROLL_STEPS = 55; 34e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 35e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final int FLING_STEPS = 5; 36e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 37e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Restrict a swipe's starting and ending points inside a 10% margin of the target 38e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final double DEFAULT_SWIPE_DEADZONE_PCT = 0.1; 39e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 40e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Limits the number of swipes/scrolls performed during a search 41e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static int mMaxSearchSwipes = 30; 42e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 43e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Used in ScrollForward() and ScrollBackward() to determine swipe direction 44e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected boolean mIsVerticalList = true; 45e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 46e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private double mSwipeDeadZonePercentage = DEFAULT_SWIPE_DEADZONE_PCT; 47e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 48e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 49e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * UiScrollable is a {@link UiCollection} and as such requires a {@link By} selector to identify 50e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * the UI element it represents. In the case of UiScrollable, the selector specified is 51e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * considered a container where further calls to enumerate or find children will be performed 52e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * in. 53e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param container a {@link By} selector 54e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 55e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public UiScrollable(By container) { 56e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // wrap the container selector with container so that QueryController can handle 57e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // this type of enumeration search accordingly 58e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu super(container); 59e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 60e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 61e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 62e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Set the direction of swipes when performing scroll search 63e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 64e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void setAsVerticalList() { 65e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mIsVerticalList = true; 66e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 67e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 68e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 69e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Set the direction of swipes when performing scroll search 70e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 71e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void setAsHorizontalList() { 72e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mIsVerticalList = false; 73e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 74e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 75e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 76e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Used privately when performing swipe searches to decide if an element has become 77e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * visible or not. 78e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param selector 79e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if found else false 80e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 81e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected boolean exists(By selector) { 82e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(getQueryController().findAccessibilityNodeInfo(selector) != null) { 83e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return true; 84e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 85e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 86e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 87e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 88e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 89e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Searches for child UI element within the constraints of this UiScrollable {@link By} 90e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * selector. It looks for any child matching the <code>childPattern</code> argument that has 91e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * a child UI element anywhere within its sub hierarchy that has content-description text. 92e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * The returned UiObject will point at the <code>childPattern</code> instance that matched the 93e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * search and not at the identifying child element that matched the content description.</p> 94e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * By default this operation will perform scroll search while attempting to find the 95e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * UI element. 96e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See {@link #getChildByDescription(By, String, boolean)} 97e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param childPattern {@link By} selector of the child pattern to match and return 98e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text String of the identifying child contents of of the <code>childPattern</code> 99e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link UiObject} pointing at and instance of <code>childPattern</code> 100e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 101e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 102e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 103e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public UiObject getChildByDescription(By childPattern, String text) 104e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throws UiObjectNotFoundException { 105e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getChildByDescription(childPattern, text, true); 106e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 107e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 108e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 109e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Searches for child UI element within the constraints of this UiScrollable {@link By} 110e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * selector. It looks for any child matching the <code>childPattern</code> argument that has 111e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * a child UI element anywhere within its sub hierarchy that has content-description text. 112e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * The returned UiObject will point at the <code>childPattern</code> instance that matched the 113e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * search and not at the identifying child element that matched the content description. 114e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param childPattern {@link By} selector of the child pattern to match and return 115e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text String may be a partial match for the content-description of a child element. 116e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param allowScrollSearch set to true if scrolling is allowed 117e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link UiObject} pointing at and instance of <code>childPattern</code> 118e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 119e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 120e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public UiObject getChildByDescription(By childPattern, String text, boolean allowScrollSearch) 121e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throws UiObjectNotFoundException { 122e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (text != null) { 123e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (allowScrollSearch) { 124e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu scrollIntoView(By.selector().descriptionContains(text)); 125e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 126e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return super.getChildByDescription(childPattern, text); 127e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 128e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException("for description= \"" + text + "\""); 129e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 130e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 131e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 132e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Searches for child UI element within the constraints of this UiScrollable {@link By} 133e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * selector. It looks for any child matching the <code>childPattern</code> argument and 134e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * return the <code>instance</code> specified. The operation is performed only on the visible 135e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * items and no scrolling is performed in this case. 136e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param childPattern {@link By} selector of the child pattern to match and return 137e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param instance int the desired matched instance of this <code>childPattern</code> 138e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link UiObject} pointing at and instance of <code>childPattern</code> 139e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 140e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 141e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public UiObject getChildByInstance(By childPattern, int instance) 142e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throws UiObjectNotFoundException { 143e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu By patternSelector = By.patternBuilder(getSelector(), 144e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu By.patternBuilder(childPattern).instance(instance)); 145e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return new UiObject(patternSelector); 146e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 147e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 148e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 149e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Searches for child UI element within the constraints of this UiScrollable {@link By} 150e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * selector. It looks for any child matching the <code>childPattern</code> argument that has 151e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * a child UI element anywhere within its sub hierarchy that has text attribute = 152e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <code>text</code>. The returned UiObject will point at the <code>childPattern</code> 153e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * instance that matched the search and not at the identifying child element that matched the 154e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * text attribute.</p> 155e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * By default this operation will perform scroll search while attempting to find the UI 156e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * element. 157e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See {@link #getChildByText(By, String, boolean)} 158e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param childPattern {@link By} selector of the child pattern to match and return 159e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text String of the identifying child contents of of the <code>childPattern</code> 160e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link UiObject} pointing at and instance of <code>childPattern</code> 161e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 162e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 163e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu @Override 164e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public UiObject getChildByText(By childPattern, String text) 165e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throws UiObjectNotFoundException { 166e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getChildByText(childPattern, text, true); 167e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 168e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 169e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 170e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Searches for child UI element within the constraints of this UiScrollable {@link By} 171e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * selector. It looks for any child matching the <code>childPattern</code> argument that has 172e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * a child UI element anywhere within its sub hierarchy that has the text attribute = 173e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <code>text</code>. 174e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * The returned UiObject will point at the <code>childPattern</code> instance that matched the 175e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * search and not at the identifying child element that matched the text attribute. 176e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param childPattern {@link By} selector of the child pattern to match and return 177e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text String of the identifying child contents of of the <code>childPattern</code> 178e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param allowScrollSearch set to true if scrolling is allowed 179e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link UiObject} pointing at and instance of <code>childPattern</code> 180e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 181e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 182e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public UiObject getChildByText(By childPattern, String text, boolean allowScrollSearch) 183e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throws UiObjectNotFoundException { 184e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 185e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (text != null) { 186e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (allowScrollSearch) { 187e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu scrollIntoView(By.selector().text(text)); 188e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 189e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return super.getChildByText(childPattern, text); 190e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 191e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException("for text= \"" + text + "\""); 192e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 193e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 194e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 195e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Performs a swipe Up on the associated UI element until the requested content-description 196e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * is found or until swipe attempts have been exhausted. See {@link #setMaxSearchSwipes(int)} 197e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text to look for anywhere within the contents of this scrollable. 198e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if item us found else false 199e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 200e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollDescriptionIntoView(String text) { 201e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollIntoView(By.selector().description(text)); 202e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 203e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 204e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 205e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Perform a scroll search for a UI element matching the {@link By} selector argument. Also 206e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * see {@link #scrollDescriptionIntoView(String)} and {@link #scrollTextIntoView(String)}. 207e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param selector {@link By} selector 208e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if the item was found and now is in view else false 209e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 210e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollIntoView(By selector) { 211e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // if we happen to be on top of the text we want then return here 212e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (exists(getSelector().childSelector(selector))) { 213e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return (true); 214e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 215e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // we will need to reset the search from the beginning to start search 216e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu scrollToBeginning(mMaxSearchSwipes); 217e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (exists(getSelector().childSelector(selector))) { 218e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return (true); 219e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 220e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu for (int x = 0; x < mMaxSearchSwipes; x++) { 221e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(!scrollForward()) { 222e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 223e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 224e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 225e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(exists(getSelector().childSelector(selector))) { 226e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return true; 227e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 228e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 229e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 230e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 231e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 232e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 233e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 234e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Performs a swipe up on the associated display element until the requested text 235e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * appears or until swipe attempts have been exhausted. See {@link #setMaxSearchSwipes(int)} 236e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param text to look for 237e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if item us found else false 238e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 239e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollTextIntoView(String text) { 240e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollIntoView(By.selector().text(text)); 241e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 242e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 243e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 244e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #getChildByDescription(String, boolean)} and {@link #getChildByText(String, boolean)} 245e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * use an arguments that specifies if scrolling is allowed while searching for the UI element. 246e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * The number of scrolls allowed to perform a search can be modified by this method. 247e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * The current value can be read by calling {@link #getMaxSearchSwipes()} 248e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param swipes 249e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 250e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void setMaxSearchSwipes(int swipes) { 251e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mMaxSearchSwipes = swipes; 252e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 253e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 254e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 255e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #getChildByDescription(String, boolean)} and {@link #getChildByText(String, boolean)} 256e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * use an arguments that specifies if scrolling is allowed while searching for the UI element. 257e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * The number of scrolls currently allowed to perform a search can be read by this method. 258e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See {@link #setMaxSearchSwipes(int)} 259e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return max value of the number of swipes currently allowed during a scroll search 260e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 261e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public int getMaxSearchSwipes() { 262e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return mMaxSearchSwipes; 263e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 264e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 265e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 266e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenience version of {@link UiScrollable#scrollForward(int)}, performs a fling 267e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 268e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 269e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 270e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean flingForward() { 271e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollForward(FLING_STEPS); 272e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 273e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 274e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 275e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenience version of {@link UiScrollable#scrollForward(int)}, performs a regular scroll 276e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 277e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 278e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 279e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollForward() { 280e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollForward(SCROLL_STEPS); 281e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 282e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 283e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 284e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Perform a scroll forward. If this list is set to vertical (see {@link #setAsVerticalList()} 285e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * default) then the swipes will be executed from the bottom to top. If this list is set 286e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * to horizontal (see {@link #setAsHorizontalList()}) then the swipes will be executed from 287e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * the right to left. 288e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 289e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param steps use steps to control the speed, so that it may be a scroll, or fling 290e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 291e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 292e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollForward(int steps) { 293e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.d(LOG_TAG, "scrollForward() on selector = " + getSelector()); 294e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 295e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 296e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Object Not Found 297e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 298e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 299e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = new Rect();; 300e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu node.getBoundsInScreen(rect); 301e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 302e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int downX = 0; 303e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int downY = 0; 304e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int upX = 0; 305e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int upY = 0; 306e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 307e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scrolling is by default assumed vertically unless the object is explicitly 308e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // set otherwise by setAsHorizontalContainer() 309e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(mIsVerticalList) { 310e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int swipeAreaAdjust = (int)(rect.height() * getSwipeDeadZonePercentage()); 311e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scroll vertically: swipe down -> up 312e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downX = rect.centerX(); 313e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downY = rect.bottom - swipeAreaAdjust; 314e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upX = rect.centerX(); 315e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upY = rect.top + swipeAreaAdjust; 316e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 317e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int swipeAreaAdjust = (int)(rect.width() * getSwipeDeadZonePercentage()); 318e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scroll horizontally: swipe right -> left 319e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // TODO: Assuming device is not in right to left language 320e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downX = rect.right - swipeAreaAdjust; 321e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downY = rect.centerY(); 322e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upX = rect.left + swipeAreaAdjust; 323e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upY = rect.centerY(); 324e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 325e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().scrollSwipe(downX, downY, upX, upY, steps); 326e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 327e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 328e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 329e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenience version of {@link UiScrollable#scrollBackward(int)}, performs a fling 330e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 331e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 332e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 333e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean flingBackward() { 334e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollBackward(FLING_STEPS); 335e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 336e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 337e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 338e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenience version of {@link UiScrollable#scrollBackward(int)}, performs a regular scroll 339e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 340e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 341e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 342e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollBackward() { 343e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollBackward(SCROLL_STEPS); 344e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 345e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 346e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 347e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Perform a scroll backward. If this list is set to vertical (see {@link #setAsVerticalList()} 348e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * default) then the swipes will be executed from the top to bottom. If this list is set 349e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * to horizontal (see {@link #setAsHorizontalList()}) then the swipes will be executed from 350e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * the left to right. 351e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 352e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param steps use steps to control the speed, so that it may be a scroll, or fling 353e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if scrolled and false if can't scroll anymore 354e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 355e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollBackward(int steps) { 356e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.d(LOG_TAG, "scrollBackward() on selector = " + getSelector()); 357e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 358e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 359e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Object Not Found 360e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 361e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 362e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = new Rect();; 363e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu node.getBoundsInScreen(rect); 364e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 365e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int downX = 0; 366e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int downY = 0; 367e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int upX = 0; 368e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int upY = 0; 369e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 370e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scrolling is by default assumed vertically unless the object is explicitly 371e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // set otherwise by setAsHorizontalContainer() 372e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(mIsVerticalList) { 373e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int swipeAreaAdjust = (int)(rect.height() * getSwipeDeadZonePercentage()); 374e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.d(LOG_TAG, "scrollToBegining() using vertical scroll"); 375e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scroll vertically: swipe up -> down 376e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downX = rect.centerX(); 377e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downY = rect.top + swipeAreaAdjust; 378e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upX = rect.centerX(); 379e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upY = rect.bottom - swipeAreaAdjust; 380e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 381e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu int swipeAreaAdjust = (int)(rect.width() * getSwipeDeadZonePercentage()); 382e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.d(LOG_TAG, "scrollToBegining() using hotizontal scroll"); 383e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // scroll horizontally: swipe left -> right 384e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // TODO: Assuming device is not in right to left language 385e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downX = rect.left + swipeAreaAdjust; 386e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu downY = rect.centerY(); 387e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upX = rect.right - swipeAreaAdjust; 388e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu upY = rect.centerY(); 389e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 390e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().scrollSwipe(downX, downY, upX, upY, steps); 391e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 392e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 393e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 394e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Scrolls to the beginning of a scrollable UI element. The beginning could be the top most 395e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * in case of vertical lists or the left most in case of horizontal lists. 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 /** 412e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenience version of {@link UiScrollable#scrollToBeginning(int, int)} with regular scroll 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 /** 422e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenience version of {@link UiScrollable#scrollToBeginning(int, int)} with fling 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 433e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * in case of vertical controls or the right most for horizontal controls 434e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 435e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param steps use steps to control the speed, so that it may be a scroll, or fling 436e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on scrolled else false 437e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 438e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollToEnd(int maxSwipes, int steps) { 439e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // protect against potential hanging and return after preset attempts 440e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu for(int x = 0; x < maxSwipes; x++) { 441e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(!scrollForward(steps)) { 442e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu break; 443e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 444e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 445e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return true; 446e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 447e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 448e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 449e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenience version of {@link UiScrollable#scrollToEnd(int, int)} with regular scroll 450e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 451e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param maxSwipes 452e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on scrolled else false 453e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 454e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean scrollToEnd(int maxSwipes) { 455e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollToEnd(maxSwipes, SCROLL_STEPS); 456e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 457e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 458e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 459e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * A convenience version of {@link UiScrollable#scrollToEnd(int, int)} with fling 460e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 461e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param maxSwipes 462e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on scrolled else false 463e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 464e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean flingToEnd(int maxSwipes) { 465e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return scrollToEnd(maxSwipes, FLING_STEPS); 466e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 467e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 468e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public double getSwipeDeadZonePercentage() { 469e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return mSwipeDeadZonePercentage; 470e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 471e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 472e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void setSwipeDeadZonePercentage(double swipeDeadZonePercentage) { 473e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mSwipeDeadZonePercentage = swipeDeadZonePercentage; 474e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 475e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu} 476