如果兄弟视图较大,则使用MATCH_PARENT,如果兄弟视图较小,则使用WRAP_CONTENT。

12

在布局中我有两个视图,分别称之为视图A视图B

┌──────┐
│┌─┐┌─┐│
││A││B││
│└─┘└─┘│
└──────┘

父布局(包括视图A和视图B)的高度为“WRAP_CONTENT”。
在这里,视图B的高度为“WRAP_CONTENT”。也就是说,它的高度可以根据内容进行更改。
我想做的是:
1. 如果视图A的内容比视图B的内容短,则将视图A的高度设置为视图B的高度。 2. 如果视图A的内容比视图B的内容高,则将视图A的高度设置为其自身内容的高度。
所以,
①如果视图B的内容较高,则将视图A的高度设置为视图B的高度。
       ┌──────┐      ┌──────┐
       │┌─┐┌─┐│      │┌─┐┌─┐│
       ││ ││ ││      ││A││ ││
I want ││A││B││, not │└─┘│B││.
       ││ ││ ││      │   │ ││
       │└─┘└─┘│      │   └─┘│
       └──────┘      └──────┘

② 如果视图B的内容较短,则视图A的高度为视图A自身内容的高度。

       ┌──────┐      ┌──────┐
       │┌─┐┌─┐│      │┌─┐┌─┐│
       ││ ││B││      ││A││B││
I want ││A│└─┘│, not │└─┘└─┘│.
       ││ │   │      └──────┘
       │└─┘   │
       └──────┘

如果父布局是LinearLayout (Horizontal),将View A的高度设置为WRAP_CONTENT违反了情况1,将View A的高度设置为MATCH_PARENT违反了情况2。
如果父布局是RelativeLayout,将View A设置为同时与其父布局的顶部和底部对齐,会违反RelativeLayout的条件:请注意,RelativeLayout的大小和其子项的位置之间不能存在循环依赖关系。例如,您不能将高度设置为WRAP_CONTENT的RelativeLayout和一个设置为ALIGN_PARENT_BOTTOM的子项组合在一起。 如何解决这个问题?
3个回答

6

有不同的方法可以实现这一点,例如通过创建自己的自定义 ViewGroup,可能基于水平的 LinearLayout。然而,我认为最直接的解决方案是在运行时动态设置要求。

考虑以下布局,其中只有两个 TextView 在一个水平的 LinearLayout 中:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#f00"
    android:padding="10dp" >

    <TextView
        android:id="@+id/first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#0f0"
        android:padding="5dp"
        android:text="One line" />

    <TextView
        android:id="@+id/second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#00f"
        android:padding="5dp"
        android:text="Two\nlines"
        android:textColor="#fff" />

</LinearLayout>

两个文本框的高度都被包裹起来,基本上符合了您的第一个要求。

现在是第二个要求:为了演示目的,我已经将第二个TextView的文本分成两行,以使其比第一个更高。要使第一个TextView与它的高度相匹配,您只需要这样做:

LinearLayout container = (LinearLayout) findViewById(R.id.container);
final TextView first = (TextView) findViewById(R.id.first);
final TextView second = (TextView) findViewById(R.id.second);

container.post(new Runnable() {
    @Override public void run() {
        int h1 = first.getMeasuredHeight();
        int h2 = second.getMeasuredHeight();
        if (h1 < h2) first.getLayoutParams().height = h2;

    }
});

“诀窍”在于将内容发布到视图队列中,确保逻辑不会在子元素被测量并具有有效高度之前执行。对于需求2,只有当第二个视图更高时,第一个视图的高度才需要更改,这正是run()方法中的部分所做的事情。

1
难道没有一种 XML 的方法来做这件事吗?否则我将不得不在我的适配器内部完成这个操作,因为我想在一个动态填充的列表中执行类似这样的操作。 - Bart Burg
1
@BartBurg:一个自定义的ViewGroup可能是最优解。扩展LinearLayout是一个不错的开始,根据您特定的用例,您可能只需要覆盖onMeasure()以考虑上述标准。 - MH.
它会导致动画效果,这可能是不希望的。非常感谢提供自定义ViewGroup示例。 - Henrique de Sousa
@HenriquedeSousa:你是否设置了android:animateLayoutChanges="true"或在容器视图上使用了setLayoutTransition()(也可以在这里查看这里)?如果没有这些,动态更改高度不应该真正显着。尽管如此,上述解决方案并不理想,自定义的ViewGroup确实是解决问题的方法。如果我有时间,我会快速尝试一下。 - MH.

2

这个问题可以非常容易地解决,只需要从axml文件中进行设置。

将父布局的高度保持为wrap_content,并将每个子视图的高度设置为match_parent。这将导致父布局的高度包裹最高的子视图,并且每个子视图的高度都会拉伸到父视图的高度。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">
    <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="text" />
    <TextView
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:text="More\ntext" />
</LinearLayout>

1

您需要使用布局参数以编程方式设置视图的尺寸。假设您正在使用LinearLayout来容纳视图,那么您需要执行以下操作:

//the views are called a and b
LinearLayout.LayoutParams aParams = a.getLayoutParams();
LinearLayout.LayoutParams bParams = b.getLayoutParams();
int aWidth = aParams.width;
int aHeight = aParams.height;
int bWidth = bParams.width;
int bHeight = bParams.height;
if (aHeight >= bHeight) {
    // do nothing
}
else {
    a.setLayoutParams(new LinearLayout.LayoutParams(aWidth, bHeight));
}

在进行此修改之前,将它们的高度在xml中保持为wrap_content。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接