Скролл к элементу на экране Android приложения

Как выполнить скролл к элементу, который еще не отобразился на экране приложения?
например, скроллить вниз по экрану до тех пока пока не отобразился элемент, если отобразился, остановить скролл и выполнить действие (клик по элементу)
пробоавл scrollTo(“текст”), но так сначала прогоняется весь экран, а затем только выполняется клик(

1 лайк
public boolean scrollToElementById(String elemId) {
    try {
        driver.findElementByAndroidUIAutomator("new UiScrollable(new UiSelector().scrollable(true).instance(0))" +
                ".scrollIntoView(new UiSelector().resourceId(\" + elemId + \").instance(0))");
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("Scroll to element failed");
        return false;
    }
}

А потом кликнуть по елементу

2 лайка

@Anger87 Вы считаете, что это будет работать по-другому?

1 лайк

какой инструмент ? Appium ? Если да , то swipe работает нормально там

swipe это совсем другое, swipe позволяет прокручивать экран в рамках размера экрана, вышеописанный способ позволяет прокручивать экран к какому-либо существующему на даннjй странице элементу, неважно входит ли он в зону видимости или нет. Как известно, аппиум не видит элементы за рамками экрана. поэтому приходится прибегать к методам из uiautomator.

driver.findElementByAndroidUIAutomator("new UiScrollable(new UiSelector().scrollable(true).instance(0))" + ".scrollIntoView(new UiSelector().resourceId(\" + elemId + \").instance(0))");

3 лайка

swipe пока елемент не появиться делает тоже самое

2 лайка

Я использую 2-й подход, скролл через UIAutomator, а поиск через сам фреймворк.
Кстати, если используется список аля ListView или RecircleView, то resourceId у всех элементов будет единый.

1 лайк

Приведите пример кода, пожалуйста.

1 лайк

Пример кода подхода или пример единых resourceId?

1 лайк

private void scrollToElement(WebElement element, double yStartCoef, double yFinishCoef) {
Dimension size = getMobileDriver().manage().window().getSize();

    int startY = (int) (size.getHeight() * yStartCoef);
    int endY = (int) (size.getHeight() * yFinishCoef);
    int startX = (int) (size.getWidth() * 0.5);
    for (int i = 0; i < 10; i++) {
        try {
            getMobileDriver().manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
            performWaitForMobileElement(element, 2);
            break;
        } catch (Exception e) {
            LOG.error(element + " element not available");
            getMobileDriver().swipe(startX, startY, startX, endY, 1000);
            LOG.info("Swiping down from: (on X) " + startX + " and (on Y): " + startY + " to " + endY + " to element " + element);
        } finally {
            getMobileDriver().manage().timeouts().implicitlyWait(45, TimeUnit.SECONDS);
        }
    }
}

public void performWaitForMobileElement(final WebElement element, int timeout) {
getDriverWaitUtil().withTimeout(timeout).forCondition(getWaitForMobileElementCondition(element));
}

public Function<WebDriver, Boolean> getWaitForMobileElementCondition(final WebElement element) {
    Function<WebDriver, Boolean> isElementEnabled = new Function<WebDriver, Boolean>() {
        @Override
        public Boolean apply(WebDriver input) {
            return element.isEnabled();
        }
    };
    return isElementEnabled;
}
1 лайк

И где же здесь свайп до нужного вам элемента? Это похоже на костыль. Попробуйте применить код от Anger87. и Вы увидите различие.пишешь в одну строчку нужный локатор и все. Это самый первый способ, который приходит в голову, прокрутить экран до конца текущего экрана(то что позволяет сделать свайп) и попытаться найти элемент, если нет то крутить дальше. А что будет если с 10 попытки Ваш элемент не будет найден, то есть не до конца страницы дошли, например очень длинная лента сообщений?А что если элемент еще не появился при прокрутке, но появится чуть позже где то в середине, а Вы уже это место прокрутили? Указанный Anger87 пример делает, это все за Вас и быстрее, плюс если элемент находится не в самом низу он еще центрует элемент посередине экрана, начинает обход с начала экрана,проходит до конца и экрана и если не нашел, то возвращается опять к началу.

2 лайка

Количевство прокруток можно коректировать, если елемента нету в xml лейауте то вам не поможет тот подход о котором ви говорите, в данном случае просто свайп вертикальний будет свайпать вниз пока не подгрузится в лейауте елемент которий ви ищите. Ви не путайте мобайл лейаут и DOM - подгрузки там разние совсем… конечно елемент может бить не посредине итд, ето можно коректировать коефициентами в методе, но поверьте опиту, что на андроиде свайп работает стабильно, а разние там scrollTo i findElementByAndroidUIAutomator работают только тогда когда елемент есть в layout … проверено на тонне девайсов в клауде Perfecto Mobile…плюс етот метод будет работать крос платформенно, если ето лента сообщений то даю гарантию 99 процентов что она будет гибридной и там будет веб контекст где простой js скрол может помоць, так что не усложняйте себе жизнь))

