Я бы хотел, чтобы ScrollView начинался полностью снизу. Какие-нибудь методы?
Android: усилие прокрутки вниз
Ответы (18)
scroll.fullScroll(View.FOCUS_DOWN)
тоже должно работать.
Поместите это в scroll.Post(Runnable run)
Код Котлина
scrollView.post {
scrollView.fullScroll(View.FOCUS_DOWN)
}
scroll.fullScroll(View.FOCUS_DOWN)
приведет к изменению фокуса. Это приведет к некоторому странному поведению, когда есть более одного фокусируемого представления, например, два EditText. Проверьте мой ответ ниже.
- person peacepassion; 02.09.2017
ScrollView
во время вызова fullScroll()
. Если это так, то более эффективным подходом, если вы используете Kotlin, будет использование _ 3_ из Android KTX.
- person CommonsWare; 05.05.2020
binding.scroll.run { post { fullScroll(View.FOCUS_DOWN) } }
легко;)
- person murt; 23.04.2021
вы должны запустить код внутри scroll.post следующим образом:
scroll.post(new Runnable() {
@Override
public void run() {
scroll.fullScroll(View.FOCUS_DOWN);
}
});
scroll.scrollTo(0, scroll.getHeight());
для перехода вниз или scroll.smoothScrollTo(0, scroll.getHeight());
для более плавной прокрутки.
- person yuval; 27.04.2016
scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
- person Albert Vila Calvo; 27.05.2019
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)
}
val lastChild = getChildAt(0)
- person Ian Elvister; 12.03.2021
Иногда 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);
Что лучше всего сработало для меня, так это
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());
}
});
Увеличиваю, чтобы работать отлично.
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
больше не содержит этой ошибки, и вам следует ее использовать.
postDelayed
:)
- person ademar111190; 05.01.2016
Я пробовал это успешно.
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, scrollView.getHeight());
}
}, 1000);
Когда представление еще не загружено, вы не можете прокручивать его. Вы можете сделать это «позже» с помощью поста или вызова сна, как указано выше, но это не очень элегантно.
Лучше спланировать прокрутку и сделать это при следующем onLayout (). Пример кода здесь:
https://stackoverflow.com/a/10209457/1310343
Одна вещь, которую следует учитывать, - это то, что НЕ устанавливать. Убедитесь, что вашим дочерним элементам управления, особенно элементам EditText, не задано свойство RequestFocus. Это может быть одно из последних интерпретируемых свойств в макете, и оно переопределит настройки гравитации для своих родителей (макет или ScrollView).
Вот еще несколько способов прокрутки вниз
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()
}
Использование
Если вы scrollview уже выложили
my_scroll_view.scrollToBottom()
Если ваша прокрутка не закончена (например: вы прокручиваете вниз в методе Activity onCreate
...)
my_scroll_view.post {
my_scroll_view.scrollToBottom()
}
Не совсем ответ на вопрос, но мне нужно было прокрутить вниз, как только EditText получил фокус. Однако принятый ответ заставит ET сразу же потерять фокус (я полагаю, на 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();
}
}
});
На самом деле я обнаружил, что двойной вызов fullScroll помогает:
myScrollView.fullScroll(View.FOCUS_DOWN);
myScrollView.post(new Runnable() {
@Override
public void run() {
myScrollView.fullScroll(View.FOCUS_DOWN);
}
});
Возможно, это как-то связано с активацией метода post () сразу после выполнения первой (неудачной) прокрутки. Я думаю, что это происходит после любого предыдущего вызова метода myScrollView, поэтому вы можете попробовать заменить первый метод fullScroll () чем-нибудь еще, что может быть вам интересно.
Есть еще один классный способ сделать это с сопрограммами Kotlin. Преимущество использования сопрограммы по сравнению с обработчиком с исполняемым (post / postDelayed) состоит в том, что она не запускает дорогостоящий поток для выполнения отложенного действия.
launch(UI){
delay(300)
scrollView.fullScroll(View.FOCUS_DOWN)
}
Важно указать HandlerContext сопрограммы как пользовательский интерфейс, иначе отложенное действие не может быть вызвано из потока пользовательского интерфейса.
В этом случае использование scroll.scrollTo (0, sc.getBottom ()) не работает, используйте его с помощью scroll.post
Пример:
scroll.post(new Runnable() {
@Override
public void run() {
scroll.fullScroll(View.FOCUS_DOWN);
}
});
Одна из возможных причин, по которой scroll.fullScroll(View.FOCUS_DOWN)
может не работать, даже если он заключен в .post()
, заключается в том, что представление не размещено. В этом случае View.doOnLayout () может быть лучшим вариантом:
scroll.doOnLayout(){
scroll.fullScroll(View.FOCUS_DOWN)
}
Или что-то более продуманное для смелых душ: https://chris.banes.dev/2019/12/03/suspending-views/
Это работает мгновенно. Без задержки.
// wait for the scroll view to be laid out
scrollView.post(new Runnable() {
public void run() {
// then wait for the child of the scroll view (normally a LinearLayout) to be laid out
scrollView.getChildAt(0).post(new Runnable() {
public void run() {
// finally scroll without animation
scrollView.scrollTo(0, scrollView.getBottom());
}
}
}
}
Если ваш минимальный SDK составляет 23 или выше, вы можете использовать это:
View childView = findViewById(R.id.your_view_id_in_the_scroll_view)
if(childView != null){
scrollview.post(() -> scrollview.scrollToDescendant(childView));
}
Сочетание всех ответов помогло мне:
Функция расширения PostDelayed
private fun ScrollView.postDelayed(
time: Long = 325, // ms
block: ScrollView.() -> Unit
) {
postDelayed({block()}, time)
}
Расширение Функция measureScrollHeight
fun ScrollView.measureScrollHeight(): Int {
val lastChild = getChildAt(childCount - 1)
val bottom = lastChild.bottom + paddingBottom
val delta = bottom - (scrollY+ height)
return delta
}
Функция расширения ScrolltoBottom
fun ScrollView.scrollToBottom() {
postDelayed {
smoothScrollBy(0, measureScrollHeight())
}
}
Имейте в виду, что минимальная задержка должна быть не менее 325 мс, иначе прокрутка будет ошибочной (не до конца). Чем больше ваша дельта между текущей высотой и дном, тем больше должно быть время задержки.