RelativeLayout中子元素的match_parent属性

27

简而言之,是否可以让一个位于RelativeLayout中的子视图始终与该RelativeLayout的高度匹配,无论该RelativeLayout中的其他子视图如何运作? 总之,就是这样。详细信息如下。

我要实现的是一个ListView行,其中至少有三个视图,其中一个视图将成为列表条目右侧的一种条纹(如下面的红色视图)。 我遇到的问题是在左侧有一个TextView,而取决于我有多少文本,条纹将无法填满整个布局。 这一点通过下面的图片非常清楚地解释了。

ListView项布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

<View
        android:id="@+id/bottom_line"
        android:layout_width="match_parent"
        android:layout_height="5dp"
        android:layout_alignParentBottom="true"
        android:background="#fc0" />

<!-- Why match_parent does not work in view below? -->
<View
        android:id="@+id/stripe"
        android:layout_width="80dp"
        android:layout_height="wrap_content"
        android:minHeight="50dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:background="#f00" />

<TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@id/stripe"
        android:text="This is a very long line, meant to completely break the match_parent property of the box at right"
        style="?android:textAppearanceLarge"/>

</RelativeLayout>

结果:

RelativeLayout with child not filling the whole layout vertically

将条纹和根元素的高度设置为match_parent没有任何区别。我已经这样做了。

重申一下问题,我希望红色条纹始终在垂直方向上填充父容器。 您可以看到条纹未对齐到根元素的顶部。

注意:上面的示例是我能想到的最简单、自包含的示例。它只是一个由静态字符串数组填充的匿名ArrayAdapterListActivity。在onCreate中的相关代码最多8行,所以不用担心。真正的问题出在布局上。此外,我已经使用嵌套的LinearLayout使其正常工作,但如果可能的话,我想减少布局结构的深度。LinearLayout完全符合预期。


@JD.com RelativeLayout在使用权重属性时不起作用(除了RelativeLayout本身的父容器...)。 - davidcesarino
5个回答

35

我有相同的需求,我的解决方案是将红色条纹的顶部与父级的顶部对齐,将条纹的底部与左侧文本视图的底部对齐。在这种情况下,高度变得无关紧要。您可以使用wrap_contentmatch_parent


我接受你的解决方案,因为我应该更好地表达我的问题。虽然你的答案符合当前的问题,但我真正想表达的是它应该被设置而不考虑其他视图(这在第一句中已经暗示了,但例子太过局限)。例如,如果我使用一个TextView作为条纹,那么如果我们相反地有比条纹更小的垂直文本(在这种情况下,条纹内容将被切掉),那么这个解决方案就行不通了。再次强调,我应该更好地表达我的问题(例如:条纹可以由除View之外的其他视图组成,而不是像暗示的那样“不考虑”)。 - davidcesarino
你是对的。在这种情况下,RelativeLayout 的高度为“wrap_content”,这意味着它参考子元素的高度。如果您定义一个高度为“match_parent”的子元素,则该子元素将参考其父元素的高度。父元素参考子元素的高度,而子元素参考父元素的高度。我认为这就是 RelativeLayout 目前无法处理的问题。您需要另一个锚点,并且我找到了一个解决方案,使用另一个位于所有其他元素下方的子元素。 - sergej shafarenka

19

简单来说,将主要的RelativeLayout放在一个LinearLayout中,然后子视图高度的计算就会正确无误。我曾经遇到过同样的问题,这种方法对我有效。


6
尝试这个:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

    <View
        android:id="@+id/stripe"
        android:layout_width="80dp"
        android:layout_height="match_parent"
        android:layout_alignBottom="@id/text"
        android:layout_alignParentRight="true"
        android:layout_alignTop="@id/text"
        android:background="#f00"
        android:minHeight="50dp"/>

    <TextView
        android:id="@+id/text"
        style="?android:textAppearanceLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@id/stripe"
        android:text="This is a very long line, meant to completely break the match_parent property of the box at right"/>

    <View
        android:id="@+id/bottom_line"
        android:layout_width="match_parent"
        android:layout_height="5dp"
        android:layout_below="@id/text"
        android:background="#fc0"/>

</RelativeLayout>

红色视图的顶部和底部对齐现在与TextView相同。

1
抱歉,您的解决方案存在问题。使用您的方法,条纹宽度取决于文本宽度(toRightof = text),如果文本达到根元素的最大宽度,则条纹最终将被推出布局。此外,如果条纹内容高度大于文本高度,则条纹内容将被裁剪。 - davidcesarino
你说得对!我编辑了我的代码,现在它可以正确地工作了;-)(将“toRightOf”从View更改为TextView的“toLeftOf”) - Namenlos
感谢您的努力。这基本上与您上面(和之前)的那个人说的一样,所以我将他的答案标记为已接受。实际上,我之前尝试过这个方法,但即使如此也有注意事项。请参见我在您上面的评论中提到的有关如果条纹具有任何大于TextView的内容,则会出现问题的情况。在这种情况下,条纹内容将被切掉。是的,我的错,因为我没有表达清楚,但我可以再次询问。 - davidcesarino
我尝试了一下,但它不起作用,唯一解决方法是将其放入LinearLayout中。 - Ronny Shibley

1
给列表项持有者添加监听器,以便每次持有者高度发生变化时,将该高度设置为子级的高度。i1用于顶部,i3用于底部。
parent.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
            child.setTop(i1);
            child.setBottom(i3);
        }
    });

1
这是一个很烦人的问题,你需要将RelativeLayout放在LinearLayout中。
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:minHeight="40dp"
        >
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <RelativeLayout
                android:id="@+id/deleteItem"
                android:layout_width="60dp"
                android:layout_height="match_parent"
                android:layout_alignParentRight="true"
                android:clickable="true"
                android:background="@color/background_grey"
                >
                <TextView
                    style="@style/SmallButtonFont"
                    android:layout_marginRight="12dp"
                    android:layout_centerInParent="true"
                    android:text="CLEAR"
                    android:textColor="@color/globalRedLight" />
            </RelativeLayout>
    </RelativeLayout>
</LinearLayout>

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