19

RelativeLayout当您将视图与布局的一侧(任何一侧)对齐并且在同一方向上具有较大的边距时,我注意到了一种奇怪的行为。

我有 2 个RelativeLayouts,每个都包含一个简单的视图。在一种布局中,视图与顶部和左侧对齐,在另一种布局中与底部和右侧对齐:

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

    <RelativeLayout 
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="110dp"
        android:layout_gravity="center"
        android:background="#ff555555" >

        <View
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:background="#aa8711" />     
    </RelativeLayout>

    <RelativeLayout 
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginBottom="110dp"
        android:layout_gravity="center"
        android:background="#ff555555" >

        <View
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:background="#998877" />         
     </RelativeLayout>      
</FrameLayout>

它看起来像这样:

基本设置

我在父对齐的每个方向上添加了 130dp 的边距。这意味着视图应该在布局中仅部分可见。这就是发生的事情:

每个对齐方向 130dp

如您所见,视图现在小于原始大小,因为它们被推到了布局的“墙壁”上。接下来,我尝试提供比布局更大的边距,因此我在对齐的方向上给了它们 151dp 的边距。它看起来像这样:

在此处输入图像描述

右下对齐的视图现在“突破”了布局,并且再次与原来的大小相同。另一方面,左上对齐的视图也处于其原始大小,但完全在布局内部而不是在布局外部。

我已经单独尝试过这个,并且在对齐的每一个排列中都得到了相同的结果。

问题一:谁能解释这种不一致的行为?

我尝试了同样的事情,这次将行为与FrameLayout. 最初设定:

在此处输入图像描述

在边距之后:

在此处输入图像描述

始终将FrameLayout视图保持在其原始大小,并简单地让视图“退出”它。我试图在至少应该在视图之外的视图大小的相反方向上给出负边距,并看到与默认情况下RelativeLayout发生的相同行为。FrameLayout

问题 2:谁能解释行为差异和相反的负边际效应?

4

1 回答 1

3

为什么它只能部分可见?

我在父对齐的每个方向上添加了 130dp 的边距。这意味着视图应该在布局中仅部分可见

盒子越来越小,因为优先考虑不惜一切代价将其保留在父布局中,同时仍应用边距。由于较小的子视图为 50dp,因此您添加了边距130dp,它需要的总宽度是,180dp但父视图本身只有150dp宽。也就是说130dp + 50dp > 150dp- 孩子加上边距不能放在父母里面。

这是“愚蠢的输入”,XML 解释器正在尽最大努力呈现某些内容。它最终做出的决定是它可以改变子框的宽度并仍然遵守边距约束。或者在数学上

130dp + 20dp == 150dp

50dp基本上,它会将内框的宽度从分配到缩小,20dp以便它可以容纳在父级内部并增加边距。如果你看一下正方形的大小,20dp看起来就差不多了。它小了 60%。

这是解释器的聪明行为,因为随着屏幕尺寸的变化并且遇到这样的问题,它应该始终保留与宽度约束相反的边距约束。

总而言之,解释器正在尽最大努力适应盒子,以及它在其父项内的边距,这样做是为了使盒子更小。它选择在给定的宽度上保留给定的边距 - 可能是因为最顶层的父布局。

当您说“这应该是部分可见的”时,我假设您认为孩子将在父边界内渲染一半,在父边界外渲染一半,类似于 Windows 窗体开发。但事实并非如此,因为在大多数布局中,它总是试图将子级保持在父级的范围内。

所做的选择也取决于最顶层的父布局,某些布局可能更喜欢保留子框的宽度而不是边距,甚至将框渲染到父边界之外。


在第二种情况下:

所以我在对齐的方向上给了他们 151dp 的边距。

您超出了解释器可以缩小图像的范围。它不能将图像缩小到负1。即

50dp + 151dp > 150dp

它不能满足你给它的这个边距限制,所以行为是相当不可预测的。我猜我会说它知道它不能将这两个图像以及它们的边距都保留在父级中。所以它只是渲染一个内部和一个外部。

再一次,这是愚蠢的输入,解释器正在尽最大努力呈现你想要的。


谁能解释行为的差异和相反的负边际效应?

负边距会根据其父级中的布局类型做不同的事情,并且它也是对齐的。在框架布局中,它的行为与相对布局不同。通常,如果您正在查看负面布局,则您选择了错误的父容器,并且您正在尝试破解它以使其看起来正确。

我不知道你到底想做什么,但也许你只需要稍微调整一下你的思维过程,想想试图理解你给它的 XML 的糟糕解释。

你不会是第一个完全被 android 的 XML 布局弄糊涂的人。在布局中嵌套布局总是令人困惑,并且行为会根据边距、对齐方式、宽度等许多因素而改变。我认识的大多数人只是简单地使用它,直到它是正确的,然后尝试不同的容器布局类型来获得正确的设计.

简而言之,避免使用边距(如 flash 或 winforms)并在没有布局类型的情况下播放,而不是在你想要的地方获得东西。

希望对您有所帮助,对不起tl;博士。

于 2013-12-23T06:45:14.127 回答