Giới hạn chiều cao của ListView trên Android


92

Tôi muốn hiển thị một nút dưới a ListView. Vấn đề là, nếu ListViewđược mở rộng (các mục được thêm vào ...), nút sẽ bị đẩy ra khỏi màn hình.

Tôi đã thử một LinearLayoutvới trọng lượng (như được đề xuất trong Android: tại sao không có maxHeight cho Chế độ xem? ), Nhưng tôi đã sai trọng lượng hoặc đơn giản là nó không hoạt động.

Ngoài ra, tôi đã tìm thấy ở đâu đó gợi ý để sử dụng a RelativeLayout. Sau ListViewđó sẽ được đặt phía trên nút với android:layout_abovetham số.

Vấn đề với điều này là tôi không biết làm thế nào để định vị nút sau đó. Trong ví dụ mà tôi tìm thấy, Chế độ xem bên dưới ListViewđã được điều chỉnh bằng cách sử dụng android:layout_alignParentBottom, nhưng tôi không muốn nút của mình bám vào cuối màn hình.

Bất kỳ ý tưởng nào ngoài việc sử dụng phương pháp setHeight và một số tính toán không gian cần thiết?


Chỉnh sửa: Tôi nhận được rất nhiều câu trả lời hữu ích.

  • Giải pháp của bigstone & user639183 gần như hoạt động hoàn hảo. Tuy nhiên, tôi phải thêm một khoảng đệm / lề bổ sung vào cuối nút, vì nó vẫn sẽ bị đẩy ra khỏi màn hình một nửa (nhưng sau đó dừng lại)

  • Câu trả lời của Adinia chỉ với bố cục tương đối là ổn nếu bạn muốn nút cố định ở cuối màn hình. Nó không phải là những gì tôi dự định nhưng vẫn có thể hữu ích cho những người khác.

  • Giải pháp của AngeloS là giải pháp tôi đã chọn cuối cùng vì nó chỉ tạo ra các hiệu ứng mà tôi muốn. Tuy nhiên, tôi đã thực hiện hai thay đổi nhỏ đối với nút LinearLayoutxung quanh:

    • Đầu tiên, vì tôi không muốn có bất kỳ giá trị tuyệt đối nào trong bố cục của mình, tôi đã thay đổi android:layout_height="45px"thành wrap_content, điều này cũng hoạt động tốt.

    • Thứ hai, vì tôi muốn nút được căn giữa theo chiều ngang, chỉ được hỗ trợ bởi chiều dọc LinearLayout, tôi đã thay đổi android: orient = "vertical" thành "vertical".

    AngeloS cũng tuyên bố trong bài đăng đầu tiên của mình rằng anh ấy không chắc liệu các android:layout_weight="0.1"tham số LinearLayoutxung quanh ListViewcó bất kỳ tác dụng nào không; Tôi chỉ thử và nó thực sự làm! Nếu không, nút lại bị đẩy ra khỏi màn hình.


theo cách này, bố cục tương đối bên trong dài hơn màn hình, có thể thêm một bước android:layout_alignParentBottom="true". Nhưng rõ ràng hơn, bạn có muốn nút tiếp tục được gắn vào cuối ListView khi có ít mục không? Nếu có, hãy xem Rich nói gì.
bigstones

vâng, đó là những gì tôi muốn.
sứa

năm sau, bây giờ chúng tôi có chiều cao nhờ tối đa để ConstraintLayout: stackoverflow.com/questions/42694355/...
user1506104

Câu trả lời:


55

Tôi đã gặp vấn đề chính xác này và để giải quyết nó, tôi đã tạo hai vùng riêng biệt LinearLayoutsđể chứa ListViewButtontương ứng. Từ đó, tôi đặt cả hai vào một cái khác Linear Layoutvà đặt vùng chứa đó android:orientationthành vertical. Tôi cũng đặt trọng lượng của các LinearLayouttừng là nơi khắc ListViewđến 0.1nhưng tôi không biết nếu có bất kỳ tác dụng. Từ đó, bạn có thể đặt chiều cao của thùng chứa dưới cùng (có nút của bạn) thành bất kỳ chiều cao nào bạn muốn.

CHỈNH SỬA đây là ý tôi:

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

Giải pháp trên sẽ sửa nút ở dưới cùng của màn hình.


