Android: ScrollView forza in basso


200

Vorrei che un ScrollView iniziasse fino in fondo. Qualche metodo?


1
Penso che sia solo scrollTo (), sì, ho appena controllato i documenti di sviluppo per ScrollView. Vai tranquillo.
Noah Seidman,

Risposte:


274

scroll.fullScroll(View.FOCUS_DOWN) anche dovrebbe funzionare.

Metti questo in a scroll.Post(Runnable run)

Codice di Kotlin

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

6
Non sembra fare nulla, nessun suggerimento? L'ho provato su onCreate e successivamente su onClick di un pulsante.
Richard John

Non sembra funzionare nel cambiare orientamento. Altrimenti funziona.
Prashant

1
Questo non funziona se la dimensione del layout è cambiata subito prima di chiamarla. Deve invece essere pubblicato.
MLProgrammer-CiM

2
Questo e sotto non funzioneranno fino a quando non si avrà un po 'di tempo per gonfiare completamente la vista, semplicemente semplificando la risposta di Ademar. scrollView.postDelayed (new Runnable () {@Override public void run () {scrollView.fullScroll (View.FOCUS_UP // Or Down);}}, 1000);
EngineSense il

scroll.fullScroll (View.FOCUS_DOWN) porterà al cambio di messa a fuoco. Ciò comporterà un comportamento strano quando ci sono più di una vista focalizzabile, ad esempio due EditText. Controlla un'altra soluzione che fornisco in fondo.
peacepassion,

332

dovresti eseguire il codice all'interno di scroll.post in questo modo:

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

4
c'è un modo senza perdere l'elemento corrente del focus, quando lo faccio perdo il focus del mio elemento corrente (diverso da scrollview)
rkmax

2
Ciò è necessario solo nei casi in cui il layout non è stato ancora misurato e layout (ad esempio se lo si esegue in onCreate). In casi come la pressione di un pulsante, .post () non è necessario.
Patrick Boos,

12
Se non vuoi concentrarti su ScrollView, puoi usare scroll.scrollTo(0, scroll.getHeight());per saltare verso il basso o scroll.smoothScrollTo(0, scroll.getHeight());per uno scorrimento più fluido
yuval

Questo codice non è una possibile perdita di memoria? Viene creato un Runnable anonimo che contiene un riferimento a una vista attività (scorrimento). Se l'attività viene distrutta mentre il runnable sta eseguendo il suo compito, perderà un riferimento alla vista di scorrimento, no?
Ogni volta che il

A Kotlin:scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
Albert Vila Calvo,

94

scroll.fullScroll(View.FOCUS_DOWN)porterà al cambiamento di messa a fuoco. Ciò comporterà un comportamento strano quando ci sono più di una vista focalizzabile, ad esempio due EditText. C'è un altro modo per questa domanda.

    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);

Funziona bene

Estensione di Kotlin

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

Sono così felice di non dover perdere altro tempo su questo. Proprio quello di cui avevo bisogno
Alexandre G,

6
Questo dovrebbe avere più voti. È di gran lunga la risposta migliore.
Eric Lange,

1
Questa è la migliore risposta presente qui.
void pointer

1
Ho provato tutto il resto in questa pagina, anche le cose al di sotto di questo. Questa è stata l'unica cosa che ha funzionato e non fa perdere la messa a fuoco del mio EditText. Grazie.
Gioele il

Se è necessario scorrere verso il basso mentre viene visualizzata la tastiera, combinare questo codice con questa libreria . Funziona come un fascino.
Wonsuc,

47

A volte scrollView.post non funziona

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

MA se usi scrollView.postDelayed, funzionerà sicuramente

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

grazie per l'identificazione. postDelayed è la soluzione migliore.
Prashant,

@Prashant :) :) :)
Ajay Shrestha

1
Ricorda solo che devi eliminare il Runnable quando finisci l'attività
FabioR,

38

Quello che ha funzionato meglio per me è

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());
     }
});

Ho provato questo, ma l'algoritmo qui è sbagliato. Controlla la mia risposta in fondo per favore.
peacepassion,

28

Incremento per funzionare perfettamente.

    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();
    }

Nota

Questa risposta è una soluzione alternativa per le versioni davvero vecchie di Android. Oggi postDelayednon ha più quel bug e dovresti usarlo.


3
Non sopra due, ma questo funziona bene nel mio telefono (LG JellyBean 4.1.2 Optimus G).
Youngjae,

9
Perché non usare scrollView.postDelayed (eseguibile, 100)?
Matt Wolfe,

1
@MattWolfe al momento non funzionava in alcune vecchie versioni di Android. Ma oggi questa risposta è del tutto deprecata.
ademar111190,

4
Per amore di Dio, usa scrollView.postDelayed (runnable, 100)! :)
Alex Lockwood,

1
Ho aggiunto una nota @AlexLockwood Spero che la gente usi il postDelayed:)
ademar111190,

4

l'ho provato con successo.

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

3

Quando la vista non è ancora caricata, non è possibile scorrere. Puoi farlo "più tardi" con un post o una chiamata di sonno come sopra, ma questo non è molto elegante.

È meglio pianificare lo scorrimento e farlo sul prossimo onLayout (). Codice di esempio qui:

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


3

Una cosa da considerare è cosa NON impostare. Assicurarsi che i controlli figlio, in particolare i controlli EditText, non abbiano la proprietà RequestFocus impostata. Questa potrebbe essere una delle ultime proprietà interpretate sul layout e sovrascriverà le impostazioni di gravità sui suoi genitori (il layout o ScrollView).


3

Ecco alcuni altri modi per scorrere verso il basso

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()
}

utilizzando

Se si scorre già la visualizzazione

my_scroll_view.scrollToBottom()

Se la vista di scorrimento non è stata completata (ad es .: si scorre fino in fondo nel onCreatemetodo Attività ...)

my_scroll_view.post { 
   my_scroll_view.scrollToBottom()          
}

1

Non è esattamente la risposta alla domanda, ma ho dovuto scorrere verso il basso non appena un EditText ha ottenuto il focus. Tuttavia, la risposta accettata farebbe perdere immediatamente anche la messa a fuoco dell'ET (suppongo a ScrollView).

La mia soluzione alternativa era la seguente:

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

In realtà ho scoperto che chiamare FullScroll due volte fa il trucco:

myScrollView.fullScroll(View.FOCUS_DOWN);

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

Potrebbe avere qualcosa a che fare con l'attivazione del metodo post () subito dopo aver eseguito il primo scorrimento (non riuscito). Penso che questo comportamento si verifichi dopo qualsiasi precedente chiamata di metodo su myScrollView, quindi puoi provare a sostituire il primo metodo fullScroll () con qualsiasi altra cosa che possa essere pertinente per te.


0

L'utilizzo di un altro modo interessante per farlo con le coroutine di Kotlin. Il vantaggio di utilizzare una coroutine rispetto a un gestore con un eseguibile (post / postDelayed) è che non avvia un thread costoso per eseguire un'azione ritardata.

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

È importante specificare HandlerContext del coroutine come UI, altrimenti l'azione ritardata potrebbe non essere richiamata dal thread dell'interfaccia utente.


0

In quei casi utilizzavano solo scroll.scrollTo (0, sc.getBottom ()) non funziona, usalo usando scroll.post

Esempio:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.