Bagaimana cara menggulir ke atas tata letak ScrollView yang panjang?

162

Untuk bagian dari aplikasi saya, pengguna disajikan dengan daftar nama dan diminta untuk mengelompokkannya sesuai keinginan mereka.

(Catatan, kode ListView disalin kata demi kata dari tutorial Android Views. Saya belum menyesuaikannya dengan kebutuhan saya, saya hanya mencoba mencari cara untuk membuat ini berfungsi.)

Layout dasar adalah LinearLayout, yang berisi ScrollView (disebut "groupsScrollView" dalam kode di bawah), yang berisi RelativeLayout. Saya memiliki beberapa tombol dan teks, dan kemudian ListView saya di bawahnya, yang menampilkan daftar nama. Semua ini lebih tinggi daripada area layar yang terlihat, sehingga pengguna diizinkan untuk menggulir secara vertikal untuk melihat semuanya.

Ini semua bekerja dengan indah, kecuali ketika halaman memuatnya selalu pra-gulir ke bagian atas ListView saya - di tengah halaman. Teks dan tombol yang saya buat yang memberi tahu pengguna apa yang harus dilakukan tidak terlihat.

Saya dapat mengambil layar dan menggulir ke atas, yang berfungsi dengan baik, tapi saya ingin layar memuat yang sudah digulir ke atas. Pengguna tidak perlu menggulir ke atas untuk melihat bagian atas halaman yang baru dimuat. Tetapi semua yang saya coba gulir secara terprogram ke bagian atas layar gagal.

Inilah metode onCreate saya:

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.groups);

    mainScrollView = (ScrollView)findViewById(R.id.groupsScrollView);

    //get the Bundle out of the Intent...
    Bundle extras = getIntent().getExtras();
    mNames = extras.getStringArray("mNames");

    setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, mNames));

    ListView lv = getListView();
    lv.setTextFilterEnabled(true);

    //This is the line I'm having issues with
    mainScrollView.pageScroll(View.FOCUS_UP);

    lv.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
            int position, long id) {
          // When clicked, show a toast with the TextView text
          Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
              Toast.LENGTH_SHORT).show();
        }
      });
}

Baris "mainScrollView.pageScroll (View.FOCUS_UP); adalah masalahnya. Itu tidak menyebabkan kesalahan, tetapi sepertinya tidak melakukan apa-apa. Saya sudah mencoba scrollTo (0,0), scrollDirection (View.FOCUS_UP ), dan segala sesuatu yang dapat saya pikirkan.

Karena saya tidak mendapatkan kesalahan, saya harus berasumsi bahwa perintah-perintah gulir ini benar-benar berfungsi, tetapi mereka menggulir ke bagian atas ListView, daripada bagian atas ScrollView atau RelativeLayout yang berisi itu. Ini tampaknya dikonfirmasi oleh deskripsi Google sendiri tentang metode scrollTo (int x, int y) di mana mereka mengatakan "Versi ini juga menjepit pengguliran ke batas-batas anak kita.".

Jadi untuk membuat pertanyaan panjang lebih lama, bagaimana cara memuat banyak tampilan di layar yang terdapat di dalam ScrollView, dan kemudian secara program gulir semuanya ke bagian atas halaman sehingga pengguna dapat berinteraksi dengannya?

Terima kasih!

Glenn
sumber

Jawaban:

264

Mencoba

mainScrollView.fullScroll(ScrollView.FOCUS_UP);

itu harus bekerja.

roomtek
sumber
Bekerja untuk saya juga. : D
Muntasir Aonik
1
Saya menemukan ScrollView # fullScroll () mengubah fokus saat ini. Saya diuji dengan EditText.
illusionJJ
175

Punya masalah yang sama, mungkin semacam bug.

Bahkan fullScroll(ScrollView.FOCUS_UP)dari jawaban yang lain tidak berhasil.
Satu-satunya hal yang berhasil bagi saya adalah menelepon scroll_view.smoothScrollTo(0,0)tepat setelah dialog ditampilkan.

