Bisakah saya menggulir ScrollView secara terprogram di Android?

145

Apakah ada cara untuk menggulir ScrollViewprogram ke posisi tertentu?

Saya telah membuat dinamis TableLayoutyang ditempatkan di a ScrollView. Jadi saya ingin itu pada tindakan tertentu (seperti mengklik Tombol, dll.) Baris tertentu harus gulir secara otomatis ke posisi teratas.

Apa itu mungkin?

Arun Badole
sumber

Jawaban:

165
ScrollView sv = (ScrollView)findViewById(R.id.scrl);
sv.scrollTo(0, sv.getBottom());

atau

sv.scrollTo(5, 10);

Android
sumber
43
Menggabungkan jawaban ercu dan komentar yang dibuat di atasnya, cara terbaik tampaknya adalah:mScrollView.post(new Runnable() { public void run() { mScrollView.fullScroll(View.FOCUS_DOWN); } });
sparrowt
2
scrollTo () tidak akan menghasilkan keinginan resull. Seseorang harus menggunakan fullScroll ()
Amit Yadav
3
Gulir yang lebih bagus adalah dengan efek alami: sv.smoothScrollTo (5, 10)
ivan.panasiuk
205

Jawaban dari Pragna tidak selalu berhasil, coba ini:

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.scrollTo(0, mScrollView.getBottom());
        } 
});

atau

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.fullScroll(mScrollView.FOCUS_DOWN);
        } 
});

jika Anda ingin menggulir untuk memulai

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.fullScroll(mScrollView.FOCUS_UP);
        } 
});
ercu
sumber
28
Saya terbiasa mScrollView.fullScroll(mScrollView.FOCUS_DOWN);dengan kesuksesan.
amcc
3
Saya dapat mengkonfirmasi temuan Vanthel. mScrollView.fullScroll dalam sebuah tulisan runnable melakukan trik.
AlanKley
1
Luar biasa! Memang, tanpa Runnable, itu tidak berhasil. Sekarang berhasil! :)
Regis_AG
5
@HiteshDhamshaniya Jika Anda ingin gulir yang lancar, coba mScrollView.smoothScrollTo(0, mScrollView.getBottom());.
Mike Ortiz
1
Mengapa perlu di postsini?
Liuting
35

Saya ingin scrollView untuk menggulir langsung setelah onCreateView () (bukan setelah misalnya klik tombol). Untuk membuatnya berfungsi, saya perlu menggunakan ViewTreeObserver:

mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mScrollView.post(new Runnable() {
                public void run() {
                    mScrollView.fullScroll(View.FOCUS_DOWN);
                }
            });
        }
    });

Namun berhati-hatilah bahwa ini akan dipanggil setiap kali sesuatu ditata (misalnya jika Anda menetapkan tampilan tidak terlihat atau serupa) jadi jangan lupa untuk menghapus pendengar ini jika Anda tidak membutuhkannya lagi dengan:

public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) pada SDK Lvl <16

atau

public void removeOnGlobalLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) di SDK Lvl> = 16

Patrick Favre
sumber
23

Ada banyak jawaban bagus di sini, tetapi saya hanya ingin menambahkan satu hal. Terkadang Anda ingin menggulir ScrollView ke tampilan tata letak tertentu, alih-alih gulir penuh ke atas atau bawah.

Contoh sederhana: dalam formulir pendaftaran, jika pengguna mengetuk tombol "Daftar" ketika teks edit formulir tidak diisi, Anda ingin menggulir ke teks edit khusus itu untuk memberi tahu pengguna bahwa ia harus mengisi bidang itu.

Dalam hal ini, Anda dapat melakukan sesuatu seperti itu:

scrollView.post(new Runnable() { 
        public void run() { 
             scrollView.scrollTo(0, editText.getBottom());
        } 
});

atau, jika Anda menginginkan gulir yang lancar dan bukan gulir instan:

scrollView.post(new Runnable() { 
            public void run() { 
                 scrollView.smoothScrollTo(0, editText.getBottom());
            } 
    });

