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