Batasi ketinggian ListView di Android

92

Saya ingin menunjukkan tombol di bawah a ListView. Masalahnya adalah, jika ListViewdiperpanjang (item ditambahkan ...), tombol didorong keluar dari layar.

Saya mencoba LinearLayoutdengan bobot (seperti yang disarankan di Android: mengapa tidak ada maxHeight untuk Tampilan? ), Tetapi entah bobot saya salah atau tidak berhasil.

Juga, saya menemukan petunjuk di suatu tempat untuk menggunakan file RelativeLayout. The ListViewkemudian akan ditetapkan di atas tombol dengan android:layout_aboveparam.

Masalah dengan ini adalah saya tidak tahu bagaimana memposisikan tombol sesudahnya. Dalam contoh yang saya temukan, Tampilan di bawah ListViewtelah disesuaikan menggunakan android:layout_alignParentBottom, tetapi saya tidak ingin tombol saya menempel di bagian bawah layar.

Adakah ide selain menggunakan metode setHeight dan beberapa penghitungan ruang yang dibutuhkan?


Sunting: Saya mendapat banyak jawaban yang berguna.

  • Solusi bigstone & user639183 hampir bekerja dengan sempurna. Namun, saya harus menambahkan bantalan / margin ekstra ke bagian bawah tombol, karena masih akan didorong setengah jalan keluar dari layar (tetapi kemudian berhenti)

  • Jawaban Adinia dengan tata letak relatif hanya boleh jika Anda ingin tombol tetap di bagian bawah layar. Bukan itu yang saya inginkan tapi mungkin masih berguna untuk orang lain.

  • Solusi AngeloS adalah yang saya pilih di akhir karena baru saja menciptakan efek yang saya inginkan. Namun, saya membuat dua perubahan kecil di LinearLayoutsekitar tombol:

    • Pertama, karena saya tidak ingin memiliki nilai absolut dalam tata letak saya, saya mengubahnya android:layout_height="45px"ke wrap_content, yang juga berfungsi dengan baik.

    • Kedua, karena saya ingin tombolnya berada di tengah secara horizontal, yang hanya didukung oleh vertikal LinearLayout, saya mengubah android: orientasi = "horizontal" menjadi "vertikal".

    AngeloS juga menyatakan di posting awalnya bahwa dia tidak yakin apakah android:layout_weight="0.1"param di LinearLayoutsekitar ListViewberpengaruh; Saya baru saja mencoba dan ternyata benar! Tanpa, tombol akan didorong keluar dari layar lagi.

ubur-ubur
sumber
Dengan cara ini tata letak relatif bagian dalam berkembang lebih panjang dari layar, satu langkah dapat ditambahkan android:layout_alignParentBottom="true". Tetapi untuk memperjelas, apakah Anda ingin tombol tetap terpasang di bagian bawah ListView saat item hanya ada sedikit? Jika ya, lihat apa yang dikatakan Rich.
batu besar
ya, itulah yang saya inginkan.
ubur
bertahun-tahun kemudian, kami sekarang memiliki tinggi maksimum berkat ConstraintLayout: stackoverflow.com/questions/42694355/…
user1506104

Jawaban:

55

Saya memiliki masalah yang tepat ini dan untuk mengatasinya saya membuat dua terpisah LinearLayoutsuntuk menampung ListViewdan Buttonmasing - masing. Dari sana saya memasukkan keduanya ke dalam yang lain Linear Layoutdan mengatur wadah itu android:orientationke vertical. Saya juga mengatur bobot LinearLayoutyang ditampung ListViewke 0.1tapi saya tidak tahu apakah itu berpengaruh. Dari sana, Anda dapat mengatur ketinggian wadah bawah (yang memiliki tombol Anda) ke ketinggian apa pun yang Anda inginkan.

EDIT ini yang saya maksud:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="0.1"
    android:orientation="horizontal">

    <ListView
        android:id="@+id/ListView01"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:dividerHeight="2px"></ListView>
</LinearLayout>

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="45px"
    android:background="@drawable/drawable"
    android:orientation="horizontal">

    <Button
        android:id="@+id/moreButton"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentRight="true"
        android:background="@drawable/btn_more2"
        android:paddingRight="20px" />