Để nút nổi ở cuối danh sách, hãy thay đổi chiều cao của ListView01thành 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>


Tôi xem nó như một thứ gì đó mô phỏng đối với <divcác thẻ trong HTML .. nó chỉ là một trình bao bọc và giải pháp này chắc chắn hoạt động.
AngeloS

Và liên quan đến chi phí, nó không khác nhiều so với những gì bạn đang làm với các bố cục tương đối .. ngay bây giờ bạn có một trình bao bọc bên ngoài và bạn đang lồng ghép một trình bao bọc khác .. tôi khuyên bạn chỉ nên lồng một trình bao bọc khác và chia nhỏ chế độ xem danh sách và nút thành hai vùng chứa tạo hiệu ứng ngăn xếp trong bố cục tuyến tính dọc. Tôi không thể nhấn mạnh rằng đây là một giải pháp làm việc.
AngeloS

1
ĐÚNG! những công việc này! điều quan trọng cần lưu ý, sự khác biệt duy nhất giữa giải pháp đầu tiên và giải pháp thứ hai của bạn là tuyến tính cần phải wrap_content, vì vậy tôi đã kết thúc với một loại khởi động được thiết lập: imgur.com/c9L1Z . Gửi bất kỳ ai khác nhận thấy điều này: trọng số là quan trọng, nhưng có thể có bất kỳ giá trị nào.
Sam

2
không cần phải gói tất cả các quan điểm như vậy - kiểm tra @ giải pháp Sparkle của
Richard Le Mesurier

Có cần đặt 45px hoặc một giá trị chính xác cho bố cục nút không? Tôi cần phải đặt wrap_content thay
Mario Velasco

65

Tôi đã giải quyết vấn đề này trong mã, chỉ đặt chiều cao của listview nếu nó có nhiều hơn 5 mục trong đó:

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

Lưu ý rằng tôi đã đặt chiều cao tối đa bằng 5,5 lần chiều cao của một mục, vì vậy người dùng sẽ biết chắc chắn rằng có một số thao tác cuộn phải làm! :)


1
Câu trả lời hay đấy. Với mã đó, tôi khám phá chiều cao của mục của mình và bây giờ tôi có thể đặt kích thước danh sách của mình để hiển thị số lần lặp tôi muốn. Cảm ơn.
Derzu

3
Đây là câu trả lời tốt nhất. Tại sao phải viết 50 dòng XML lồng nhau khi bạn có thể giải quyết vấn đề với 5 dòng mã?
Greg Ennis

Cảm ơn bạn @shaylh. Hoạt động hoàn hảo.
Anju

Mặc dù tôi đã làm sạch các giải pháp XML một cách độc đáo, nhưng cuối cùng tôi vẫn sử dụng ý tưởng này trong sản phẩm cuối cùng của mình.
Richard Le Mesurier

1
@JayR không bao giờ là quá muộn để nhận xét
Manza

21

Trong lần chỉnh sửa cuối cùng, bạn cũng phải thêm android:layout_above="@+id/butt1"mã ListView của mình.

Và để cho bạn (và tất cả những người ở đây đã thử một câu trả lời trước đó) rằng bạn thực sự không cần sử dụng nhiều hơn một RelativeLayout, đây là mã đã sửa của bạn :

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

kết quả , sử dụng một số danh sách ngẫu nhiên:
nhập mô tả hình ảnh ở đây


1
Cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn, nhưng việc cố định nút ở cuối màn hình không như tôi dự định. Nó phải nằm ở cuối ListView.
sứa

