在安卓系统中使用负利润率是一种不好的做法吗?

负保证金示范:

enter image description here

剧本

通过将其中一个视图设置为负边距,使其侵入另一个视图的边框,从而使视图重叠。

想法

它似乎工作的方式,你会期望与重叠的布局,如果他们应该。但我不想因为不知不觉做错了事而遇到更大的问题。模拟器,物理设备,你能想到的,当你使用负边距时,一切似乎都正常工作,一个视图侵入另一个视图的边界框,这取决于它在布局中的声明方式,它将位于另一个视图的上方或下方。

我也知道,自从 API 21以来,我们可以设置 translationZelevation属性,使视图出现在其他视图的上方或下方,但 我的担心基本上来自这样一个事实,即 在文件中layout_margin属性它明确指定的 保证金应该是正数,让我引用:

节选:
指定视图左、上、右和底部的额外空间。这个空间超出了这个视图的范围。保证金应该是正数. 必须是一个维度值,它是一个浮点数,后面附加了一个单位,如“14.5 sp”。可用的单位是: px (像素) ,dp (密度无关像素) ,sp (根据首选字体大小缩放像素) ,in (英寸) ,mm (毫米) ...

自从我最初提出这个问题以来,我没有遇到任何负利润率的问题,尽可能避免使用它们,但是 没有遇到了任何问题,所以即使文档说明了这一点,我也不太担心。

91006 次浏览

我只知道这是可能的,在相当短的时间内。但我觉得没问题。只是要注意屏幕大小等等,这样你就不会意外地在屏幕上出现不应该重叠的项目。(也就是说,文字放在文本上可能是个坏主意。)

2010年,@RomainGuy (核心 Android 工程师)表示,负边距具有未指定的行为

2011年,@RomainGuy 表示,你可以在 ABC0和 RelativeLayout上使用负边距

2016年,@RomainGuy 表示 它们从未得到官方支持,也不会得到 ConstraintLayout的支持

在2020年12月(2.1.0版,2021年6月正式发布) ,负利润率支持约束 已添加到 ConstraintLayout

但是很容易绕过这个限制。

在基本视图的底部添加一个辅助视图(高度0dp,宽度限制为父视图) ,在底部添加所需的边距。
然后把你的视图放在这个视图的下面,有效地允许它有一个“负”边距,但不必使用任何不被支持的负值。

如果您想使用负边距,设置足够的填充容器及其 剪贴板为假,并为其子级设置负边距,这样它就不会剪辑子视图!

对于我来说,关于在 TextView 上设置负边距(我知道 OP 指的是 ViewGroup,但是我在寻找设置负边距的问题,我在这里着陆了) ... 我发现4.0.3(API 15)只有一个问题,android:layout_marginTopandroid:layout_marginBottom设置为负值,如 -2 dp。

由于某种原因,TextView 根本不显示。它似乎从视野中“消失”了(不仅仅是看不见)。

当我在其他3个版本的 layoMarge 中尝试这种方法时,我没有发现这个问题。

请注意,我还没有在真正的设备上尝试过这种方法,它使用的是4.0.3模拟器。这是我发现的仅影响4.0.3的第二个奇怪的东西,所以我的新规则是使用4.0.3模拟器进行 一直都是测试:)

我成功地通过使用 android:lineSpacingExtra="-2dp"减少了 TextView 的底部边距,即使我碰巧有 android:singleLine="true"(所以我不会想到行间距会是一个因素)。

这在过去可能是不好的做法,但是随着材料设计和它的浮动动作按钮,它似乎是不可避免的,并在许多情况下需要现在。基本上,当你有两个独立的布局,你不能把一个单独的 RelativeLayout,因为他们需要明显的独立处理(例如,想想头和内容) ,唯一的方法重叠 FAB 是使它坚持一个布局使用负边距。这就给可点击区域带来了额外的问题。

不,你不应该使用 negative margin。相反,你应该使用 translate。即使负边距工作有时,当你改变布局可编程,翻译将有所帮助。并且当你使用边距时,视图不能溢出屏幕。

希望这能对某些人有所帮助。下面是基于@CommonsWare 的答案使用 ConstraintLayout编写的示例代码:

添加一个辅助视图(高度0dp,宽度限制为父级) 底部的基础视图,在底部添加您想要的边距。然后 把你的视图放在这个视图的下面,有效地允许它有一个 “负数”边距,但不必使用任何无支持的负数 价值。

示例代码:

<TextView
android:id="@+id/below"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F1B36D"
android:padding="30dp"
android:text="I'm below"
android:textColor="#ffffff"
android:textSize="48sp"
android:textAlignment="center"
tools:layout_editor_absoluteX="129dp"
tools:layout_editor_absoluteY="0dp" />


<android.support.v4.widget.Space
android:id="@+id/space"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="32dp"
app:layout_constraintBottom_toBottomOf="@+id/below"
app:layout_constraintLeft_toLeftOf="@id/below"
app:layout_constraintRight_toRightOf="@id/below" />


<TextView
android:id="@+id/top"
android:layout_width="100dp"
android:layout_height="60dp"
android:textAlignment="center"
android:textColor="#ffffff"
android:text="I'M ON TOP!"
android:background="#676563"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/space" />

产出:

enter image description here

你可以使用以下方式代替负边距: translationXtranslationY

例如:

android:layout_marginBottom = -2dp


android:translationY = -2dp

更新: 记住,整个视图是翻译过来的。