</LinearLayout>

Solusi di atas akan memperbaiki tombol di bagian bawah layar.


Agar tombol mengapung di bagian bawah daftar, ubah ketinggian ListView01menjadi wrap_content:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="0.1"
    android:orientation="horizontal">

    <ListView
        android:id="@+id/ListView01"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:dividerHeight="2px"></ListView>
</LinearLayout>

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="45px"
    android:background="@drawable/drawable"
    android:orientation="horizontal">

    <Button
        android:id="@+id/moreButton"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentRight="true"
        android:background="@drawable/btn_more2"
        android:paddingRight="20px" />
</LinearLayout>

AngeloS
sumber
Saya melihatnya sebagai sesuatu yang mirip dengan <divtag di HTML .. ini hanya pembungkus dan solusi ini pasti berhasil.
AngeloS
Dan berkaitan dengan overhead, itu tidak jauh berbeda dari apa yang Anda lakukan dengan tata letak relatif .. saat ini Anda memiliki satu pembungkus outter, dan Anda menumpuk yang lain .. saya menyarankan Anda hanya membuat satu sarang lagi dan membagi tampilan daftar dan tombol menjadi dua wadah yang menciptakan efek tumpukan dalam tata letak linier vertikal. Saya tidak bisa cukup menekankan bahwa ini adalah solusi yang berhasil.
AngeloS
1
IYA! ini bekerja! penting untuk dicatat, satu-satunya perbedaan antara solusi pertama dan kedua adalah kebutuhan linearlayout untuk wrap_content, jadi saya berakhir dengan pengaturan jenis awal: imgur.com/c9L1Z . Toa orang lain yang menemukan ini: pembobotan itu penting, tetapi dapat mengambil nilai apa pun.
Sam
2
tidak perlu membungkus semua pandangan seperti itu - lihat solusi @ Sparkle
Richard Le Mesurier
Apakah perlu meletakkan 45px atau nilai yang tepat untuk tata letak tombol? Saya harus meletakkan wrap_content sebagai gantinya
Mario Velasco
65

Saya memecahkan masalah ini dalam kode, mengatur ketinggian listview hanya jika memiliki lebih dari 5 item di dalamnya:

if(adapter.getCount() > 5){
        View item = adapter.getView(0, null, listView);
        item.measure(0, 0);         
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, (int) (5.5 * item.getMeasuredHeight()));
        listView.setLayoutParams(params);
}

Perhatikan bahwa saya menyetel tinggi maksimal menjadi 5,5 kali tinggi satu item, sehingga pengguna akan tahu pasti ada beberapa pengguliran yang harus dilakukan! :)

ssst
sumber
1
Jawaban bagus. Dengan kode itu saya menemukan tinggi item saya, dan sekarang saya dapat mengatur ukuran daftar saya untuk menunjukkan berapa banyak iten yang saya inginkan. Terima kasih.
Derzu
3
Ini jawaban terbaik. Mengapa menulis 50 baris XML bersarang ketika Anda dapat menyelesaikan masalah dengan 5 baris kode?
Greg Ennis
Terima kasih @shaylh. Bekerja dengan sempurna.
Anju
Meskipun saya membersihkan solusi XML dengan baik, saya tetap menggunakan ide ini di produk akhir saya.
Richard Le Mesurier
1
@JayR tidak ada kata terlambat untuk berkomentar
Manza
21

Pada suntingan terakhir Anda, Anda hanya perlu menambahkan android:layout_above="@+id/butt1" kode ListView Anda.

Dan untuk menunjukkan kepada Anda (dan semua orang di sini yang mencoba jawaban sebelumnya) bahwa Anda benar-benar tidak perlu menggunakan lebih dari satu RelativeLayout, berikut adalah kode Anda yang telah diperbaiki :

   <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/bkg">
    <TextView
        android:id="@+id/textView1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="TextView1"
        android:layout_alignParentTop="true">
    </TextView>
    <TextView
        android:id="@+id/textView2"
        android:layout_below="@+id/textView1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="TextView2"
        android:layout_centerHorizontal="true">
    </TextView>
    <Button
        android:id="@+id/butt1"
        android:text="string/string3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true">
    </Button>
    <ListView
        android:id="@+id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="2dip"
        android:layout_marginBottom="2dip"
        android:drawSelectorOnTop="false"
        android:visibility="visible"
        android:layout_below="@+id/textView2"
        android:layout_above="@+id/butt1" />
    </RelativeLayout>