Thật vậy, có vẻ như lần này LinearLayouts có thể là giải pháp duy nhất cho những gì bạn muốn; Tôi đã thử các kết hợp khác nhau với RelativeLayouts và không có kết hợp nào thực sự hiệu quả :( ... Nhưng tôi rất vui vì bạn đã tìm thấy câu trả lời của mình.
Adinia

1
Cảm ơn bạn! Thật hoàn hảo!
Guicara

6

Sử dụng LinearLayout, đặt chiều cao của ListViewButtonđến wrap_contentvà thêm trọng lượng = 1 vào ListView. Điều này sẽ hoạt động như bạn muốn.
Và có, thiết lập layout_gravitycủa Buttonđểbottom


6

Đã tìm ra cách để thực hiện việc này mà không cần sử dụng các vùng chứa lồng nhau, lấy cảm hứng từ giải pháp của AngeloS.

Tôi đã sử dụng một LinearLayoutvới hướng thẳng đứng, có một ListViewvà một nút. Tôi đặt android:layout_weight="0.1"cho ListView.

Nó luôn quản lý để đưa nút vào cuối danh sách. Và nút không bị đẩy ra khỏi màn hình khi danh sách phát triển.

<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"
    />

2
Không, chỉ cần thử nó và nút vẫn ở cuối màn hình, nó không nằm ở cuối danh sách. :(
Adinia

@Adinia Điều này hoạt động hoàn hảo ít nhất là trên 4.4.3. Giải pháp tốt đẹp, Sparkle, nên có nhiều phiếu bầu hơn.
Richard Le Mesurier

Humm..có thể bạn có một số cài đặt khác trong bố cục của mình? Tôi vừa thử nghiệm lại trên Nexus 4 với 4.4.3 và nút nằm ở cuối bố cục, không phải trong danh sách, nó không dính vào danh sách.
Adinia

2
@ Richard Le Mesurier Thật vậy, với android:layout_height="wrap_content" cho LinearLayout, như trong giải pháp của bạn, nó đang làm việc một cách hoàn hảo, và không chỉ trên 4.4.3, nhưng kể từ Sparkle không đề cập đến nó, tôi đã thử nó với match_parenttrước đó.
Adinia

Cũng làm việc trên Pie. +1
Zubair Younas

5

RelativeLayout là một giải pháp, nếu bạn không muốn nút ở quá gần dưới cùng, bạn có thể thêm lề (đệm một nút sẽ làm hỏng nó vì nó sử dụng nền 9 miếng và nó đặt đệm riêng).

Nó sẽ giống như vậy nếu bạn sử dụng LinearLayout: cách để đạt được những gì bạn muốn là đặt ListViewchiều cao = 0 và cân nặng = 1 và cho chiều cao nút = wrap_content và trọng lượng = 0. (đặt cả hai thành wrap_content, như user639183 đã nói, sẽ không giới hạn ListViewchiều cao của).


Vâng, nó sẽ hạn chế ListView's chiều cao
ernazm

@ user639183 vừa thử, bạn nói đúng, tôi xin lỗi, tôi rất chắc chắn về điều đó.
bigstones

Tôi đã thay đổi trọng lượng theo đề xuất (trước đây, tôi có Trọng lượng ListView = 2 và trọng lượng nút = 1, tự hỏi tại sao điều này không hoạt động?) Hiệu ứng rất thú vị: nút bây giờ chỉ được đẩy một nửa ra khỏi màn hình. Trên thực tế, tôi có thể làm cho nó ở lại nơi tôi muốn bằng cách thêm một số "android: layout_marginBottom". Tuy nhiên, tôi cũng có thể thử phương pháp tiếp cận Maxims và xem cách đó có hiệu quả không.
sứa

@jellyfish: Tôi không biết, sự chắc chắn của tôi đã bị phá bỏ bởi @ user639183. Ý tưởng là toàn bộ chiều cao sẽ được chia sẻ bởi hai chế độ xem. Số lượng cổ phiếu họ nhận được tính theo trọng lượng của chúng, vì vậy 1-0 -> mọi thứ cho người đầu tiên (2-1 sẽ nhường 1/3 không gian cho người thứ hai). Tôi nghĩ rằng đặt wrap_content trên chế độ xem cuộn sẽ làm cho nó cao ngang với nội dung của nó. Tuy nhiên .. bạn đã đặt bố cục bên ngoài thành fill_parent chưa?
bigstones vào

Thật kỳ lạ khi một RelativeLayout lồng nhau (theo đề xuất của Maxim) không hoạt động. Tôi chỉ có thể gửi nó ở trên, như tôi đã có cảm giác tôi chỉ bỏ lỡ một cái gì đó ...
con sứa

2

Bạn có thể thực hiện công việc này bằng cách sử dụng các vùng chứa lồng nhau. Có thể bạn cần bọc Nút trong một hộp chứa thứ hai (bên trong) để nó chiếm nhiều không gian hơn và chỉ cần căn chỉnh Nút vào đầu của hộp đựng bên trong.

Có thể một cái gì đó như thế này:

Giao diện tương đối

- ListView

-- Giao diện tương đối

---- Cái nút

Sử dụng các tùy chọn căn chỉnh khác nhau trên hai vùng chứa, bạn sẽ có thể làm cho điều này hoạt động.


Tôi nghĩ rằng sử dụng relLayout là giải pháp tốt nhất, nhưng tôi thực sự không thể hiểu tại sao bạn lại sử dụng các vùng chứa lồng nhau, khi bạn chỉ có thể sử dụng một cái gì đó như android:layout_marginTop="30dip" cho Nút, nếu bạn muốn có thêm không gian giữa Danh sách và Nút chẳng hạn.
Adinia

trong câu hỏi, OP đã nói rằng nếu anh ta thực hiện đúng vị trí của nút so với ListView, nó sẽ tắt màn hình khi ListView phát triển đủ cao. Trong những trường hợp đó, bạn phải gặp khó khăn với các thùng chứa lồng nhau
Rich

2

Đây là cách sạch sẽ nhất để làm điều đó:

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

Nó tương tự như giải pháp của Angelos nhưng bạn không cần tuyến tính bao bọc ListView. Ngoài ra, bạn có thể sử dụng FrameLayout nhẹ hơn so với LinearLayout để kết thúc Nút.


2

Ý tưởng được phác thảo trong các giải pháp rất tốt bằng cách:

Cả hai dường như hoạt động hoàn hảo ít nhất là trên v4.4.3.

Tôi vẫn phải dành thời gian viết mã thử nghiệm để kiểm tra và xác nhận từng phương pháp. Dưới đây là mã kiểm tra độc lập, tối thiểu được yêu cầu.


Bố cục dựa trên giải pháp của Sparkle, vì nó chứa ít bố cục lồng nhau hơn. Cũng đã được cập nhật để phản ánh các kiểm tra LINT hiện tại.

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

Hoạt động cung cấp mã bảng soạn sẵn để kiểm tra giải pháp cho chính bạn.

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

Vui lòng thêm hoặc cải thiện vì đây là "wiki cộng đồng".


1

Cố gắng sử dụng RelativeLayout với nút ở dưới cùng. Đặt chiều cao của bố cục là "wrap_content". Tôi đã không thử nó. Chỉ là ý tưởng


Tôi thực sự nghĩ rằng điều này sẽ hoạt động, nhưng có vẻ như nó không. Bố cục lấp đầy tất cả không gian còn lại, như thể chiều cao được đặt thành match_parent. Không có ý nghĩa, mặc dù.
sứa

1

trong LinearLayout, chỉ cần thêm android:layout_weight="1"vào ListView của bạn


0

Sau đây là những gì đã làm việc cho tôi ...

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


                }

Lưu ý: Params.width = ... Cũng cần được thiết lập ...

Ví dụ trên là khi bạn sử dụng TableRow và ListView bên trong TableRow ...


0

bọc nội dung trong bố cục tuyến tính

trong Chế độ xem danh sách, hãy thêm: android: layout_weight = "1"

trong Nút đặt chiều cao cố định của bạn

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

0

Nếu bạn muốn nội dung bên dưới chế độ xem danh sách di chuyển xuống khi các phần tử được thêm vào danh sách, hãy thử giải pháp này:

Thêm phần đệm tích cực vào cuối chế độ xem danh sách và phần đệm phủ định vào đầu "chân trang". Điều này sẽ hoạt động trong bố cục tuyến tính hoặc bố cục tương đối.

<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"/>

-1

Vì không có thuộc tính MaxHeight, cách tốt nhất của bạn là đặt chiều cao của ListView thành một giá trị đã đặt hoặc sử dụng wrap_content.


-2

Tôi đã giải quyết vấn đề này bằng cách đặt ListView bên trong ScrollView. Lint không thích nó, nhưng bằng cách thêm minHeight và đặt fillViewport thành true, tôi đã có một kết quả tốt đẹp.

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

Tôi đã thử cách tiếp cận này, ngay cả khi bạn giới hạn kích thước của listview, nó không cho phép tôi cuộn listview, điều này thật khó xử. Bạn có biết tại sao?
Eduardo

7
KHÔNG BAO GIỜ đặt ListView bên trong ScrollView!
jenzz

Có, không bao giờ đặt ListView bên trong ScrollView. Nhưng với "bản hack" này thì có thể ... stackoverflow.com/a/14577399/1255990
Leonardo Cardoso
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.