Android: ScrollView nach unten zwingen


200

Ich möchte, dass eine ScrollView ganz unten beginnt. Irgendwelche Methoden?


1
Ich denke, es ist nur scrollTo (), ja, ich habe gerade die Entwicklungsdokumente für ScrollView überprüft. Kinderleicht.
Noah Seidman

Antworten:


274

scroll.fullScroll(View.FOCUS_DOWN) sollte auch funktionieren.

Setzen Sie dies in ein scroll.Post(Runnable run)

Kotlin Code

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

6
Das scheint nichts zu tun, irgendwelche Vorschläge? Ich habe es bei onCreate und später beim onClick einer Schaltfläche versucht.
Richard Johnn

Es scheint nicht daran zu arbeiten, die Orientierung zu ändern. Ansonsten funktioniert es.
Prashant

1
Dies funktioniert nicht, wenn sich die Layoutgröße unmittelbar vor dem Aufruf geändert hat. Es muss stattdessen gepostet werden.
MLProgrammer-CiM

2
Dies und weiter unten funktioniert erst, wenn Sie der Ansicht etwas Zeit geben, sich vollständig aufzublasen. Dies vereinfacht lediglich die Antwort von Ademar. scrollView.postDelayed (new Runnable () {@Override public void run () {scrollView.fullScroll (View.FOCUS_UP // Or Down);}}, 1000);
EngineSense

scroll.fullScroll (View.FOCUS_DOWN) führt zu einer Änderung des Fokus. Dies führt zu einem merkwürdigen Verhalten, wenn mehr als eine fokussierbare Ansicht vorhanden ist, z. B. zwei EditText. Überprüfen Sie eine andere Lösung, die ich unten anbiete.
Friedensleidenschaft

332

Sie sollten den Code in der scroll.post wie folgt ausführen:

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

4
Es gibt einen Weg, ohne den Fokus des aktuellen Elements zu verlieren. Wenn ich dies tue, verliere ich den Fokus meines aktuellen Elements (anders als in der Bildlaufansicht)
rkmax

2
Dies ist nur in Fällen erforderlich, in denen das Layout noch nicht gemessen und gestaltet wurde (z. B. wenn Sie es in onCreate ausführen). In Fällen wie dem Drücken einer Taste wird .post () nicht benötigt.
Patrick Boos

12
Wenn Sie sich nicht auf die ScrollView konzentrieren möchten, können Sie verwenden, scroll.scrollTo(0, scroll.getHeight());um nach unten zu springen, oder scroll.smoothScrollTo(0, scroll.getHeight());für eine glattere Schriftrolle
yuval

Ist dieser Code nicht ein möglicher Speicherverlust? Es wird eine anonyme ausführbare Datei erstellt, die einen Verweis auf eine Aktivitätsansicht (Bildlaufansicht) enthält. Wenn die Aktivität zerstört wird, während die ausführbare Datei ihre Aufgabe ausführt, wird ein Verweis auf die Bildlaufansicht verloren, nicht wahr?
Jenever

In Kotlin:scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
Albert Vila Calvo

94

scroll.fullScroll(View.FOCUS_DOWN)wird zu einer Änderung des Fokus führen. Dies führt zu einem merkwürdigen Verhalten, wenn mehr als eine fokussierbare Ansicht vorhanden ist, z. B. zwei EditText. Es gibt einen anderen Weg für diese Frage.

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

Das funktioniert gut.

Kotlin-Erweiterung

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

Ich bin so froh, dass ich keine Zeit mehr damit verschwenden musste. Genau das, was ich brauchte
Alexandre G

6
Dies sollte mehr positive Stimmen haben. Es ist bei weitem die beste Antwort.
Eric Lange

1
Dies ist die beste Antwort hier.
Zeiger ungültig machen

1
Versuchte alles andere auf dieser Seite, sogar das Zeug weit darunter. Dies war das einzige, was funktioniert hat, und es führt nicht dazu, dass mein EditText den Fokus verliert. Danke dir.
Joel

Wenn Sie nach unten scrollen müssen, während die Tastatur angezeigt wird, kombinieren Sie diesen Code mit dieser Bibliothek . Klappt wunderbar.
Wonsuc

47

Manchmal funktioniert scrollView.post nicht

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

ABER wenn Sie scrollView.postDelayed verwenden, wird es definitiv funktionieren

 scrollView.postDelayed(new Runnable() {
        @Override
        public void run() {
            scrollView.fullScroll(ScrollView.FOCUS_DOWN);
        }
    },1000);

Danke für die Identifizierung. postDelayed ist eine bessere Lösung.
Prashant

@ Prashant :) :) :)
Ajay Shrestha

1
Denken Sie daran, dass Sie Ihre Runnable entsorgen müssen, wenn Sie die Aktivität beenden
FabioR

38

Was für mich am besten funktioniert hat, ist

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

Ich habe es versucht, aber der Algorithmus hier ist falsch. Überprüfen Sie bitte meine Antwort unten.
Friedensleidenschaft

28

Ich erhöhe, um perfekt zu arbeiten.

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

Hinweis

Diese Antwort ist eine Problemumgehung für wirklich alte Versionen von Android. Heute postDelayedhat der nicht mehr diesen Bug und du solltest ihn benutzen.


3
Nicht über zwei, aber das funktioniert gut in meinem Handy (LG JellyBean 4.1.2 Optimus G).
Youngjae

9
Warum nicht scrollView.postDelayed (lauffähig, 100) verwenden?
Matt Wolfe

1
@ MattWolfe zu der Zeit funktionierte nicht in einigen alten Versionen von Android. Aber heute ist diese Antwort überhaupt veraltet.
ademar111190

4
Verwenden Sie für die Liebe Gottes scrollView.postDelayed (lauffähig, 100)! :)
Alex Lockwood