Jelas Anda dapat menggunakan jenis tampilan apa pun alih-alih Edit Teks. Perhatikan bahwa getBottom () mengembalikan koordinat tampilan berdasarkan tata letak induknya, sehingga semua tampilan yang digunakan di dalam ScrollView hanya boleh memiliki induk (misalnya Tata Letak Linear).

Jika Anda memiliki banyak orang tua di dalam anak ScrollView, satu-satunya solusi yang saya temukan adalah dengan memanggil requestChildFocus pada tampilan induk:

editText.getParent().requestChildFocus(editText, editText);

tetapi dalam hal ini Anda tidak dapat memiliki gulungan yang lancar.

Saya harap jawaban ini dapat membantu seseorang dengan masalah yang sama.

Mattia Ruggiero
sumber
1
@ JohnT Senang itu membantu Anda :)
Mattia Ruggiero
20

Gunakan sesuatu seperti ini:

mScrollView.scrollBy(10, 10);

atau

mScrollView.scrollTo(10, 10);
Srichand Yella
sumber
9

Coba gunakan scrollTometode More Info

bluefalcon
sumber
8

Jika Anda ingin menggulir secara instan maka Anda dapat menggunakan:

ScrollView scroll= (ScrollView)findViewById(R.id.scroll);
scroll.scrollTo(0, scroll.getBottom());

            OR

scroll.fullScroll(View.FOCUS_DOWN);

            OR

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

Atau jika Anda ingin menggulir dengan lancar dan perlahan sehingga Anda dapat menggunakan ini:

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();
    }
Maddy
sumber
apa yang catchblok itu lakukan?
John Sardinha
1
Blok penangkap adalah untuk menangkap pengecualian selama pengguliran jika ditemukan.
Maddy
5

** untuk menggulir ke ketinggian yang diinginkan. Saya telah menemukan beberapa solusi bagus **

                scrollView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        scrollView.scrollBy(0, childView.getHeight());
                    }
                }, 100);
Vikas Chauhan
sumber
4

Saya dapat ini untuk menggulir ke bagian bawah ScrollView (dengan TextView di dalamnya):

(Saya menempatkan ini pada metode yang memperbarui TextView)

final ScrollView myScrollView = (ScrollView) findViewById(R.id.myScroller);
    myScrollView.post(new Runnable() {
    public void run() {
        myScrollView.fullScroll(View.FOCUS_DOWN);
    }
});
Ohiovr
sumber
4

Ya kamu bisa.

Katakanlah Anda punya satu Layoutdan di dalamnya, Anda punya banyak Views. Jadi jika Anda ingin menggulir ke Viewprogram apa pun , Anda harus menulis cuplikan kode berikut:

Sebagai contoh:

content_main.xml

<ScrollView
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <Button
            android:id="@+id/btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/txtView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>
</ScrollView>

MainActivity.java

ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);
Button btn = (Button) findViewById(R.id.ivEventBanner);
TextView txtView = (TextView) findViewById(R.id.ivEditBannerImage);

Jika Anda ingin menggulir ke spesifik View, katakanlah txtview , dalam hal ini, cukup tulis:

scrollView.smoothScrollTo(txtView.getScrollX(),txtView.getScrollY());

Dan kamu sudah selesai.

Pankaj Lilan
sumber
3

Catatan: jika Anda sudah berada di utas, Anda harus membuat utas pos baru, atau tidak menggulir tinggi panjang baru sampai akhir penuh (untuk saya). Misalnya:

void LogMe(final String s){
    runOnUiThread(new Runnable() {
        public void run() {
            connectionLog.setText(connectionLog.getText() + "\n" + s);
            final ScrollView sv = (ScrollView)connectLayout.findViewById(R.id.scrollView);
            sv.post(new Runnable() {
                public void run() {
                    sv.fullScroll(sv.FOCUS_DOWN);
                    /*
                    sv.scrollTo(0,sv.getBottom());
                    sv.scrollBy(0,sv.getHeight());*/
                }
            });
        }
    });
}
djdance
sumber
3

Menambahkan jawaban lain yang tidak melibatkan koordinat.

Ini akan membuat tampilan yang Anda inginkan menjadi fokus (tetapi tidak ke posisi atas):

  yourView.getParent().requestChildFocus(yourView,yourView);

public void RequestChildFocus (Lihat anak, Lihat fokus)