Mohamed Hafez
sumber
Awalnya ini berhasil, tetapi kemudian ketika saya mencoba melakukannya berulang kali, pendekatan ini tidak memberikan hasil yang memuaskan.
JaydeepW
16
saya pecahkan dari scroll_view.smoothScrollTo (0,0), ketika kita memiliki listview di samping scrollview pada saat itu fullScroll (ScrollView.FOCUS_UP) tidak akan berfungsi.
Kirtikumar A.
1
scroll_view.smoothScrollTo (0,0) bekerja lebih baik untuk saya daripada mainScrollView.fullScroll (ScrollView.FOCUS_UP); TERIMA KASIH!
marienke
2
Pada sebagian besar perangkat fullScroll (ScrollView.FOCUS_UP) bekerja, tetapi pada Nexus 5 dan perangkat tempat saya memiliki ukuran teks yang dinaikkan - fullSscroll dipindahkan di bawah actionbar, smoothScrollTo (0,0) bekerja lebih baik di semua perangkat.
jt-gilkeson
Ini juga memiliki kelebihan fullScroll()di atas dalam menjaga item yang dipilih tetap dipilih setelah pindah. Dengan fullScroll(), item pertama dalam scrollview terpilih kembali setiap kali dalam kasus saya, terlepas dari item yang dipilih sebelum scroll bergerak ke atas.
GeertVc
97

Saya memiliki masalah yang sama dan ini memperbaikinya. Semoga ini bisa membantu Anda.

listView.setFocusable(false);
Miguel Palacios
sumber
3
Ini juga solusi yang tepat untuk tampilan kotak. Ini terjadi ketika Anda memiliki lebih dari satu elemen tampilan dalam grup tampilan yang sama, terutama tampilan daftar lain di atas daftar atau tampilan kotak. Karena adaptor memberitahukan utas UI, tampilan dibuat kembali dan gulir ke elemen pertama. Panggil saja listView.setFocusable (false) / gridView.setFocusable (false). Jika Anda melakukannya dari file xml, itu tidak akan berfungsi.
omersem
Solusi ini juga berfungsi dalam kasus saya, saya memiliki RecyclerView di dalam NestedScrollView sehingga otomatis bergulir ke bawah. Terima kasih sobat!
Nilesh Rathore
Saya harus menambahkan ini sebelum mengatur Adaptor tetapi setelah itu berfungsi seperti pesona. Terima kasih
Komunitas
penjelasan sempurna !!
Borja López
Terima kasih baik Miguel dan terutama omersem untuk penjelasannya, terutama bagian tentang cara kerjanya jika diatur dalam XML, ini menyelamatkan saya dari sakit kepala
buradd
53

scrollViewObject.fullScroll(ScrollView.FOCUS_UP)ini berfungsi dengan baik, tetapi hanya masalah dengan baris ini adalah bahwa, ketika data terisi dalam scrollViewObject, telah dipanggil segera. Anda harus menunggu beberapa milidetik hingga data terisi. Coba kode ini:

scrollViewObject.postDelayed(new Runnable() {
    @Override
    public void run() {
        scroll.fullScroll(ScrollView.FOCUS_UP);
    }
}, 600);

ATAU

 scrollViewObject.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        scrollViewObject.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        scrollViewObject.fullScroll(View.FOCUS_UP);
    }
});
Mohammad Imran
sumber
Saya berurusan dengan masalah yang sama di mana scrollview seharusnya bergulir ke bagian bawah halaman, memperbaikinya tepat!
Machine Tribe
1
Alih-alih menebak "keajaiban" x jumlah milidetik yang harus Anda tunggu, Lihat objek menawarkan metode posting (Runnable) yang bisa Anda gunakan yang akan memposting runnable setelah widget merender di UI.
Ryan
@Ryan: post (Runnable) selalu tidak berfungsi untuk saya di Nexus 5 (Genymotion)
Dika
posting (Runnable) mungkin tidak berfungsi karena jika Anda mengambil data setelah langkah penggalian tampilan, seperti gulir pertama bekerja dan kemudian data mengisi ke tampilan. Jadi, Anda harus menggunakan postDelayed (Runnable, dummyMillis) atau Anda harus menggunakan scroll.fullScroll (ScrollView.FOCUS_UP) setelah proses yang diisi data.
oguzhan
Solusi pertama Anda di mana Anda memberikan milis statis adalah pendekatan yang buruk.
Malwinder Singh
35

Masalah utama untuk semua solusi yang valid ini adalah bahwa Anda mencoba untuk naik ke atas ketika tidak digambar di layar.

