Android:ScrollViewを最下部に強制


回答:


274

scroll.fullScroll(View.FOCUS_DOWN) また動作するはずです。

これを scroll.Post(Runnable run)

コトリンコード

scrollView.post {
   scrollView.fullScroll(View.FOCUS_DOWN)
}

6
それは何もしないようです、何か提案はありますか?私はonCreateで、後でボタンのonClickで試してみました。
RichardJohnn 2010

向きを変えてもうまくいかないようです。そうでなければその働き。
Prashant 2015年

1
呼び出す前にレイアウトサイズが変更されている場合、これは機能しません。代わりに投稿する必要があります。
MLProgrammer-CiM 2015

2
これ以下は、demarの回答を単純化するだけで、完全に膨らませるようにビューに少し時間を与えるまで機能しません。scrollView.postDelayed(new Runnable(){@Override public void run(){scrollView.fullScroll(View.FOCUS_UP // Or Down);}}、1000);
EngineSense 2015

scroll.fullScroll(View.FOCUS_DOWN)はフォーカスの変更につながります。フォーカス可能なビューが2つ以上ある場合(たとえば、2つのEditText)、奇妙な動作が発生します。下部にある別のソリューションを確認してください。
平和への情熱'19年

332

次のようにscroll.post内でコードを実行する必要があります。

scroll.post(new Runnable() {            
    @Override
    public void run() {
           scroll.fullScroll(View.FOCUS_DOWN);              
    }
});

4
現在の要素のフォーカスを失うことなく何らかの方法があります。これを行うと、現在の要素のフォーカスを失います(scrollviewとは異なります)
rkmax

2
これは、レイアウトがまだ測定およびレイアウトされていない場合(たとえば、onCreateで実行する場合)にのみ必要です。ボタンを押すような場合、.post()は必要ありません。
Patrick Boos、2015年

12
ScrollViewに焦点を当てたくない場合は、を使用scroll.scrollTo(0, scroll.getHeight());して下部にジャンプするかscroll.smoothScrollTo(0, scroll.getHeight());、スクロールをスムーズにすることができます
yuval

このコードはメモリリークの可能性はありませんか?アクティビティ(スクロール)ビューへの参照を保持する匿名のRunnableが作成されます。ランナブルがタスクを実行しているときにアクティビティが破棄されると、スクロールビューへの参照がリークされます。
Jenever

コトリンで:scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
アルバートビラカルボ

94

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拡張

fun ScrollView.scrollToBottom() {
    val lastChild = getChildAt(childCount - 1)
    val bottom = lastChild.bottom + paddingBottom
    val delta = bottom - (scrollY+ height)        
    smoothScrollBy(0, delta)
}

これでもう時間を無駄にする必要がなくなってよかったです。ちょうど私が必要なもの
アレクサンドルG

6
これにはもっと賛成票があるはずです。断然ベストアンサーです。
Eric Lange

1
これが、ここにある最良の答えです。
voidポインタ

1
このページの他のすべてのものを試してみました。これが機能した唯一のものであり、私のEditTextがフォーカスを失うことはありません。ありがとうございました。
Joel

キーボードが表示されているときに下にスクロールする必要がある場合は、このコードをこのライブラリと組み合わせます。魅力のように機能します。
wonsuc

47

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);

識別してくれてありがとう。postDelayedがより良いソリューションです。
Prashant 2018年

@Prashant :) :) :)
Ajay Shrestha

1
アクティビティが終了したらRunnableを処分する必要があることを覚えておいてください
FabioR '22

38

私にとって最も効果的だったのは

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());
     }
});

私はこれを試しましたが、ここのアルゴリズムは間違っています。下の私の答えを確認してください。
平和への情熱2016年

28

完全に機能するようにインクリメントします。

    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これ以上そのバグはないので、それを使用する必要があります。


3
2つ以上ではありませんが、これは私の電話(LG JellyBean 4.1.2 Optimus G)でうまく機能します。
Youngjae 2013年

9
scrollView.postDelayed(runnable、100)を使用しないのはなぜですか?
Matt Wolfe

1
当時の@MattWolfeは、Androidの一部の古いバージョンでは機能しません。しかし、今日、この回答は非推奨になりました。
ademar111190 2014

4
神の愛のために、scrollView.postDelayed(runnable、100)を使用してください!:)
Alex Lockwood

1
私は@AlexLockwoodというメモを追加しました。人々がpostDelayed:)を使用することを願っています
ademar111190

4

私はそれを成功させました。

scrollView.postDelayed(new Runnable() {
    @Override
    public void run() {
        scrollView.smoothScrollTo(0, scrollView.getHeight());
    }
}, 1000);

3

ビューがまだロードされていない場合、スクロールできません。上記のようにpostまたはsleepコールで「後で」それを行うことができますが、これはあまりエレガントではありません。

スクロールを計画し、次のonLayout()で実行することをお勧めします。ここにサンプルコード:

https://stackoverflow.com/a/10209457/1310343


3

考慮すべき1つのことは、何を設定しないかです。子コントロール、特にEditTextコントロールにRequestFocusプロパティが設定されていないことを確認してください。これは、レイアウトで最後に解釈されたプロパティの1つであり、その親(レイアウトまたはScrollView)の重力設定をオーバーライドします。


3

下にスクロールする他のいくつかの方法があります

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()          
}

1

質問に対する答えは正確ではありませんが、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();
        }
    }
});

1

実際にfullScrollを2回呼び出すとうまくいくことがわかりました。

myScrollView.fullScroll(View.FOCUS_DOWN);

myScrollView.post(new Runnable() {
    @Override
    public void run() {
        myScrollView.fullScroll(View.FOCUS_DOWN);
    }
});

最初の(失敗した)スクロールを実行した直後のpost()メソッドのアクティブ化と関係がある可能性があります。この動作は、myScrollViewの以前のメソッド呼び出しの後に発生するので、最初のfullScroll()メソッドを、関連する可能性のある他の何かに置き換えてみることができます。


0

Kotlinコルーチンでこれを行う別のクールな方法があります。ハンドラーとランナブル(post / postDelayed)を対比させてコルーチンを使用する利点は、遅延アクションを実行するために高価なスレッドを起動しないことです。

launch(UI){
    delay(300)
    scrollView.fullScroll(View.FOCUS_DOWN)
}

コルーチンのHandlerContextをUIとして指定することが重要です。そうしないと、遅延アクションがUIスレッドから呼び出されない場合があります。


0

scroll.scrollTo(0、sc.getBottom())だけを使用していた場合は機能しません。scroll.postを使用してください。

例:

scroll.post(new Runnable() {
  @Override
  public void run() {
  scroll.fullScroll(View.FOCUS_DOWN);
  } 
});

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.