child - Anak dari ViewParent ini yang ingin fokus. Tampilan ini akan berisi tampilan fokus. Belum tentu pandangan yang benar-benar memiliki fokus.

terfokus - Pandangan yang merupakan keturunan anak yang sebenarnya memiliki fokus

Swas_99
sumber
Apa yang saya butuhkan, terima kasih. Fokus permintaan pertama untuk Anda gulir tampilan dan kemudian scrollView.smoothScrollTo (0, scrollView.getChildAt (0) .getBottom ());
Vulovic Vukasin
3

cukup gulir halaman:

ScrollView sv = (ScrollView) findViewById(your_scroll_view);
sv.pageScroll(View.FOCUS_DOWN);
Kirill Vashilo
sumber
2

Semua orang memposting jawaban yang begitu rumit.

Saya menemukan jawaban yang mudah, untuk menggulir ke bawah, dengan baik:

final ScrollView myScroller = (ScrollView) findViewById(R.id.myScrollerView);

// Scroll views can only have 1 child, so get the first child's bottom,
// which should be the full size of the whole content inside the ScrollView
myScroller.smoothScrollTo( 0, myScroller.getChildAt( 0 ).getBottom() );

Dan, jika perlu, Anda bisa meletakkan baris kode kedua, di atas, ke dalam runnable:

myScroller.post( new Runnable() {
    @Override
    public void run() {
        myScroller.smoothScrollTo( 0, myScroller.getChildAt( 0 ).getBottom() );
    }
}

Saya butuh banyak penelitian dan bermain-main untuk menemukan solusi sederhana ini. Saya harap ini membantu Anda juga! :)

Nalorin
sumber
1

Saya menggunakan Runnable dengan sv.fullScroll (View.FOCUS_DOWN); Ini berfungsi sempurna untuk masalah langsung, tetapi metode itu membuat ScrollView mengambil Fokus dari seluruh layar, jika Anda membuat AutoScroll itu terjadi setiap kali, tidak ada EditText akan dapat menerima informasi dari pengguna, solusi saya menggunakan kode yang berbeda di bawah runnable:

sv.scrollTo (0, sv.getBottom () + sv.getScrollY ());

membuat hal yang sama tanpa kehilangan fokus pada pandangan-pandangan penting

Salam pembuka.

Sebasu
sumber
0

ini bekerja untuk saya

mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mScrollView.post(new Runnable() {
                public void run() {
                    mScrollView.fullScroll(View.FOCUS_DOWN);
                }
            });
        }
    });
ali asadi
sumber
0
private int totalHeight = 0;

ViewTreeObserver ScrollTr = loutMain.getViewTreeObserver();
ScrollTr.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            loutMain.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        } else {
            loutMain.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
        TotalHeight = loutMain.getMeasuredHeight();

    }
});

scrollMain.smoothScrollTo(0, totalHeight);
P. Patel
sumber
0
I had to create Interface

public interface ScrollViewListener {
    void onScrollChanged(ScrollViewExt scrollView, 
                         int x, int y, int oldx, int oldy);
}    

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;

public class CustomScrollView extends ScrollView {
    private ScrollViewListener scrollViewListener = null;
    public ScrollViewExt(Context context) {
        super(context);
    }

    public CustomScrollView (Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public CustomScrollView (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setScrollViewListener(ScrollViewListener scrollViewListener) {
        this.scrollViewListener = scrollViewListener;
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (scrollViewListener != null) {
            scrollViewListener.onScrollChanged(this, l, t, oldl, oldt);
        }
    }
}




<"Your Package name ".CustomScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusableInTouchMode="true"
    android:scrollbars="vertical">

    private CustomScrollView scrollView;

scrollView = (CustomScrollView)mView.findViewById(R.id.scrollView);
        scrollView.setScrollViewListener(this);


    @Override
    public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) {
        // We take the last son in the scrollview
        View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1);
        int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()));

        // if diff is zero, then the bottom has been reached
        if (diff == 0) {
                // do stuff
            //TODO keshav gers
            pausePlayer();
            videoFullScreenPlayer.setVisibility(View.GONE);

        }
    }
Keshav Gera
sumber