Android: ScrollView силу донизу


200

Я хотів би, щоб ScrollView починався повністю внизу. Якісь методи?


1
Я думаю, що це просто scrollTo (), так що я просто перевірив документи розробників на ScrollView. Простенька.
Ной Сейдман

Відповіді:


274

scroll.fullScroll(View.FOCUS_DOWN) також повинні працювати.

Покладіть це в scroll.Post(Runnable run)

Котлінський кодекс

scrollView.post {
   scrollView.fullScroll(View.FOCUS_DOWN)
}

6
Це, здається, не робить нічого, будь-які пропозиції? Я спробував це onCreate і пізніше onClick кнопки.
Річард Джонн

Схоже, це не працює на зміну орієнтації. Інакше працює.
Прашант

1
Це не працює, якщо розмір макета змінився прямо перед викликом. Це потрібно розмістити замість цього.
MLProgrammer-CiM

2
Це та нижче не працюватимуть, поки ви не надасте деякий час зору, щоб повністю надутись, просто спростивши відповідь адемара. scrollView.postDelayed (новий Runnable () {@Override public void run () {scrollView.fullScroll (View.FOCUS_UP // Або вниз);}}, 1000);
EngineSense

scroll.fullScroll (View.FOCUS_DOWN) призведе до зміни фокусу. Це призведе до деякої дивної поведінки, коли існує більше одного зосередженого перегляду, наприклад, два EditText. Перевірте інше рішення, яке я надаю внизу.
мирний пристрасть

332

вам слід запустити код всередині scroll.post так:

scroll.post(new Runnable() {            
    @Override
    public void run() {
           scroll.fullScroll(View.FOCUS_DOWN);              
    }
});

4
є спосіб без втрати поточного елемента фокусування, коли я це роблю, я втрачаю фокус мого поточного елемента (відмінний від scrollview)
rkmax

2
Це потрібно лише в тих випадках, коли макет ще не виміряний і не розміщений (наприклад, якщо ви запускаєте його в onCreate). У таких випадках, як натискання кнопки, .post () не потрібен.
Патрік Боос

12
Якщо ви не хочете , щоб зосередитися на ScrollView, ви можете використовувати , scroll.scrollTo(0, scroll.getHeight());щоб перейти на дно, або scroll.smoothScrollTo(0, scroll.getHeight());для більш плавної прокрутки
Юваль

Чи не можливий цей код витоку пам'яті? Створюється анонімний Runnable, який містить посилання на перегляд діяльності (прокрутки). Якщо активність буде знищена під час виконання завдання, що виконується, вона просочить посилання на прокрутку, ні?
Дженевер

У Котліні:scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
Альберт Віла Кальво

94

scroll.fullScroll(View.FOCUS_DOWN)призведе до зміни фокусу. Це призведе до деякої дивної поведінки, коли є більше одного зосередженого перегляду, наприклад, два EditText. Є ще один спосіб для цього питання.

    View lastChild = scrollLayout.getChildAt(scrollLayout.getChildCount() - 1);
    int bottom = lastChild.getBottom() + scrollLayout.getPaddingBottom();
    int sy = scrollLayout.getScrollY();
    int sh = scrollLayout.getHeight();
    int delta = bottom - (sy + sh);

    scrollLayout.smoothScrollBy(0, delta);

Це добре працює.

Розширення Kotlin

fun ScrollView.scrollToBottom() {
    val lastChild = getChildAt(childCount - 1)
    val bottom = lastChild.bottom + paddingBottom
    val delta = bottom - (scrollY+ height)        
    smoothScrollBy(0, delta)
}

Тож радий, що мені не довелося більше витрачати час на це. Тільки те, що мені було потрібно
Олександр G

6
Це повинно мати більше результатів. Це найкраща відповідь на сьогоднішній день.
Ерік Ланге

1
Це найкраща відповідь, присутня тут.
недійсний покажчик

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

Якщо вам потрібно прокрутити вниз під час відображення клавіатури, комбінуйте цей код із цією бібліотекою . Працює як шарм.
wonsuc

47

Іноді scrollView.post не працює

 scrollView.post(new Runnable() {
        @Override
        public void run() {
            scrollView.fullScroll(ScrollView.FOCUS_DOWN);
        }
    });

АЛЕ якщо ви використовуєте scrollView.postDelayed, це обов'язково спрацює

 scrollView.postDelayed(new Runnable() {
        @Override
        public void run() {
            scrollView.fullScroll(ScrollView.FOCUS_DOWN);
        }
    },1000);

дякую за ідентифікацію postDelayed - краще рішення.
Прашант

@Prashant :) :) :)
Ajay Shrestha

1
Просто пам’ятайте, що вам потрібно розпоряджатися вашим Runnable, коли ви закінчите діяльність
FabioR

38

Що найкраще працювало для мене

scroll_view.post(new Runnable() {
     @Override
     public void run() {
         // This method works but animates the scrolling 
         // which looks weird on first load
         // scroll_view.fullScroll(View.FOCUS_DOWN);

         // This method works even better because there are no animations.
         scroll_view.scrollTo(0, scroll_view.getBottom());
     }
});

Я спробував це, але алгоритм тут неправильний. Перевірте мою відповідь внизу, будь ласка.
мирний пристрасть

28

Я збільшую свою роботу.

    private void sendScroll(){
        final Handler handler = new Handler();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {Thread.sleep(100);} catch (InterruptedException e) {}
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        scrollView.fullScroll(View.FOCUS_DOWN);
                    }
                });
            }
        }).start();
    }

