Як прокрутити верх до довгого макета ScrollView?


162

У частині мого додатку користувачеві подається список імен і його просять згрупувати їх, як вони вважають за потрібне.

(Зауважте, код ListView був скопійований дослівно з підручника Android Views. Я ще не налаштував його на мої потреби, я просто намагаюся з’ясувати, як зробити цю роботу.)

Основний макет - це LinearLayout, що містить ScrollView (званий "groupsScrollView" у коді нижче), що містить RelativeLayout. У мене є кілька кнопок і текст, а потім мій ListView під цим, який відображає список імен. Все це вище, ніж видима область екрана, тому користувачеві дозволено прокручувати вертикально, щоб побачити все це.

Це все прекрасно працює, за винятком випадків, коли сторінка завантажується, вона попередньо прокручується до початку мого ListView - посередині сторінки. Текст і кнопки, які я створив, що повідомляють користувачеві, що робити, не видно.

Я можу схопити екран і прокрутити вгору, це працює чудово, але я хотів би, щоб екран завантажився, вже прокрутившись до верху. Користувачеві не слід прокручувати Вгору, щоб побачити верхню частину щойно завантаженої сторінки. Але все, що я намагався програмно прокрутити до верхньої частини екрана, не вдалося.

Ось мій метод onCreate:

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.groups);

    mainScrollView = (ScrollView)findViewById(R.id.groupsScrollView);

    //get the Bundle out of the Intent...
    Bundle extras = getIntent().getExtras();
    mNames = extras.getStringArray("mNames");

    setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, mNames));

    ListView lv = getListView();
    lv.setTextFilterEnabled(true);

    //This is the line I'm having issues with
    mainScrollView.pageScroll(View.FOCUS_UP);

    lv.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
            int position, long id) {
          // When clicked, show a toast with the TextView text
          Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
              Toast.LENGTH_SHORT).show();
        }
      });
}

Рядок "mainScrollView.pageScroll (View.FOCUS_UP); є проблемою. Це не викликає помилок, але, здається, нічого не робить. Я спробував прокручуватиTo (0,0), scrollDirection (View.FOCUS_UP ), і все інше, про що я можу придумати.

Оскільки я не отримую помилку, я повинен припустити, що ці команди прокрутки дійсно працюють, але що вони прокручуються до вершини ListView, а не до вершини ScrollView або RelativeLayout, яка їх містить. Це, мабуть, підтверджується власним описом методу scrollTo (int x, int y), де вони говорять: "Ця версія також затискає прокрутку до меж нашої дитини".

Отже, щоб ще довше поставити запитання, як я завантажую купу переглядів на екран, що міститься в ScrollView, а потім програматично прокручувати все до початку сторінки, щоб користувач міг взаємодіяти з ним?

Дякую!

Відповіді:


264

Спробуйте

mainScrollView.fullScroll(ScrollView.FOCUS_UP);

це має працювати.


Працює і для мене. : D
Мунтасір Аонік

1
Я знайшов ScrollView # fullScroll () змінити поточний фокус. Я тестував за допомогою EditText.
illusionJJ

175

Був той самий випуск, напевно, якась помилка.

Навіть fullScroll(ScrollView.FOCUS_UP)з іншої відповіді не вийшло.
Єдине, що працювало для мене, дзвонило scroll_view.smoothScrollTo(0,0)відразу після появи діалогового вікна.


Це спрацювало спочатку, але пізніше, коли я намагався це робити знову і знову, такий підхід не дав задовільного результату.
JaydeepW

16
Я вирішую з scroll_view.smoothScrollTo (0,0), коли у нас є список перегляду в той час, як перелік прокрутки на той час fullScroll (ScrollView.FOCUS_UP) не працюватиме.
Кіртікумар А.

1
scroll_view.smoothScrollTo (0,0) працював для мене краще, ніж mainScrollView.fullScroll (ScrollView.FOCUS_UP); ДЯКУЮ!
marienke

2
На більшості пристроїв fullScroll (ScrollView.FOCUS_UP) працював, але на Nexus 5 та пристроях, на яких розмір тексту був збільшений вгору - fullSscroll перемістився під панель дій, smoothScrollTo (0,0) працював краще на всіх пристроях.
jt-gilkeson

Це також має перевагу над fullScroll()тим, що він зберігає вибраний елемент все ще обраним після переміщення. З fullScroll(), перший елемент перегляду прокрутки вибирався кожен раз у моєму випадку, незалежно від вибраного елемента до того, як прокрутка рухалася вгору.
GeertVc

97

У мене була така ж проблема, і це виправлено. Сподіваюся, це допоможе вам.

listView.setFocusable(false);

3
Це правильне рішення також для перегляду сітки. Це трапляється, коли у вас є декілька елементів перегляду в одній групі перегляду, особливо інший перегляд списку вгорі списку або перегляд сітки. Оскільки адаптер повідомляє потік інтерфейсу користувача, перегляд відтворюється і прокручується до першого елемента. Просто зателефонуйте listView.setFocusable (false) / gridView.setFocusable (false). Якщо ви робите це з файлу xml, він не працюватиме.
омерсем

Це рішення спрацювало і в моєму випадку, у мене був RecyclerView всередині NestedScrollView, тому воно було автоматично прокручено вниз. Спасибі, чоловіче!
Нілеш Ратхор

Мені довелося додати це перед тим, як встановити адаптер, але після цього він працює як шарм. Спасибі
Громада

ідеальне пояснення !!
Борха Лопес

