J'aimerais qu'un ScrollView commence tout en bas. Des méthodes?
J'aimerais qu'un ScrollView commence tout en bas. Des méthodes?
Réponses:
scroll.fullScroll(View.FOCUS_DOWN)
devrait également fonctionner.
Mettez cela dans un scroll.Post(Runnable run)
Code Kotlin
scrollView.post {
scrollView.fullScroll(View.FOCUS_DOWN)
}
vous devez exécuter le code à l'intérieur du scroll.post comme ceci:
scroll.post(new Runnable() {
@Override
public void run() {
scroll.fullScroll(View.FOCUS_DOWN);
}
});
scroll.scrollTo(0, scroll.getHeight());
pour sauter vers le bas ou scroll.smoothScrollTo(0, scroll.getHeight());
pour un défilement plus fluide
scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
scroll.fullScroll(View.FOCUS_DOWN)
entraînera un changement d'orientation. Cela apportera un comportement étrange lorsqu'il y a plusieurs vues focalisables, par exemple deux EditText. Il existe une autre façon de répondre à cette question.
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);
Cela fonctionne bien.
Extension Kotlin
fun ScrollView.scrollToBottom() {
val lastChild = getChildAt(childCount - 1)
val bottom = lastChild.bottom + paddingBottom
val delta = bottom - (scrollY+ height)
smoothScrollBy(0, delta)
}
Parfois, scrollView.post ne fonctionne pas
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
});
MAIS si vous utilisez scrollView.postDelayed, cela fonctionnera certainement
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
},1000);
Ce qui a le mieux fonctionné pour moi, c'est
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());
}
});
J'incrémente pour travailler parfaitement.
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();
}
Remarque
Cette réponse est une solution de contournement pour les versions très anciennes d'Android. Aujourd'hui, postDelayed
il n'y a plus de bug et vous devriez l'utiliser.
postDelayed
:)
j'ai essayé avec succès.
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, scrollView.getHeight());
}
}, 1000);
Lorsque la vue n'est pas encore chargée, vous ne pouvez pas faire défiler. Vous pouvez le faire «plus tard» avec un post ou un appel de sommeil comme ci-dessus, mais ce n'est pas très élégant.
Il est préférable de planifier le défilement et de le faire lors du prochain onLayout (). Exemple de code ici:
Une chose à considérer est ce qu'il ne faut PAS définir. Assurez-vous que vos contrôles enfants, en particulier les contrôles EditText, n'ont pas la propriété RequestFocus définie. Il peut s'agir de l'une des dernières propriétés interprétées de la disposition et elle remplacera les paramètres de gravité de ses parents (la disposition ou ScrollView).
Voici quelques autres façons de défiler vers le bas
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()
}
En utilisant
Si vous faites défiler la vue déjà présentée
my_scroll_view.scrollToBottom()
Si votre vue de défilement n'est pas terminée (par exemple: vous faites défiler vers le bas dans la onCreate
méthode d' activité ...)
my_scroll_view.post {
my_scroll_view.scrollToBottom()
}
Pas exactement la réponse à la question, mais je devais faire défiler vers le bas dès qu'un EditText avait le focus. Cependant, la réponse acceptée ferait perdre également la focalisation à l'ET (pour ScrollView, je suppose).
Ma solution de contournement était la suivante:
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();
}
}
});
En fait, j'ai trouvé qu'appeler fullScroll deux fois fait l'affaire:
myScrollView.fullScroll(View.FOCUS_DOWN);
myScrollView.post(new Runnable() {
@Override
public void run() {
myScrollView.fullScroll(View.FOCUS_DOWN);
}
});
Cela peut avoir quelque chose à voir avec l'activation de la méthode post () juste après avoir effectué le premier défilement (infructueux). Je pense que ce problème se produit après tout appel de méthode précédent sur myScrollView, vous pouvez donc essayer de remplacer la première méthode fullScroll () par toute autre chose qui pourrait vous concerner.
Il existe une autre façon intéressante de le faire avec les coroutines Kotlin. L'avantage d'utiliser une coroutine opposée à un gestionnaire avec un exécutable (post / postDelayed) est qu'il ne lance pas un thread coûteux pour exécuter une action différée.
launch(UI){
delay(300)
scrollView.fullScroll(View.FOCUS_DOWN)
}
Il est important de spécifier le HandlerContext de la coroutine comme interface utilisateur, sinon l'action différée risque de ne pas être appelée à partir du thread d'interface utilisateur.
Une des raisons possibles pour lesquelles cela scroll.fullScroll(View.FOCUS_DOWN)
pourrait ne pas fonctionner même enveloppé .post()
est que la vue n'est pas disposée. Dans ce cas, View.doOnLayout () pourrait être une meilleure option:
scroll.doOnLayout(){
scroll.fullScroll(View.FOCUS_DOWN)
}
Ou, quelque chose de plus élaboré pour les âmes courageuses: https://chris.banes.dev/2019/12/03/suspending-views/