dan hasilnya , menggunakan beberapa daftar acak:
masukkan deskripsi gambar di sini

Adinia
sumber
1
Terima kasih banyak atas bantuan Anda, tetapi memperbaiki tombol di bagian bawah layar bukanlah yang saya inginkan. Ini seharusnya berada di bagian bawah ListView.
ubur
Memang, kali ini LinearLayouts mungkin satu-satunya solusi untuk apa yang Anda inginkan; Saya sudah mencoba kombinasi yang berbeda dengan RelativeLayouts, dan tidak ada yang benar-benar berhasil :( ... Tapi saya senang Anda menemukan jawaban Anda.
Adinia
1
Terima kasih! Itu sempurna!
Guicara
6

Menggunakan LinearLayout, atur tinggi Anda ListViewdan Buttonke wrap_contentdan tambahkan berat = 1 ke ListView. Ini harus bekerja sesuai keinginan Anda.
Dan ya, mengatur layout_gravitydari Buttonuntukbottom

ernazm.dll
sumber
6

Menemukan cara untuk melakukan ini tanpa menggunakan wadah bersarang, terinspirasi dari solusi AngeloS.

Saya menggunakan a LinearLayoutdengan orientasi vertikal, yang memiliki ListViewtombol dan. Saya mengatur android:layout_weight="0.1"untuk ListView.

Itu berhasil membuat tombol menempel di bagian bawah daftar selalu. Dan tombol tidak bisa ditekan dari layar saat daftar bertambah.

<ListView
    android:id="@+id/notes_list"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="0.1"        
    />

<Button
    android:id="@+id/create_note_btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"        
    android:onClick="onCreateButtonClicked"
    android:text="@string/create_notes"
    />
Berkilau
sumber
2
Tidak, coba saja dan tombolnya tetap di bagian bawah layar, tidak berada di bagian bawah daftar. :(
Adinia
@Adinia Ini bekerja dengan sempurna setidaknya pada 4.4.3. Solusi bagus, Sparkle, harusnya memiliki lebih banyak suara.
Richard Le Mesurier
Humm..mungkin Anda memiliki beberapa pengaturan lain dalam tata letak Anda? Saya baru saja menguji lagi pada Nexus 4 dengan 4.4.3, dan tombol tetap berada di bagian bawah tata letak, bukan dari daftar, tidak menempel pada daftar.
Adinia
2
@Richard Le Mesurier Memang, dengan android:layout_height="wrap_content" untuk LinearLayout, seperti dalam solusi Anda, ini berfungsi dengan sempurna, dan tidak hanya pada 4.4.3, tetapi karena Sparkle tidak menyebutkannya, saya mencobanya match_parentsebelumnya.
Adinia
Mengerjakan Pie juga. +1
Zubair Younas
5

RelativeLayout adalah solusinya, jika Anda tidak ingin tombol berada terlalu dekat dengan bagian bawah Anda dapat menambahkan margin (padding tombol akan merusaknya karena menggunakan latar belakang 9-patch, dan mengatur paddingnya sendiri).

Ini akan sama jika Anda menggunakan a LinearLayout: cara untuk mencapai apa yang Anda inginkan adalah dengan menyetel ListViewke tinggi = 0 dan berat = 1, dan untuk tombol tinggi = isi_bungkus dan berat = 0. (menyetel keduanya ke wrap_content, seperti yang dikatakan user639183, tidak akan membatasi ListViewtinggi).

batu besar
sumber
Ya, itu akan membatasi ListViewketinggian
ernazm
@ user639183 baru saja mencoba, Anda benar Maafkan saya, saya sangat yakin tentang itu.
batu besar
Saya mengubah bobot seperti yang disarankan (sebelumnya, saya memiliki ListView weight = 2 dan button weight = 1, bertanya-tanya mengapa ini tidak berhasil?) Efeknya sangat menarik: tombol sekarang hanya ditekan setengah jalan keluar dari layar. Sebenarnya, saya bisa membuatnya tetap di tempat yang saya inginkan dengan menambahkan beberapa "android: layout_marginBottom". Namun, saya mungkin juga mencoba pendekatan Maxims dan melihat apakah itu berhasil juga.
ubur
@jellyfish: Saya tidak tahu, kepastian saya dibongkar oleh @ user639183. Idenya adalah bahwa seluruh ketinggian akan dibagi oleh dua pandangan. Jumlah saham yang mereka dapatkan ditentukan oleh bobot mereka, jadi 1-0 -> semuanya ke yang pertama (2-1 akan memberi 1/3 ruang ke yang kedua). Saya pikir pengaturan wrap_content pada tampilan bergulir akan membuatnya setinggi isinya. Namun .. apakah Anda menyetel tata letak luar ke fill_parent?
batu besar
Sungguh aneh bahwa RelativeLayout bersarang (seperti yang disarankan oleh Maxim) tidak berfungsi. Saya mungkin akan mempostingnya di atas, karena saya merasa saya melewatkan sesuatu ...
jellyfish
2

Anda mungkin dapat membuat ini bekerja menggunakan wadah bersarang. Mungkin saja Anda perlu membungkus Tombol dalam wadah kedua (dalam) sehingga membutuhkan lebih banyak ruang, dan cukup sejajarkan Tombol ke bagian atas wadah dalam.

Kemungkinan seperti ini:

RelativeLayout

- Tampilan Daftar

- RelativeLayout

---- Tombol

Dengan menggunakan opsi perataan yang berbeda pada dua wadah, Anda harus bisa membuatnya bekerja.

Kaya
sumber
Saya pikir menggunakan relativeLayout adalah solusi terbaik, tapi saya benar-benar tidak mengerti mengapa Anda menggunakan kontainer bersarang, ketika Anda bisa menggunakan sesuatu seperti android:layout_marginTop="30dip" untuk Tombol, jika Anda ingin lebih banyak ruang antara Daftar dan Tombol, misalnya.
Adinia
dalam pertanyaan, OP mengatakan bahwa jika dia secara ketat membuat posisi tombol relatif terhadap ListView, layar akan mati setelah ListView tumbuh cukup tinggi. Dalam kasus seperti itu, Anda harus menjadi rumit dengan wadah bersarang
Rich
2

Ini adalah cara terbersih untuk melakukannya:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
  <ListView
      android:id="@+id/ListView01"
      android:layout_width="fill_parent"
      android:layout_height="0dp"
      android:layout_weight="1"
      android:dividerHeight="2px">
  </ListView>
  <FrameLayout
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:background="@drawable/drawable"
      >
    <Button android:background="@drawable/btn_more2"
        android:id="@+id/moreButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:paddingRight="20px"
        />    
  </LinearLayout>
</LinearLayout>

Ini mirip dengan solusi Angelos tetapi Anda tidak memerlukan linearlayout yang membungkus ListView. Anda juga dapat menggunakan FrameLayout yang lebih ringan dibandingkan dengan LinearLayout untuk membungkus Tombol.

pengguna2994360
sumber
2

Idenya diuraikan dalam solusi yang sangat bagus oleh:

Keduanya tampaknya bekerja dengan sempurna setidaknya di v4.4.3.

Saya masih harus meluangkan waktu menulis kode tes untuk memeriksanya dan mengonfirmasi setiap metode. Di bawah ini adalah kode tes mandiri yang diperlukan.


Tata letak didasarkan pada solusi Sparkle, karena berisi lebih sedikit tata letak bersarang. Juga telah diperbarui untuk mencerminkan pemeriksaan LINT saat ini.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context="MainActivity" >

    <ListView
        android:id="@+id/listview"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <Button
        android:id="@+id/btn"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Grow List"
        tools:ignore="HardcodedText" />

</LinearLayout>

Aktivitas menyediakan kode boilerplate untuk menguji solusinya sendiri.

public class MainActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ListView listview = (ListView)findViewById(R.id.listview);
        final ArrayAdapter<String> adapter = 
                new ArrayAdapter<String>(this,
                                         android.R.layout.simple_list_item_1,
                                         new ArrayList<String>());
        adapter.setNotifyOnChange(true);
        listview.setAdapter(adapter);

        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                int count = adapter.getCount();
                adapter.add(String.valueOf(count));
                listview.setSelection(count);
            }
        });
    }
}

