ScrollViewを一番下から開始したいと思います。方法はありますか?
scroll.fullScroll(View.FOCUS_DOWN)
も機能するはずです。
次のようにscroll.post内でコードを実行する必要があります。
scroll.post(new Runnable() {
@Override
public void run() {
scroll.fullScroll(View.FOCUS_DOWN);
}
});
scroll.fullScroll(View.FOCUS_DOWN)
はフォーカスの変更につながります。フォーカス可能なビューが複数ある場合、たとえば2つの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 Extension
fun ScrollView.scrollToBottom() {
val lastChild = getChildAt(childCount - 1)
val bottom = lastChild.bottom + paddingBottom
val delta = bottom - (scrollY+ height)
smoothScrollBy(0, delta)
}
時々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
にはそのバグはないため、使用する必要があります。
ビューがまだロードされていない場合、スクロールできません。上記のようにpostまたはsleep呼び出しで「後で」実行できますが、これはあまりエレガントではありません。
スクロールを計画し、次のonLayout()で実行することをお勧めします。ここにサンプルコード:
考慮すべきことの1つは、設定しないものです。子コントロール、特にEditTextコントロールには、RequestFocusプロパティが設定されていないことを確認してください。これは、レイアウト上の最後に解釈されたプロパティの1つであり、親(レイアウトまたは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()
}
使用
既にレイアウトされているスクロールビューの場合
my_scroll_view.scrollToBottom()
Scrollviewのレイアウトが完了していない場合(例:Activity onCreate
method ...で一番下までスクロールします)
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を2回呼び出すとうまくいくことがわかりました。
myScrollView.fullScroll(View.FOCUS_DOWN);
myScrollView.post(new Runnable() {
@Override
public void run() {
myScrollView.fullScroll(View.FOCUS_DOWN);
}
});
最初の(失敗した)スクロールを実行した直後のpost()メソッドのアクティブ化に関係している可能性があります。この動作は、myScrollViewでの以前のメソッド呼び出しの後に発生するため、最初のfullScroll()メソッドを、関連する可能性のある他のメソッドで置き換えることができます。
Kotlinコルーチンを使用してこれを行う別のクールな方法があります。 runnable(post/postDelayed)を持つHandlerとは対照的にコルーチンを使用する利点は、遅延アクションを実行するために高価なスレッドを起動しないことです。
launch(UI){
delay(300)
scrollView.fullScroll(View.FOCUS_DOWN)
}
コルーチンのHandlerContextをUIとして指定することが重要です。そうしないと、遅延アクションがUIスレッドから呼び出されない場合があります。
これらの場合、単にscroll.scrollTo(0、sc.getBottom())を使用していましたが機能しません。scroll.postを使用して使用してください
例:
scroll.post(new Runnable() {
@Override
public void run() {
scroll.fullScroll(View.FOCUS_DOWN);
}
});