Примітка

Ця відповідь є вирішенням дійсно старих версій Android. На сьогодні ця postDelayedпомилка не має більше, і вам слід її використовувати.


3
Не вище двох, але це добре працює в моєму телефоні (LG JellyBean 4.1.2 Optimus G).
Youngjae

9
Чому б не використати scrollView.postDelayed (можна виконати, 100)?
Метт Вулф

1
@MattWolfe на той час не працював у деяких старих версіях Android. Але сьогодні ця відповідь взагалі застаріла.
ademar111190

4
Для любові до бога використовуйте scrollView.postDelayed (працює, 100)! :)
Алекс Локвуд

1
Я додав замітку @AlexLockwood Я сподіваюся, що люди користуються postDelayed:)
ademar111190

4

Я спробував це успішно.

scrollView.postDelayed(new Runnable() {
    @Override
    public void run() {
        scrollView.smoothScrollTo(0, scrollView.getHeight());
    }
}, 1000);

3

Якщо представлення ще не завантажено, ви не можете прокручувати. Ви можете зробити це "пізніше" за допомогою посту чи дзвінка уві сні, як зазначено вище, але це не дуже елегантно.

Краще спланувати прокрутку і зробити це на наступному onLayout (). Приклад коду тут:

https://stackoverflow.com/a/10209457/1310343


3

Варто враховувати, що НЕ встановлювати. Переконайтеся, що в доменних контролях, особливо в елементах EditText, немає властивості RequestFocus. Це може бути одним з останніх інтерпретованих властивостей у макеті, і він буде заміняти налаштування гравітації для батьків (макет або ScrollView).


3

Ось кілька інших способів прокручування донизу

fun ScrollView.scrollToBottom() {
    // use this for scroll immediately
    scrollTo(0, this.getChildAt(0).height) 

    // or this for smooth scroll
    //smoothScrollBy(0, this.getChildAt(0).height)

    // or this for **very** smooth scroll
    //ObjectAnimator.ofInt(this, "scrollY", this.getChildAt(0).height).setDuration(2000).start()
}

Використання

Якщо ви вже проклали огляд прокрутки

my_scroll_view.scrollToBottom()

Якщо ваш перегляд прокрутки не викладений (наприклад: ви прокручуєте донизу onCreateметод методу ...)

my_scroll_view.post { 
   my_scroll_view.scrollToBottom()          
}

1

Не зовсім відповідь на питання, але мені потрібно було прокрутити вниз, як тільки EditText отримав фокус. Однак прийнята відповідь змусить ЕТ також втратити фокус відразу (я припускаю ScrollView).

Моє вирішення було таким:

emailEt.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if(hasFocus){
            Toast.makeText(getActivity(), "got the focus", Toast.LENGTH_LONG).show();
            scrollView.postDelayed(new Runnable() {
                @Override
                public void run() {
                    scrollView.fullScroll(ScrollView.FOCUS_DOWN);
                }
            }, 200);
        }else {
            Toast.makeText(getActivity(), "lost the focus", Toast.LENGTH_LONG).show();
        }
    }
});

1

Я фактично виявив, що виклик fullScroll двічі робить трюк:

myScrollView.fullScroll(View.FOCUS_DOWN);

myScrollView.post(new Runnable() {
    @Override
    public void run() {
        myScrollView.fullScroll(View.FOCUS_DOWN);
    }
});

Це може бути пов'язане з активацією методу post () відразу після виконання першого (невдалого) прокрутки. Я думаю, що така поведінка виникає після будь-якого попереднього виклику методу на myScrollView, тому ви можете спробувати замінити перший метод fullScroll () будь-яким іншим, що може стосуватися вас.


0

Використовуючи ще один класний спосіб зробити це за допомогою процедур Котліна. Перевагою використання кореневої програми, на противагу обробнику, що працює з прогоном (post / postDelayed), є те, що воно не запускає дорогу нитку для виконання затримки.

launch(UI){
    delay(300)
    scrollView.fullScroll(View.FOCUS_DOWN)
}

Важливо вказати HandlerContext coroutine як інтерфейс користувача, інакше затримка дії не може бути викликана з потоку інтерфейсу користувача.


0

У цьому випадку використовували просто scroll.scrollTo (0, sc.getBottom ()) не працює, використовуйте його за допомогою scroll.post

Приклад:

scroll.post(new Runnable() {
  @Override
  public void run() {
  scroll.fullScroll(View.FOCUS_DOWN);
  } 
});

0

Однією з можливих причин, чому scroll.fullScroll(View.FOCUS_DOWN)може не працювати навіть загорнутий, .post()є те, що погляд не викладений. У цьому випадку View.doOnLayout () може бути кращим варіантом:

scroll.doOnLayout(){
    scroll.fullScroll(View.FOCUS_DOWN)
}

Або щось більш досконале для сміливих душ: https://chris.banes.dev/2019/12/03/suspending-views/

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