1 лайк

Ознакомтесь - прокачайте “опыт” :slight_smile:

UIScrollable.scrollIntoView()

Лень читать код? Не проблема - расскажите нам “сказку” как ваш код “просвайпает” на About phone на этом скрине?

http://i.imgur.com/cAQeFGO.png

1 лайк

попробуйте его запустить и убедитесь что просвайпает без проблем, пока не появиться About, каждий день почти сталкиваюсь с подобними задачами и работает на ура на разних девайсах при чем…
посмотрел Java Doc метода scrollInToView - Perform a scroll search for a UI element matching the {@link UiSelector} selector argument. - ето значит что он должен бить в layout - About нету в layout - оно работает у Вас ?

1 лайк

Вы не умеете в Android - прекратите писать чушь.

2 лайка

Вот часть кода, я делаю так:

@AndroidFindBy(uiAutomator = “new UiScrollable(new UiSelector().scrollable(true).instance(0))” + “.scrollIntoView(new UiSelector().resourceId(“ru.test.testt.testtt:id/test_but”).instance(0))”)
private MobileElement navigateToTestButton;

затем клик
public TestPage openPage() {
navigateToTestButton.click();
return new TestPage(driver);
}

вот так у меня работает на одном экране,
но другом почему то скролит совсем не до конца экрана, только по начальному блоку(
буду разбираться, наверное добавить еще класс перед resourceId ?

1 лайк

“Оно” не скроллит экранами. Скроллится элемент [quote=“hulk_egor, post:16, topic:12865”]
new UiSelector().scrollable(true).instance(0)
[/quote]

т.е. первый элемент у которого атрибут scrollable == true.
Если у вас несколько scrollable контейнеров - уточняйте локатор:
UiSelector

1 лайк

uiAutomator = “new UiScrollable(new UiSelector().scrollable(true).className(” + ““android.support.v7.widget.RecyclerView”)).scrollIntoView(new UiSelector().resourceId(“ru.test.testt.testtt:id/test_but”))”

указаваю, да , но все равно не скролит дальше вниз(

1 лайк

Вот пожалуйста, у всех строк рецайклер-въю ид одни и те-же:

<node index="0" text="" resource-id="ru.livemaster:id/works_recycler" class="android.support.v7.widget.RecyclerView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false" scrollable="true" long-clickable="false" password="false" selected="false" bounds="[0,162][720,1184]">
	<node index="0" text="" resource-id="" class="android.widget.RelativeLayout" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,162][720,363]">
		<node index="0" text="" resource-id="ru.livemaster:id/contact_avatar" class="android.widget.ImageView" package="ru.livemaster" content-desc="ImageView" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[20,182][180,342]" />
		<node index="1" text="" resource-id="ru.livemaster:id/text_layout" class="android.widget.LinearLayout" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,182][429,343]">
			<node index="0" text="sphinxTest2" resource-id="ru.livemaster:id/text_title" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,182][354,220]" />
			<node index="1" text="Hello (magazin345)" resource-id="ru.livemaster:id/text_master_name" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,220][429,256]" />
			<node index="2" text="Готовая работа" resource-id="ru.livemaster:id/text_item_type" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,256][375,289]" />
			<node index="3" text="234 руб" resource-id="ru.livemaster:id/text_price" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,289][341,343]" />
		</node>
	</node>
	<node index="1" text="" resource-id="" class="android.widget.RelativeLayout" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,363][720,564]">
		<node index="0" text="" resource-id="ru.livemaster:id/contact_avatar" class="android.widget.ImageView" package="ru.livemaster" content-desc="ImageView" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[20,383][180,543]" />
		<node index="1" text="" resource-id="ru.livemaster:id/text_layout" class="android.widget.LinearLayout" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,383][375,544]">
			<node index="0" text="белье" resource-id="ru.livemaster:id/text_title" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,383][278,421]" />
			<node index="1" text="Anna" resource-id="ru.livemaster:id/text_master_name" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,421][261,457]" />
			<node index="2" text="Готовая работа" resource-id="ru.livemaster:id/text_item_type" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,457][375,490]" />
			<node index="3" text="300 руб" resource-id="ru.livemaster:id/text_price" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,490][341,544]" />
		</node>
	</node>
	<node index="2" text="" resource-id="" class="android.widget.RelativeLayout" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,564][720,765]">
		<node index="0" text="" resource-id="ru.livemaster:id/contact_avatar" class="android.widget.ImageView" package="ru.livemaster" content-desc="ImageView" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[20,584][180,744]" />
		<node index="1" text="" resource-id="ru.livemaster:id/text_layout" class="android.widget.LinearLayout" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,584][375,745]">
			<node index="0" text="мужчина" resource-id="ru.livemaster:id/text_title" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,584][322,622]" />
			<node index="1" text="Anna" resource-id="ru.livemaster:id/text_master_name" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,622][261,658]" />
			<node index="2" text="Готовая работа" resource-id="ru.livemaster:id/text_item_type" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,658][375,691]" />
			<node index="3" text="2 000 руб" resource-id="ru.livemaster:id/text_price" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,691][373,745]" />
		</node>
	</node>
	<node index="3" text="" resource-id="" class="android.widget.RelativeLayout" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,765][720,966]">
		<node index="0" text="" resource-id="ru.livemaster:id/contact_avatar" class="android.widget.ImageView" package="ru.livemaster" content-desc="ImageView" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[20,785][180,945]" />
		<node index="1" text="" resource-id="ru.livemaster:id/text_layout" class="android.widget.LinearLayout" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,785][680,946]">
			<node index="0" text="ацывуа2к23" resource-id="ru.livemaster:id/text_title" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,785][364,823]" />
			<node index="1" text="Администратор (administrator) (administrator)" resource-id="ru.livemaster:id/text_master_name" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,823][680,859]" />
			<node index="2" text="Готовая работа" resource-id="ru.livemaster:id/text_item_type" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,859][375,892]" />
			<node index="3" text="4 234 руб" resource-id="ru.livemaster:id/text_price" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,892][373,946]" />
		</node>
	</node>
	<node index="4" text="" resource-id="" class="android.widget.RelativeLayout" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,966][720,1167]">
		<node index="0" text="" resource-id="ru.livemaster:id/contact_avatar" class="android.widget.ImageView" package="ru.livemaster" content-desc="ImageView" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[20,986][180,1146]" />
		<node index="1" text="" resource-id="ru.livemaster:id/text_layout" class="android.widget.LinearLayout" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,986][680,1147]">
			<node index="0" text='Копия работы: Копия работы Боди "Пасхальный Кролик"3333333' resource-id="ru.livemaster:id/text_title" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,986][680,1024]" />
			<node index="1" text="VelvetCat" resource-id="ru.livemaster:id/text_master_name" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,1024][311,1060]" />
			<node index="2" text="На заказ" resource-id="ru.livemaster:id/text_item_type" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,1060][299,1093]" />
			<node index="3" text="5 500 руб" resource-id="ru.livemaster:id/text_price" class="android.widget.TextView" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[200,1093][373,1147]" />
		</node>
	</node>
	<node index="5" text="" resource-id="" class="android.widget.RelativeLayout" package="ru.livemaster" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,1167][720,1184]" />
</node>
1 лайк

У приложения скролл бар изменяется, поэтому я скролю только первый блок. Как при скроле одного блока перейти к скроллу следующего?

1 лайк