125

Demo of negative margin:

                         enter image description here

The scenario

Overlapping views by setting a negative margin to one of them so that it invades the bounding box of another view.

Thoughts

It seems to work the way you'd expect with overlapping of the layouts if they should. But I don't want to run into a bigger problem for unknowingly not doing things right. Emulators, physical devices, you name it, when you use negative margins everything seems to work correctly, one view invades another's views bounding box and depending on how it's declared in the layout it will be above or below the other view.

I'm also aware that since API 21 we can set the translationZ and elevation attributes to make view appear above or below other views but my concern basically comes from the fact that in the documentation for the layout_margin attributes it's clearly specified that margin values should be positive, let me quote:

Excerpt:
Specifies extra space on the left, top, right and bottom sides of this view. This space is outside this view's bounds. Margin values should be positive. Must be a dimension value, which is a floating point number appended with a unit such as "14.5sp". Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size), in (inches), mm (millimeters)...

In the years since originally asking this question I haven't had any issues with negative margins, did try to avoid using them as much as possible, but did not encounter any issues, so even though the documentation states that, I'm not too worried about it.

Community
  • 1
  • 1
Juan Cortés
  • 18,689
  • 8
  • 63
  • 88
  • 2
    i know espresso tests wont be able to see the object if one of its margins are negative...so thats a reason not to use them – Tim Boland Sep 03 '19 at 18:50

8 Answers8

203

In 2010, @RomainGuy (core Android engineer) stated that negative margins had unspecified behavior.

In 2011, @RomainGuy stated that you can use negative margins on LinearLayout and RelativeLayout.

In 2016, @RomainGuy stated that they have never been officially supported and won't be supported by ConstraintLayout.

It is easy to work around this limitation though.

Add an helper view (height 0dp, width constrained to parent) at the bottom of your base view, at the bottom add the margin you want.
Then position your view below this one, effectively allowing it to have a "negative" margin but without having to use any unsupported negative value.

Brais Gabin
  • 5,447
  • 5
  • 50
  • 88
CommonsWare
  • 910,778
  • 176
  • 2,215
  • 2,253
  • 1
    Seems to be a harmless thing then, leaving open in case anyone has some other insight – Juan Cortés May 20 '12 at 13:17
  • I assume same goes for negative paddings – Drew LeSueur Jan 21 '13 at 21:57
  • 1
    @DrewLeSueur: I would not make that assumption. I have no idea what a negative padding would even mean. – CommonsWare Jan 21 '13 at 21:59
  • 1
    @CommonsWare can you tell me, is it possible do something like that `-@dimen/anyvalue" ? I want call declared value but negative. Help. – deadfish Apr 08 '13 at 14:45
  • 2
    @100kg: Sorry, but that is not supported. – CommonsWare Apr 08 '13 at 14:48
  • on a checkbox, a negative margin has varying effects on a Samsung Galaxy S4 and a S3 – Someone Somewhere Nov 13 '13 at 01:30
  • 22
    I noticed that in **Android 4.4** KitKat, something has changed with regards to negative margins (compared to 4.3; at least on Asus Nexus 7). Turns out you need `android:clipChildren="false"` and `android:clipToPadding="false"` where you previously didn't, or [things break like this](http://i.stack.imgur.com/HvQNb.png). – Jonik Dec 06 '13 at 16:09
  • 1
    @Jonik I think you don't even need to set `android:clipChildren="false"`. Just applying `android:clipToPadding="false"` to the parent `ViewGroup` is sufficient. – jenzz Jan 27 '14 at 12:25
  • @Jonik Negative margins don't work well with relative layout but worked well with linear layout for me without clipping – Rushi M Thakker Aug 04 '17 at 11:01
  • Nice answer with all the historical context! – Martin Konicek Jan 22 '18 at 16:25
  • 1
    @CommonsWare Please, could you provide a minimal sample layout code example? – Tebo Mar 31 '18 at 14:36
  • @Tebo: Sorry, I did not write that section of the answer, and I have no idea what it is referring to. – CommonsWare Mar 31 '18 at 14:38
  • 1
    @Tebo I have added the sample layout code below. Please check it. I hope it will help others as well. – Vikasdeep Singh Jul 07 '18 at 02:24
  • you could similarly use a guideline with <0 percent, ie layout_constraintGuide_percent="-0.2", or >1 percent layout_constraintGuide_percent="1.2" if you want it to overlap bottom or right – lisa Aug 15 '18 at 15:27
23

Hope this will help someone. Here is working sample code using ConstraintLayout based on @CommonsWare's answer:

Add an helper view (height 0dp, width constrained to parent) at the bottom of your base view, at the bottom add the margin you want. Then position your view below this one, effectively allowing it to have a "negative" margin but without having to use any unsupported negative value.

Sample code:

<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" />

Output:

enter image description here

Vikasdeep Singh
  • 17,777
  • 9
  • 70
  • 93
17

In case you want use negative margin,set enough padding for container and its clipToPadding to false and set negative margin for it's children so it won't clip the child view!

Ali
  • 18,627
  • 13
  • 75
  • 90
5

It might have been bad practice in the past but with Material Design and its floating action buttons, it seems to be inevitable and required in many cases now. Basically, when you have two separate layouts that you can't put into a single RelativeLayout because they need distinctly separate handling (think header and contents, for instance), the only way to overlap the FAB is to make it stick out of one those layouts using negative margins. And this creates additional problems with clickable areas.

Gábor
  • 7,853
  • 2
  • 50
  • 65
3

For me, and regarding setting a negative margin on a TextView (I realize the OP is referring to a ViewGroup, but I was looking for issues with setting negative margins and I landed here)... I found a problem with 4.0.3 (API 15) ONLY and the setting of android:layout_marginTop or android:layout_marginBottom to a negative value such as -2dp.

For some reason the TextView does not display at all. It appears to be "gone" from the view (not just invisible).

When I tried this with the other 3 versions of layout_margin, I didn't see the issue.

Note that I haven't tried this on a real device, this is using a 4.0.3 emulator. This is the 2nd odd thing I've found that only affected 4.0.3, so my new rule is to always test with a 4.0.3 emulator :)

I have success with reducing the bottom margin of a TextView by using android:lineSpacingExtra="-2dp" which works even though I happen to have android:singleLine="true" (and so I wouldn't have thought that line spacing would be a factor).

GaryAmundson
  • 199
  • 9
  • 1
    I found similar behavior on a Nexus 4 (which is xhdpi) and 4.2.2. There was a layout with no padding, although a parent layout had padding. There was a TextView inside with negative marginTop. On 5.0 it worked fine. On 4.2.2 on both the device and in an emulator for Nexus 4, it disappears. The solution was to move the padding to the layout that contained the TextView. – louielouie Dec 17 '14 at 20:55
3

No, you should not use negative margin. instead you should use translate. Even if negative margin work sometime, when you change layout programmably, translate would help. And view can't overflow the screen wen you use margin.

1

Instead of negative margins you can use: translationX and translationY.

Example:

android:layout_marginBottom = -2dp

android:translationY = -2dp
I.Step
  • 105
  • 14
0

I've only known that it was possible for a rather short period of time. But I see no problem with it. Just be aware of screen sizes and such so you are sure not to accidentally make to items that shouldn't appear overlapped on the screen. (i.e. text on top of text is likely a bad idea.)

FoamyGuy
  • 45,328
  • 16
  • 118
  • 151