RelativeLayout 对齐父级 *side* + 边距 *side*

Posted

技术标签:

【中文标题】RelativeLayout 对齐父级 *side* + 边距 *side*【英文标题】:RelativeLayout align parent *side* + margin *side* 【发布时间】:2013-09-15 03:14:16 【问题描述】:

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

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

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_ >

    <RelativeLayout 
        android:layout_
        android:layout_
        android:layout_marginTop="110dp"
        android:layout_gravity="center"
        android:background="#ff555555" >

        <View
            android:layout_
            android:layout_
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:background="#aa8711" />     
    </RelativeLayout>

    <RelativeLayout 
        android:layout_
        android:layout_
        android:layout_marginBottom="110dp"
        android:layout_gravity="center"
        android:background="#ff555555" >

        <View
            android:layout_
            android:layout_
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:background="#998877" />         
     </RelativeLayout>      
</FrameLayout>

看起来像这样:

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

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

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

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

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

我尝试了同样的事情,这次将其行为与FrameLayout 的行为进行了比较。 初始设置:

和之后的边距:

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

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

【问题讨论】:

【参考方案1】:

为什么它只能部分可见?

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

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

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

130dp + 20dp == 150dp

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

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

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

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

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


第二种情况:

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

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

50dp + 151dp > 150dp

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

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


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

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

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

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

简而言之,避免使用边距(如 flash 或 winforms)并在没有布局类型的情况下进行播放,以获得所需的内容。

希望对您有所帮助,对不起 tl;dr.

【讨论】:

首先感谢您的回答。我不认为你完全明白。我没有被 XML 系统弄糊涂,它非常直观。我确实发现FrameLayoutRelativeLayout 表现得更好。我有一个基于布局的动画,用于移动视图(实际上是移动它们而不仅仅是动画)。我需要能够将它们“移出屏幕”或者“移出容器”更准确。我只是想知道RelativeLayout 是否有理由在我将其推向一个方向而不是另一个方向时将其保持在内部。边距无处不在,这不是“愚蠢”的输入 您永远不应该将它们“移出屏幕”,为什么不简单地隐藏它们呢?听起来您使用它有点像 Flash,或者您在 Flash 中有背景并且您试图在舞台上进行补间?高级运动和动画应该在 openGL 中完成

以上是关于RelativeLayout 对齐父级 *side* + 边距 *side*的主要内容,如果未能解决你的问题,请参考以下文章

在ListView中居中布局

RelativeLayout 中的 ImageView 与父级不匹配

对齐两个 relativeLayout

在RelativeLayout中将Android按钮与底部对齐?

Android RelativeLayout:包装在ScrollView中时如何对齐ParentBottom?

Android RelativeLayout:包装在ScrollView中时如何对齐ParentBottom?