Anda harus menunggu hingga tampilan gulir muncul di layar, lalu pindahkan ke atas dengan salah satu solusi ini. Ini adalah solusi yang lebih baik daripada postdelay, karena Anda tidak keberatan dengan penundaan itu.

    // Wait until my scrollView is ready
    scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Ready, move up
            scrollView.fullScroll(View.FOCUS_UP);
        }
    });
Pelanes
sumber
7
Solusi yang bagus - Jangan lupa menghapus Pendengar Global di akhir onGlobalLayoutpemanggilan metode scrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Nilhcem
30

Sangat mudah

    ScrollView scroll = (ScrollView) findViewById(R.id.addresses_scroll);
    scroll.setFocusableInTouchMode(true);
    scroll.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
CommonSenseCode
sumber
3
bagi saya itu tidak berhasil (baris ke-3), solusinya adalah: scroll.fullScroll (View.FOCUS_UP); (dengan menyertakan 2 baris pertama Anda)
medskill
@ medskill, Hai, apakah Anda menulis ini di file xml Anda? Saya menemukan bahwa ini hanya berfungsi di onCreate().
dikenal
@ imknownJ.Kimu Bekerja untukku dalam file xml
Paglian
Ini berhasil untuk saya. Anda membutuhkan baris kedua dan ketiga. Itu tidak akan berfungsi dalam XML untuk saya.
ET
2
Aku akan menciummu jika aku bisa! Menghabiskan 1-2 jam untuk ini. Yang terbaik saat menunggu dua tampilan daftar untuk dimuat dan tidak ingin fokus pada mereka. Menambahkannya ke onResume ().
John T
24

Saya menghadapi Masalah yang Sama Ketika saya menggunakan Scrollview di dalam View Flipper atau Dialog, case tersebut scrollViewObject.fullScroll(ScrollView.FOCUS_UP)mengembalikan false sehingga case scrollViewObject.smoothScrollTo(0, 0)berfungsi untuk saya

Gulir Fokus Atas

sravan
sumber
19
 final ScrollView scrollview = (ScrollView)findViewById(R.id.selected_place_layout_scrollview);

         scrollview.post(new Runnable() { 
                public void run() { 
                    scrollview.scrollTo(0, 0); 
                } 
            }); 
Mladen Rakonjac
sumber
9
runOnUiThread( new Runnable(){
   @Override
   public void run(){
      mainScrollView.fullScroll(ScrollView.FOCUS_UP);
   }
}
pengkhianat
sumber
9

Ini berhasil untuk saya

scroll_view.smoothScrollTo(0,0); // scroll to top of screen
Pankaj Talaviya
sumber
6

Ini adalah scroll paksa untuk scrollview :

            scrollView.post(new Runnable() {
                @Override
                public void run() {
                    scrollView.scrollTo(0, 0);
                    scrollView.pageScroll(View.FOCUS_UP);
                    scrollView.smoothScrollTo(0,0);
                }
            });
Hadi Note
sumber
4
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // Ready, move up
        scrollView.fullScroll(View.FOCUS_UP);
    }
});

sumber
1

Saya memperbaiki masalah saya di Kotlin seperti ini:

scrollview.isFocusableInTouchMode = true
scrollview.fullScroll(View.FOCUS_UP)
scrollview.smoothScrollTo(0,0)
Nyonya
sumber
0
@SuppressWarnings({ "deprecation", "unchecked" })
public void swipeTopToBottom(AppiumDriver<MobileElement> driver) 
                    throws InterruptedException {
       Dimension dimensions = driver.manage().window().getSize();
        Double screenHeightStart = dimensions.getHeight() * 0.30;
        int scrollStart = screenHeightStart.intValue();
        System.out.println("s="+scrollStart);
        Double screenHeightEnd = dimensions.getHeight()*0.90;
        int scrollEnd = screenHeightEnd.intValue();
        driver.swipe(0,scrollStart,0,scrollEnd,2000);
        CommonUtils.threadWait(driver, 3000);
    }
Ajeet Gour
sumber
ini pasti akan berjalan,
Ajeet Gour
Harap berikan penjelasan singkat tentang bagaimana jawaban ini menyelesaikan masalah.
Ayberk Özgür