Jangan ragu untuk menambah atau meningkatkan karena ini adalah "wiki komunitas".

Richard Le Mesurier
sumber
1

Coba gunakan RelativeLayout dengan tombol di bagian bawah. Setel tinggi tata letak sebagai "wrap_content". Saya belum mencobanya. Ide saja

Pepatah
sumber
Saya benar-benar berpikir ini harus berhasil, tetapi tampaknya tidak. Tata letak mengisi semua ruang yang tersisa, seolah-olah ketinggian disetel ke match_parent. Tapi tidak masuk akal.
ubur
1

di LinearLayout, tambahkan saja android:layout_weight="1"ListView Anda

DawnYu
sumber
0

Berikut adalah apa yang berhasil untuk saya ...

 if(adapter.getCount() > 3){
                    View item = adapter.getView(0, null, impDateListView);
                    item.measure(0, 0);         
                    LayoutParams params = impDateListView.getLayoutParams();
                    params.width = LayoutParams.MATCH_PARENT;
                    params.height = 3 * item.getMeasuredHeight();
                    impDateListView.setLayoutParams(params);


                }

Catatan: The params.width = ... Perlu disetel juga ...

Contoh di atas adalah ketika Anda menggunakan TableRow dan ListView di dalam TableRow ...

Atul Dravid - Prajurit Putih Ltd.
sumber
0