1
Ich habe eine Notiz hinzugefügt @AlexLockwood Ich hoffe, die Leute benutzen die postDelayed:)
ademar111190

4

Ich habe das erfolgreich versucht.

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

3

Wenn die Ansicht noch nicht geladen ist, können Sie nicht scrollen. Sie können es "später" mit einem Post- oder Schlafanruf wie oben tun, aber dies ist nicht sehr elegant.

Es ist besser, die Schriftrolle zu planen und beim nächsten onLayout () auszuführen. Beispielcode hier:

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


3

Eine zu berücksichtigende Sache ist, was NICHT eingestellt werden soll. Stellen Sie sicher, dass für Ihre untergeordneten Steuerelemente, insbesondere für EditText-Steuerelemente, die RequestFocus-Eigenschaft nicht festgelegt ist. Dies ist möglicherweise eine der zuletzt interpretierten Eigenschaften des Layouts und überschreibt die Schwerkrafteinstellungen der übergeordneten Elemente (Layout oder ScrollView).


3

Hier sind einige andere Möglichkeiten, um nach unten zu scrollen

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

Verwenden von

Wenn Sie die Bildlaufansicht bereits angelegt haben

my_scroll_view.scrollToBottom()

Wenn Ihre Bildlaufansicht nicht fertig angelegt ist (z. B.: Sie scrollen in der Aktivitätsmethode nach unten onCreate...)

my_scroll_view.post { 
   my_scroll_view.scrollToBottom()          
}

1

Nicht genau die Antwort auf die Frage, aber ich musste nach unten scrollen, sobald ein EditText den Fokus bekam. Die akzeptierte Antwort würde jedoch dazu führen, dass der ET auch sofort den Fokus verliert (auf die ScrollView, nehme ich an).

Meine Problemumgehung war folgende:

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

Ich habe tatsächlich festgestellt, dass das zweimalige Aufrufen von fullScroll den Trick macht:

myScrollView.fullScroll(View.FOCUS_DOWN);

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

Dies hat möglicherweise etwas mit der Aktivierung der post () -Methode direkt nach dem ersten (nicht erfolgreichen) Bildlauf zu tun. Ich denke, dieses Verhalten tritt nach jedem vorherigen Methodenaufruf in myScrollView auf, sodass Sie versuchen können, die erste fullScroll () -Methode durch etwas anderes zu ersetzen, das für Sie relevant sein könnte.


0

Es gibt eine andere coole Möglichkeit, dies mit Kotlin-Coroutinen zu tun. Der Vorteil der Verwendung einer Coroutine im Gegensatz zu einem Handler mit einer ausführbaren Datei (post / postDelayed) besteht darin, dass kein teurer Thread zum Ausführen einer verzögerten Aktion gestartet wird.

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

Es ist wichtig, den HandlerContext der Coroutine als Benutzeroberfläche anzugeben, da sonst die verzögerte Aktion möglicherweise nicht vom UI-Thread aufgerufen wird.


0

In diesen Fällen würde nur scroll.scrollTo (0, sc.getBottom ()) nicht funktionieren, verwenden Sie es mit scroll.post

Beispiel:

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.