【问题标题】:Limit height of ListView on AndroidAndroid上ListView的限制高度
【发布时间】:2011-07-26 03:28:43
【问题描述】:

我想在ListView 下显示一个按钮。问题是,如果ListView 被扩展(添加的项目......),按钮就会被推出屏幕。

我尝试了带有权重的LinearLayout(如Android: why is there no maxHeight for a View? 中所建议的那样),但要么我的权重错误,要么它根本不起作用。

另外,我在某处发现了使用RelativeLayout 的提示。然后ListView 将设置在带有android:layout_above 参数的按钮上方。

问题是我不知道之后如何定位按钮。在我找到的示例中,ListView 下方的视图是使用android:layout_alignParentBottom 调整的,但我不希望我的按钮紧贴屏幕底部。

除了使用 setHeight 方法和一些计算所需空间之外还有什么想法吗?


编辑: 我得到了很多有用的答案。

  • bigstone 和 user639183 的解决方案几乎完美运行。但是,我必须在按钮底部添加一个额外的填充/边距,因为它仍然会被推到屏幕的一半(但随后停止)

  • 如果您希望将按钮固定到屏幕底部,Adinia 仅使用相对布局的答案就可以了。这不是我想要的,但可能对其他人有用。

  • AngeloS 的解决方案是我最后选择的,因为它只是创建了我想要的效果。不过,我对按钮周围的LinearLayout 做了两个小改动:

    • 首先,由于我不想在布局中包含任何绝对值,因此我将android:layout_height="45px" 更改为wrap_content,这样也可以正常工作。

    • 其次,由于我希望按钮水平居中,仅垂直 LinearLayout 支持,因此我将 android:orientation="horizo​​ntal" 更改为 "vertical"。

    AngeloS 在他最初的帖子中还表示,他不确定 ListView 周围的 LinearLayout 中的 android:layout_weight="0.1" 参数是否有任何效果;我刚试过,它确实做到了!没有,按钮会再次被推出屏幕。

【问题讨论】:

  • 这样内部相对布局比屏幕长,一步可以添加android:layout_alignParentBottom="true"。但要明确一点,当项目很少时,您是否希望按钮保持连接到 ListView 的底部?如果是,看看 Rich 怎么说。
  • 是的,这就是我想要的。
  • 多年后,由于 ConstraintLayout,我们现在拥有最大高度:stackoverflow.com/questions/42694355/…

标签: android listview layout android-layout


【解决方案1】:

我在代码中解决了这个问题,只有当列表视图超过 5 个项目时才设置它的高度:

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

请注意,我将最大高度设置为单个项目高度的 5.5 倍,因此用户肯定会知道需要进行一些滚动操作! :)

【讨论】:

  • 不错的答案。使用该代码我发现了我的项目的高度,现在我可以设置我的列表的大小以显示我想要多少个项目。谢谢。
  • 这是最好的答案。 5行代码就能解决问题,为什么还要写50行嵌套XML?
  • 谢谢@shaylh。完美运行。
  • 尽管我很好地清理了 XML 解决方案,但我最终还是在我的最终产品中使用了这个想法。
  • @JayR 评论永远不会太晚
【解决方案2】:

我遇到了这个确切的问题,为了解决这个问题,我创建了两个单独的 LinearLayouts 来分别容纳 ListViewButton。从那里我将两者都放入另一个Linear Layout 并将该容器的android:orientation 设置为vertical。我还将容纳ListViewLinearLayout 的权重设置为0.1,但我不知道这是否有任何影响。从那里,您可以将底部容器(有您的按钮)的高度设置为您想要的任何高度。

编辑这就是我的意思:

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

上述解决方案将按钮固定在屏幕底部。


要让按钮浮动在列表底部,请将ListView01 的高度更改为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>