membungkus konten dalam tata letak linier

dalam Tampilan Daftar tambahkan: android: layout_weight = "1"

di Tombol Anda mengatur ketinggian tetap

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical">

<ListView
    android:id="@+id/my_list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1">
</ListView>

 <Button
    android:text="Button"
    android:layout_width="match_parent"
    android:layout_height="50dp"/>

</LinearLayout>
Toma
sumber
0

Jika Anda ingin konten di bawah tampilan daftar bergerak ke bawah saat elemen ditambahkan ke daftar, coba solusi ini:

Tambahkan padding positif ke bagian bawah tampilan daftar dan padding negatif di bagian atas "footer". Ini akan berfungsi dalam tata letak linier atau tata letak relatif.

<ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="50dp"/>

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="-50dp"/>
Jenny Pushkarskaya
sumber
-1

Karena tidak ada atribut MaxHeight, taruhan terbaik Anda adalah mengatur ketinggian ListView ke nilai yang ditetapkan, atau menggunakan wrap_content.

Chris Cashwell
sumber
-2

Saya menyelesaikan ini dengan meletakkan ListView di dalam ScrollView. Lint tidak menyukainya, tetapi dengan menambahkan minHeight dan menyetel fillViewport ke true, saya mendapatkan hasil yang bagus.

    <ScrollView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="1dp"
        android:layout_marginRight="1dp"
        android:minHeight="100dp"
        android:fillViewport="true"
        android:fadeScrollbars="false"
        android:paddingTop="2dp" 
        android:orientation="vertical"
        android:scrollbarAlwaysDrawVerticalTrack="true" >

        <ListView
            android:id="@+id/workoutAElistRoutines"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="fill_vertical"
            android:background="@drawable/dialog_inner_border_tan"
            android:choiceMode="singleChoice"
            android:orientation="vertical"
            android:paddingLeft="3dp"
            android:paddingRight="3dp" >

        </ListView>
    </ScrollView>        
Jon
sumber
Saya mencoba pendekatan ini, meskipun membatasi ukuran tampilan daftar, tidak memungkinkan saya menggulir tampilan daftar, yang canggung. Apa kamu tahu kenapa?
Eduardo
7
JANGAN PERNAH meletakkan ListView di dalam ScrollView!
jenzz
Ya, jangan pernah meletakkan ListView di dalam ScrollView. Tetapi dengan "peretasan" ini, mungkin saja ... stackoverflow.com/a/14577399/1255990
Leonardo Cardoso