Android: Gaya ScrollView ke bawah

200

Saya ingin ScrollView memulai dari jauh ke bawah. Ada metode?

Noah Seidman
sumber
1
Saya pikir itu hanya scrollTo (), ya saya baru saja memeriksa dokumen dev untuk ScrollView. Peasy mudah.
Noah Seidman

Jawaban:

274

scroll.fullScroll(View.FOCUS_DOWN) juga harus bekerja.

Masukkan ini ke dalam a scroll.Post(Runnable run)

Kode Kotlin

scrollView.post {
   scrollView.fullScroll(View.FOCUS_DOWN)
}
CommonsWare
sumber
6
Tampaknya tidak melakukan apa-apa, saran? Saya mencobanya di onCreate dan kemudian di onClick sebuah tombol.
RichardJohnn
Tampaknya tidak berhasil mengubah orientasi. Kalau tidak berfungsi.
Prashant
1
Ini tidak berfungsi jika ukuran tata letak telah berubah tepat sebelum memanggilnya. Itu perlu diposting sebagai gantinya.
MLProgrammer-CiM
2
Ini dan di bawah ini, tidak akan berfungsi sampai Anda memberi waktu pada pandangan untuk mengembang sepenuhnya, hanya menyederhanakan jawaban ademar. scrollView.postDelayed (Runnable baru () {@Override public void run () {scrollView.fullScroll (View.FOCUS_UP // Atau Down);}}, 1000);
EngineSense
scroll.fullScroll (View.FOCUS_DOWN) akan mengarah pada perubahan fokus. Itu akan membawa beberapa perilaku aneh ketika ada lebih dari satu tampilan yang bisa fokus, misalnya dua EditText. Periksa solusi lain yang saya berikan di bagian bawah.
peacepassion
332

Anda harus menjalankan kode di dalam scroll.post seperti ini:

scroll.post(new Runnable() {            
    @Override
    public void run() {
           scroll.fullScroll(View.FOCUS_DOWN);              
    }
});
hungson175
sumber
4
ada beberapa cara tanpa kehilangan fokus elemen saat ini, ketika saya melakukan ini saya kehilangan fokus elemen saya saat ini (berbeda dari scrollview)
rkmax
2
Ini diperlukan hanya dalam kasus di mana tata letak belum diukur dan ditata (misalnya jika Anda menjalankannya di onCreate). Dalam kasus seperti menekan tombol, .post () tidak diperlukan.
Patrick Boos
12
Jika Anda tidak ingin fokus pada ScrollView, Anda dapat menggunakan scroll.scrollTo(0, scroll.getHeight());untuk melompat ke bawah, atau scroll.smoothScrollTo(0, scroll.getHeight());untuk scroll yang lebih halus
yuval
Bukankah kode ini kemungkinan kebocoran memori? Sebuah Runnable anonim dibuat yang menyimpan referensi ke tampilan aktivitas (gulir). Jika aktivitas hancur ketika runnable menjalankan tugasnya, itu akan membocorkan referensi ke scrollview, bukan?
Jenever
Di Kotlin:scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
Albert Vila Calvo
94

scroll.fullScroll(View.FOCUS_DOWN)akan mengarah pada perubahan fokus. Itu akan membawa beberapa perilaku aneh ketika ada lebih dari satu tampilan yang bisa fokus, misalnya dua EditText. Ada cara lain untuk pertanyaan ini.

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

Ini bekerja dengan baik.

Perpanjangan Kotlin

fun ScrollView.scrollToBottom() {
    val lastChild = getChildAt(childCount - 1)
    val bottom = lastChild.bottom + paddingBottom
    val delta = bottom - (scrollY+ height)        
    smoothScrollBy(0, delta)
}
kedamaian
sumber
Senang saya tidak perlu membuang waktu lagi untuk ini. Apa yang saya butuhkan
Alexandre G
6
Ini seharusnya memiliki lebih banyak suara positif. Ini adalah jawaban terbaik sejauh ini.
Eric Lange
1
Ini adalah jawaban terbaik yang ada di sini.
void pointer
1
Sudah mencoba semua yang lain di halaman ini, bahkan barang-barang di bawah ini. Ini adalah satu-satunya hal yang berhasil, dan itu tidak menyebabkan EditText saya kehilangan fokus. Terima kasih.
Joel
Jika Anda perlu menggulir ke bawah saat keyboard muncul, gabungkan kode ini dengan perpustakaan ini . Bekerja seperti pesona.
wonsuc
47

Terkadang scrollView.post tidak berfungsi

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

TETAPI jika Anda menggunakan scrollView.postDelayed, itu pasti akan berfungsi

 scrollView.postDelayed(new Runnable() {
        @Override
        public void run() {
            scrollView.fullScroll(ScrollView.FOCUS_DOWN);
        }
    },1000);
Ajay Shrestha
sumber
terima kasih untuk identifikasi. postDelayed adalah solusi yang lebih baik.
Prashant
@Pashash :) :) :)
Ajay Shrestha
1
Ingatlah bahwa Anda harus membuang Runnable Anda saat Anda menyelesaikan aktivitas
FabioR
38

Apa yang paling berhasil bagi saya adalah

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());
     }
});
https
sumber
Saya mencoba ini, tetapi algoritma di sini salah. Tolong periksa jawaban saya di bagian bawah.
peacepassion
28

