在Android中使用负边距是一种不好的做法吗?


114

负边距演示:

                         在此处输入图片说明

场景

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

思想

如果布局应该重叠,它似乎可以按照您期望的方式工作。但是我不想在不知情的情况下遇到更大的问题。模拟器,物理设备,用它命名,当您使用负边距时,所有内容似乎都可以正常工作,一个视图会侵入另一个视图的边界框,并且取决于在布局中声明的方式,该视图将位于另一个视图的上方或下方。

我还知道,自API 21以来,我们可以设置translationZelevation 属性以使视图显示在其他视图之上或之下,但是我主要担心的是,layout_margin属性的文档中明确指定了边距值应为正,我引用:

摘录:
在此视图的左侧,顶部,右侧和底部指定额外的空间。此空间超出了此视图的范围。保证金值应为正。必须是尺寸值,该尺寸值是一个浮点数,后跟一个单位,例如“ 14.5sp”。可用的单位是:px(像素),dp(与密度无关的像素),sp(根据首选字体大小缩放的像素),(英寸),mm(毫米)...

在未来的几年,因为最初提出这个问题,我还没有切缘阴性的任何问题,并尽量避免使用它们尽可能多地,但并没有遇到任何问题,所以即使文档指出,我不是太担心它。


1
我知道浓缩咖啡测试如果其边距之一为负值将无法看到该对象...所以这就是不使用它们的原因
Tim Boland

Answers:


192

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

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

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

不过,解决此限制很容易。

在基本视图的底部添加一个辅助视图(高度0dp,宽度限制为父视图),在底部添加所需的边距。
然后将您的视图置于该视图的下方,有效地使其具有“负”边距,而不必使用任何不受支持的负值。


1
似乎是无害的事情,万一有人有其他见解,请敞开门
JuanCortés2012年

1
@DrewLeSueur:我不会做那个假设。我什至不知道负填充将意味着什么。
CommonsWare 2013年

1
@CommonsWare你能告诉我,是有可能做这样的事情` - @扪/ anyvalue”我要调用中声明价值,但负求助?
deadfish

2
@ 100kg:抱歉,不支持。
CommonsWare 2013年

21
我注意到,在Android 4.4 KitKat中,负边距方面有所变化(相比于4.3;至少在Asus Nexus 7上)。原来是您需要的android:clipChildren="false"android:clipToPadding="false"以前是不需要的,否则事情就这样破裂了
Jonik 2013年

18

希望这会帮助某人。这是ConstraintLayout基于@CommonsWare的答案的工作示例代码:

在基本视图的底部添加一个辅助视图(高度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" />

输出:

在此处输入图片说明


16

如果要使用负边距,请为容器设置足够的填充,并将其clipToPadding设置为false,然后为其子设置负边距,这样就不会剪切子视图!


4

过去可能是不好的做法,但是使用Material Design及其浮动操作按钮,这似乎是不可避免的,现在在许多情况下都是必需的。基本上,当您有两个单独的布局,由于它们需要截然不同的处理而无法放入单个RelativeLayout中时(例如,考虑标头和内容),重叠FAB的唯一方法是使FAB伸出其中的一个使用负边距的布局。这会为可点击区域带来其他问题。


3

对我来说,关于在TextView上设置负页边距(我意识到OP指的是ViewGroup,但是我一直在寻找设置负页边距的问题,因此在此着陆)...我发现4.0.3有问题( API 15),仅将android:layout_marginTop或设置为android:layout_marginBottom负值,例如-2dp。

由于某种原因,TextView根本不显示。从视图看来,它“消失了”(而不仅仅是不可见的)。

当我尝试使用其他3个版本的layout_margin进行此操作时,没有看到此问题。

请注意,我尚未在实际设备上尝试过此操作,而是使用4.0.3模拟器。这是我发现仅影响4.0.3的第二件事,所以我的新规则是始终使用4.0.3模拟器进行测试:)

android:lineSpacingExtra="-2dp"即使我碰巧也可以使用它来减少TextView的底部边距,从而获得了成功android:singleLine="true"(因此我不会想到行距会成为一个因素)。


1
我在Nexus 4(xhdpi)和4.2.2上发现了类似的行为。尽管父级布局具有填充,但是存在没有填充的布局。里面有一个TextView,其marginTop为负。在5.0上运行良好。在设备和Nexus 4的仿真器中的4.2.2上,它消失了。解决方案是将填充移到包含TextView的布局中。
louielouie 2014年

3

不,您不应使用negative margin。相反,您应该使用translate。即使负边距有时起作用,当您以编程方式更改布局时,转换也会有所帮助。使用边距时,视图也不会溢出屏幕。


0

我只知道有可能在相当短的时间内。但我认为没有问题。请注意屏幕尺寸等等,以确保您不会意外地制作不应在屏幕上重叠的项目。(即,文本上方的文本可能是一个坏主意。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.