Vorrei che un ScrollView iniziasse fino in fondo. Qualche metodo?
Vorrei che un ScrollView iniziasse fino in fondo. Qualche metodo?
Risposte:
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)
}
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);
}
});
scroll.scrollTo(0, scroll.getHeight());
per saltare verso il basso o scroll.smoothScrollTo(0, scroll.getHeight());
per uno scorrimento più fluido
scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
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)
}
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);
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());
}
});
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 postDelayed
non ha più quel bug e dovresti usarlo.
postDelayed
:)
l'ho provato con successo.
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, scrollView.getHeight());
}
}, 1000);
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:
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).
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 onCreate
metodo Attività ...)
my_scroll_view.post {
my_scroll_view.scrollToBottom()
}
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();
}
}
});
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.
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.
Una possibile ragione per cui scroll.fullScroll(View.FOCUS_DOWN)
potrebbe non funzionare nemmeno avvolta .post()
è che la vista non è definita. In questo caso View.doOnLayout () potrebbe essere un'opzione migliore:
scroll.doOnLayout(){
scroll.fullScroll(View.FOCUS_DOWN)
}
O qualcosa di più elaborato per le anime coraggiose: https://chris.banes.dev/2019/12/03/suspending-views/