Saya menambahkan untuk bekerja dengan sempurna.

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

Catatan

Jawaban ini merupakan solusi untuk Android versi lama. Hari postDelayedini tidak ada lagi bug dan Anda harus menggunakannya.

ademar111190
sumber
3
Tidak di atas dua, tetapi ini berfungsi baik di ponsel saya (LG JellyBean 4.1.2 Optimus G).
Youngjae
9
Mengapa tidak menggunakan scrollView.postDelayed (runnable, 100)?
Matt Wolfe
1
@MattWolfe pada saat itu tidak berfungsi di beberapa versi lama Android. Tetapi hari ini jawaban ini sudah usang sama sekali.
ademar111190
4
Demi kasih tuhan, gunakan scrollView.postDelayed (runnable, 100)! :)
Alex Lockwood
1
Saya menambahkan catatan @AlexLockwood Saya harap orang-orang menggunakan postDelayed:)
ademar111190
4

Saya mencoba yang berhasil.

scrollView.postDelayed(new Runnable() {
    @Override
    public void run() {
        scrollView.smoothScrollTo(0, scrollView.getHeight());
    }
}, 1000);
Yusuf Yaşar
sumber
3

Saat tampilan belum dimuat, Anda tidak dapat menggulir. Anda dapat melakukannya 'nanti' dengan postingan atau panggilan tidur seperti di atas, tetapi ini tidak terlalu elegan.

Lebih baik untuk merencanakan gulir dan melakukannya pada onLayout berikutnya (). Contoh kode di sini:

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

jujur
sumber
3

Satu hal yang perlu dipertimbangkan adalah apa yang TIDAK diatur. Pastikan kontrol anak Anda, terutama kontrol EditText, tidak memiliki properti RequestFocus yang ditetapkan. Ini mungkin salah satu properti yang ditafsirkan terakhir pada tata letak dan itu akan menimpa pengaturan gravitasi pada orang tuanya (tata letak atau ScrollView).

Epsilon3
sumber
3

Berikut ini beberapa cara lain untuk menggulir ke bawah

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

Menggunakan

Jika Anda scrollview sudah ditata

my_scroll_view.scrollToBottom()

Jika scrollview Anda belum selesai ditata (mis: Anda gulir ke bawah dalam onCreatemetode Aktivitas ...)

my_scroll_view.post { 
   my_scroll_view.scrollToBottom()          
}
Phan Van Linh
sumber
1

Bukan jawaban untuk pertanyaan itu, tetapi saya perlu menggulir ke bawah segera setelah EditText mendapatkan fokus. Namun jawaban yang diterima akan membuat ET juga kehilangan fokus segera (menurut saya ScrollView).

Solusi saya adalah sebagai berikut:

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();
        }
    }
});
Teo Inke
sumber
1

Saya benar-benar menemukan bahwa memanggil fullScroll dua kali berhasil:

myScrollView.fullScroll(View.FOCUS_DOWN);

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

Mungkin ada hubungannya dengan aktivasi metode post () setelah melakukan scroll pertama (tidak berhasil). Saya pikir perilaku ini terjadi setelah pemanggilan metode sebelumnya pada myScrollView, jadi Anda dapat mencoba mengganti metode fullScroll () pertama dengan hal lain yang mungkin relevan bagi Anda.

BarLr
sumber
0

Menggunakan ada cara keren lain untuk melakukan ini dengan coroutine Kotlin. Keuntungan menggunakan coroutine yang bertentangan dengan Handler dengan runnable (post / postDelayed) adalah tidak menjalankan utas mahal untuk melakukan tindakan yang tertunda.

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

Penting untuk menentukan HandlerContext coroutine sebagai UI jika tidak, tindakan yang tertunda mungkin tidak dipanggil dari utas UI.

Phaestion
sumber
0

Dalam kasus itu hanya menggunakan scroll.scrollTo (0, sc.getBottom ()) tidak berfungsi, gunakan scroll.post

Contoh:

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

Salah satu kemungkinan alasan mengapa scroll.fullScroll(View.FOCUS_DOWN)mungkin tidak berfungsi bahkan dibungkus .post()adalah karena tampilan tidak ditata. Dalam hal ini, View.doOnLayout () bisa menjadi opsi yang lebih baik:

scroll.doOnLayout(){
    scroll.fullScroll(View.FOCUS_DOWN)
}

Atau, sesuatu yang lebih rumit untuk jiwa-jiwa pemberani: https://chris.banes.dev/2019/12/03/suspending-views/

Ghedeon
sumber