Дякую і Мігелю, і особливо omersem за пояснення, особливо частину про те, як це буде працювати, якщо встановлено в XML, це врятувало мене головний біль
buradd

53

scrollViewObject.fullScroll(ScrollView.FOCUS_UP)це працює чудово, але лише проблема цього рядка полягає в тому, що коли дані заповнюються у scrollViewObject, було викликано негайно. Потрібно почекати кілька мілісекунд, поки дані не заповняться. Спробуйте цей код:

scrollViewObject.postDelayed(new Runnable() {
    @Override
    public void run() {
        scroll.fullScroll(ScrollView.FOCUS_UP);
    }
}, 600);

АБО

 scrollViewObject.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        scrollViewObject.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        scrollViewObject.fullScroll(View.FOCUS_UP);
    }
});

Я мав справу з тією ж проблемою, де вигляд прокрутки повинен був прокручуватися внизу сторінки, виправити це вгору!
Машинне плем'я

1
Замість того, щоб здогадуватися про "чарівну" x кількість мілісекунд, яку вам доведеться почекати, об’єкти "Перегляд" пропонують метод публікації (Runnable), який ви можете використовувати, який розмістить виконувану роботу, коли віджет відобразиться в інтерфейсі користувача.
Райан

@Ryan: пост (Runnable) завжди не працює для мене на Nexus 5 (Genymotion)
Dika

публікація (Runnable) може не працювати, оскільки якщо ви отримуєте дані після кроку перегляду перегляду, спочатку прокрутка працює вгору, а потім дані заповнюються у подання. Тож вам або слід використовувати postDelayed (Runnable, dummyMillis) або використовувати scroll.fullScroll (ScrollView.FOCUS_UP) після заповнених даних процесів.
огужан

Ваше перше рішення, в якому ви даєте статичні мілі - це поганий підхід.
Malwinder Singh

35

Основна проблема всіх цих дійсних рішень полягає в тому, що ви намагаєтеся перемістити прокрутку вгору, коли вона ще не намальована на екрані.

Потрібно почекати, поки на екрані з’явиться перегляд прокрутки, а потім перемістити його вгору з будь-яким із цих рішень. Це краще рішення, ніж після затримки, оскільки ви не заперечуєте про затримку.

    // Wait until my scrollView is ready
    scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Ready, move up
            scrollView.fullScroll(View.FOCUS_UP);
        }
    });

7
Приємне рішення - Не забудьте видалити глобального слухача в кінці onGlobalLayoutвиклику методу scrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Nilhcem

30

Дуже легко

    ScrollView scroll = (ScrollView) findViewById(R.id.addresses_scroll);
    scroll.setFocusableInTouchMode(true);
    scroll.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);

3
для мене це не спрацювало (3-й рядок), рішення було: scroll.fullScroll (View.FOCUS_UP); (з урахуванням перших 2 рядків)
medskill

@medskill, Привіт, ти це записав у свій XML-файл? Я вважаю, що це працює лише в onCreate().
невідомо

@ imknownJ.Kimu працює для мене у XML-файлі
Paglian

Це працювало для мене. Вам потрібні і другий, і третій рядки. Він би не працював у XML для мене.
ET

2
Я б поцілував тебе, якби міг! На це витратили 1-2 години. Найкращий, коли чекав завантаження двох переглядів списку, і не хотів зосереджуватися на них. Додано його до onResume ().
Джон Т

24

Я зіткнувся з тією самою проблемою, коли я використовую Scrollview всередині перегляду Flipper або Dialog, що випадок scrollViewObject.fullScroll(ScrollView.FOCUS_UP)повертає помилково, щоб цей випадок спрацював scrollViewObject.smoothScrollTo(0, 0)для мене

Прокрутіть фокус вгорі


19
 final ScrollView scrollview = (ScrollView)findViewById(R.id.selected_place_layout_scrollview);

         scrollview.post(new Runnable() { 
                public void run() { 
                    scrollview.scrollTo(0, 0); 
                } 
            }); 

9
runOnUiThread( new Runnable(){
   @Override
   public void run(){
      mainScrollView.fullScroll(ScrollView.FOCUS_UP);
   }
}


6

Це примусовий прокручування для перегляду прокрутки :

            scrollView.post(new Runnable() {
                @Override
                public void run() {
                    scrollView.scrollTo(0, 0);
                    scrollView.pageScroll(View.FOCUS_UP);
                    scrollView.smoothScrollTo(0,0);
                }
            });

4
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // Ready, move up
        scrollView.fullScroll(View.FOCUS_UP);
    }
});

1

Я вирішив свою проблему в Котліні так:

scrollview.isFocusableInTouchMode = true
scrollview.fullScroll(View.FOCUS_UP)
scrollview.smoothScrollTo(0,0)

0
@SuppressWarnings({ "deprecation", "unchecked" })
public void swipeTopToBottom(AppiumDriver<MobileElement> driver) 
                    throws InterruptedException {
       Dimension dimensions = driver.manage().window().getSize();
        Double screenHeightStart = dimensions.getHeight() * 0.30;
        int scrollStart = screenHeightStart.intValue();
        System.out.println("s="+scrollStart);
        Double screenHeightEnd = dimensions.getHeight()*0.90;
        int scrollEnd = screenHeightEnd.intValue();
        driver.swipe(0,scrollStart,0,scrollEnd,2000);
        CommonUtils.threadWait(driver, 3000);
    }

це буде працювати точно,
Ajeet Gour

Надайте коротке пояснення, як ця відповідь вирішує проблему.
Айберк Озгюр
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.