Chciałbym, aby ScrollView zaczął się od samego początku. Jakieś metody?
Chciałbym, aby ScrollView zaczął się od samego początku. Jakieś metody?
Odpowiedzi:
scroll.fullScroll(View.FOCUS_DOWN)
powinien również działać.
Umieść to w scroll.Post(Runnable run)
Kod Kotlin
scrollView.post {
scrollView.fullScroll(View.FOCUS_DOWN)
}
powinieneś uruchomić kod w scroll.post w następujący sposób:
scroll.post(new Runnable() {
@Override
public void run() {
scroll.fullScroll(View.FOCUS_DOWN);
}
});
scroll.scrollTo(0, scroll.getHeight());
aby przejść do dołu lub scroll.smoothScrollTo(0, scroll.getHeight());
płynniejszego przewijania
scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
scroll.fullScroll(View.FOCUS_DOWN)
doprowadzi do zmiany ostrości. Spowoduje to dziwne zachowanie, gdy istnieje więcej niż jeden widok z możliwością ustawiania ostrości, np. Dwa EditText. Jest inny sposób na to pytanie.
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);
To działa dobrze.
Rozszerzenie Kotlin
fun ScrollView.scrollToBottom() {
val lastChild = getChildAt(childCount - 1)
val bottom = lastChild.bottom + paddingBottom
val delta = bottom - (scrollY+ height)
smoothScrollBy(0, delta)
}
Czasami scrollView.post nie działa
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
});
ALE jeśli użyjesz scrollView.postDelayed, to na pewno zadziała
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
},1000);
To, co działało dla mnie najlepiej, to
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());
}
});
Zwiększam do perfekcji.
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();
}
Uwaga
Ta odpowiedź jest obejściem dla naprawdę starych wersji Androida. Dzisiaj postDelayed
nie ma już tego błędu i powinieneś go użyć.
postDelayed
:)
próbowałem tego z sukcesem.
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, scrollView.getHeight());
}
}, 1000);
Gdy widok nie jest jeszcze załadowany, nie można przewijać. Możesz to zrobić „później” za pomocą połączenia pocztowego lub snu, jak wyżej, ale nie jest to zbyt eleganckie.
Lepiej zaplanować zwój i zrobić to na następnej funkcji onLayout (). Przykładowy kod tutaj:
Jedną rzeczą do rozważenia jest to, czego NIE należy ustawiać. Upewnij się, że formanty podrzędne, zwłaszcza formanty EditText, nie mają ustawionej właściwości RequestFocus. Może to być jedna z ostatnich interpretowanych właściwości układu i zastąpi ustawienia grawitacji na jego rodzicach (układzie lub ScrollView).
Oto kilka innych sposobów przewijania na dół
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()
}
Za pomocą
Jeśli przewijasz widok już ułożony
my_scroll_view.scrollToBottom()
Jeśli widok przewijania nie jest zakończony (np. Przewijasz w dół w onCreate
metodzie działania ...)
my_scroll_view.post {
my_scroll_view.scrollToBottom()
}
Nie do końca odpowiedź na pytanie, ale musiałem przewinąć w dół, gdy tylko tekst EditText się skupi. Jednak zaakceptowana odpowiedź sprawiłaby, że ET również natychmiast straciłoby koncentrację (zakładam, że do ScrollView).
Moje obejście było następujące:
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();
}
}
});
Odkryłem, że dwukrotne wywołanie funkcji fullScroll:
myScrollView.fullScroll(View.FOCUS_DOWN);
myScrollView.post(new Runnable() {
@Override
public void run() {
myScrollView.fullScroll(View.FOCUS_DOWN);
}
});
Może to mieć coś wspólnego z aktywacją metody post () zaraz po wykonaniu pierwszego (nieudanego) przewijania. Myślę, że takie zachowanie występuje po każdym poprzednim wywołaniu metody myScrollView, więc możesz spróbować zastąpić pierwszą metodę fullScroll () inną, która może być dla ciebie odpowiednia.
Jest jeszcze jeden fajny sposób na zrobienie tego z karlinami Kotlin. Zaletą użycia coroutine w przeciwieństwie do Handlera z runnable (post / postDelayed) jest to, że nie uruchamia on drogiego wątku w celu wykonania akcji opóźnionej.
launch(UI){
delay(300)
scrollView.fullScroll(View.FOCUS_DOWN)
}
Ważne jest, aby określić HandlerContext coroutine jako interfejs użytkownika, w przeciwnym razie opóźnione działanie może nie zostać wywołane z wątku interfejsu użytkownika.
Jednym z możliwych powodów, dla których scroll.fullScroll(View.FOCUS_DOWN)
może nie działać, nawet gdy jest opakowany, .post()
jest brak widoku. W takim przypadku lepszym rozwiązaniem może być View.doOnLayout () :
scroll.doOnLayout(){
scroll.fullScroll(View.FOCUS_DOWN)
}
Lub coś bardziej opracowanego dla odważnych dusz: https://chris.banes.dev/2019/12/03/suspending-views/