【讨论】:

  • 我认为它类似于 HTML 中的 &lt;div 标签。它只是一个包装器,这个解决方案绝对有效。
  • 关于开销,它与您使用相对布局所做的并没有太大区别.. 现在您有一个外部包装器,并且您正在嵌套另一个.. 我建议您只嵌套再将列表视图和按钮拆分为两个容器,在垂直线性布局中创建堆栈效果。我不能强调这是一个可行的解决方案。
  • 是的!这行得通!需要注意的是,您的第一个和第二个解决方案之间的唯一区别是线性布局需要 wrap_content,所以我最终设置了一个初始类型:imgur.com/c9L1Z。感谢其他发现这一点的人:权重很重要,但可以取任何值。
  • 不需要像这样包装所有视图 - 看看@Sparkle's solution
  • 按钮布局是否需要放置 45px 或精确值?我需要把 wrap_content 代替
【解决方案3】:

在您最后一次编辑时,您只需在 ListView 代码中添加android:layout_above="@+id/butt1"

为了向您(以及之前尝试过答案的所有人)展示您确实不需要使用多个 RelativeLayout,这里是您的更正代码

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

结果,使用一些随机列表:

【讨论】:

  • 非常非常感谢您的帮助,但是将按钮固定在屏幕底部只是不是我的本意。它应该在 ListView 的底部。
  • 确实,这一次 LinearLayouts 可能是您想要的唯一解决方案;我尝试过使用 RelativeLayouts 的不同组合,但没有一个真正奏效:( ...但我很高兴你找到了答案。
【解决方案4】:

使用LinearLayout,将ListViewButton 的高度设置为wrap_content,并为ListView 添加权重=1。这应该可以按您的意愿工作。
是的,将Buttonlayout_gravity 设置为bottom

【讨论】:

    【解决方案5】:

    受 AngeloS 解决方案的启发,找到了一种不使用嵌套容器的方法。

    我使用了一个垂直方向的LinearLayout,它有一个ListView 和一个按钮。我将android:layout_weight="0.1" 设置为ListView

    它设法让按钮始终停留在列表的底部。当列表增长时,按钮不会被推离屏幕。

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

    【讨论】:

    • 没有,刚试了一下,按钮一直在屏幕底部,不是在列表底部。 :(
    • @Adinia 这至少在 4.4.3 上完美运行。不错的解决方案,Sparkle,应该有更多的选票。
    • 嗯..也许您的布局中有其他设置?我刚刚在带有 4.4.3 的 Nexus 4 上再次进行了测试,按钮停留在布局的底部,而不是列表的底部,它不会粘在列表中。
    • @Richard Le Mesurier 事实上,android:layout_height="wrap_content" 用于 LinearLayout,就像在您的解决方案中一样,它运行良好,不仅在 4.4.3 上,而且由于 Sparkle 没有提到它,我之前用match_parent 试过。
    • 也在做馅饼。 +1
    【解决方案6】:

    RelativeLayout 是一个解决方案,如果您不希望按钮太靠近底部,您可以添加边距(填充按钮会破坏它,因为它使用 9-patch 背景,并且它设置了自己的填充)。

    如果你使用LinearLayout 也是一样:实现你想要的方法是将ListView 设置为 height=0 和 weight=1,并且对于按钮 height=wrap_content 和 weight= 0。 (将两者都设置为 wrap_content,正如 user639183 所说,不会限制 ListView 的高度)。

    【讨论】:

    • 是的,它会限制ListView的高度
    • @user639183 刚试过,你是对的对不起,我很确定。
    • 我按照建议更改了权重(之前我有 ListView weight=2 和 button weight=1,想知道为什么这不起作用?)效果很有趣:按钮现在只被按下离屏幕一半。实际上,我可以通过添加一些“android:layout_marginBottom”让它保持在我想要的位置。不过,我也可以尝试 Maxims 方法,看看是否也有效。
    • @jellyfish:我不知道,我的确定性被@user639183 摧毁了。这个想法是整个高度将由两个视图共享。他们获得的股份数量由他们的权重决定,所以 1-0 -> 第一个的所有内容(2-1 将给第二个 1/3 的空间)。我认为在滚动视图上设置 wrap_content 会使它与它的内容一样高。但是..您是否将外部布局设置为fill_parent?
    • 嵌套的RelativeLayout(Maxim 建议的)不起作用真的很奇怪。我可能只是把它贴在上面,因为我觉得我错过了一些东西......
    【解决方案7】:

    您可能可以使用嵌套容器来完成这项工作。您可能需要将 Button 包装在第二个(内部)容器中,以便占用更多空间,并将 Button 与内部容器的顶部对齐。

    可能是这样的:

    相对布局

    -- 列表视图

    -- 相对布局

    ---- 按钮

    在两个容器上使用不同的对齐选项,您应该可以让它工作。

    【讨论】:

    • 我认为使用 relativeLayout 是最好的解决方案,但我真的不明白你为什么要使用嵌套容器,如果你愿意的话,你可以只使用类似 android:layout_marginTop="30dip" 的按钮作为按钮例如,List 和 Button 之间的空间更大。
    • 在问题中,OP说如果他严格控制按钮相对于ListView的定位,一旦ListView长得足够高,它就会离开屏幕。在这种情况下,您必须对嵌套容器感到棘手
    【解决方案8】:

    这是最干净的方法:

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

    它类似于 Angelos 的解决方案,但您不需要包装 ListView 的线性布局。您也可以使用比 LinearLayout 更轻的 FrameLayout 来包裹 Button。

    【讨论】:

      【解决方案9】:

      非常好的解决方案中概述了这个想法:

      至少在 v4.4.3 上,它们似乎都能完美运行。

      我仍然不得不花一些时间编写测试代码来检查并确认每个方法。以下是所需的独立、最少的测试代码。


      布局基于 Sparkle 的解决方案,因为它包含的嵌套布局较少。也已更新以反映当前的 LINT 检查。

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

      Activity 提供样板代码来为您自己测试解决方案。

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

      请随意添加或改进,因为这是“社区 wiki”。

      【讨论】:

        【解决方案10】:

        在 LinearLayout 中,只需将 android:layout_weight="1" 添加到您的 ListView 中

        【讨论】:

          【解决方案11】:

          尝试在底部使用带有按钮的RelativeLayout。将布局的高度设置为“wrap_content”。 我没试过。只是想法

          【讨论】:

          • 我真的认为这应该可行,但似乎不行。布局填充了所有剩余的空间,就好像高度被设置为 match_parent。不过,这没有意义。
          【解决方案12】:

          以下对我有用...

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

          注意:params.width =...也需要设置...

          上面的例子是当你在TableRow里面使用TableRow和ListView时...

          【讨论】:

            【解决方案13】:

            在线性布局中包装内容

            在列表视图中添加: android:layout_weight="1"

            在您的 Button 中设置固定高度

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

            【讨论】:

              【解决方案14】:

              如果您希望列表视图下方的内容随着元素添加到列表中而下移,请尝试以下解决方案:

              在列表视图底部添加正填充,在“页脚”顶部添加负填充。这适用于线性布局或相对布局。

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

              【讨论】:

                【解决方案15】:

                由于没有 MaxHeight 属性,最好的办法是将 ListView 的高度设置为一个设定值,或者使用wrap_content

                【讨论】:

                  【解决方案16】:

                  我通过将 ListView 放在 ScrollView 中解决了这个问题。 Lint 不喜欢它,但是通过添加一个 minHeight 并将 fillViewport 设置为 true,我得到了一个不错的结果。

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

                  【讨论】:

                  • 我尝试了这种方法,即使它限制了列表视图的大小,它也不允许我滚动列表视图,这很尴尬。你知道为什么吗?
                  • 永远不要将 ListView 放入 ScrollView!
                  • 是的,永远不要将 ListView 放在 ScrollView 中。但有了这个“黑客”,就有可能......stackoverflow.com/a/14577399/1255990
                  猜你喜欢
                  • 2014-12-03
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-11-20
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-04-28
                  • 2017-06-10
                  • 1970-01-01
                  相关资源
                  最近更新 更多