Is it possible to achieve negative margin on constraint layout to achieve overlap? I am trying to have a image centered on the layout and have a Text view such that it overlaps a by x dp. I tried setting negative margin value but no luck. It would be great if there is a way to achieve this.
问题:
回答1:
Update: I want to draw attention to the answer posted by Amir Khorsandi that specifies using translationY
to inset the view. The answer below works well (thank you for all the votes), but I posted this solution because I believed that translationY
would cause problems with visually moving the view but leaving the actual view in the old position. This would cause interaction problems if the view was to respond to touches. (This view of mine was reinforced by goemic who said as much in a comment on Amir Khorsandi's post.)
I think that I believed this because this is true with view animation. See Animation in Honeycomb - an old blog entry by relevant.
Finally, the previous animations changed the visual appearance of the target objects... but they didn't actually change the objects themselves.
This is NOT true for the translationX
and translationY
XML attributes. translationX
and translationY
will actually move the view. So, the top of the text view can be constrained to the bottom of the image view and the translationY
property can be set to -22dp
. This will have the same effect as using the Space
widget as described below and is easier to implement and understand.
If I am missing something, please post a comment here.
Original answer
Although it doesn't appear that negative margins will be supported in ConstraintLayout
, there is a way to accomplish the effect using the tools that are available and supported. Here is an image where the image title is overlapped 22dp
from the bottom of the image - effectively a -22dp
margin:
This was accomplished by using a Space
widget with a bottom margin equal to the offset that you want. The Space
widget then has its bottom constrained to the bottom of the ImageView
. Now all you need to do is to constrain the top of the TextView
with the image title to the bottom of the Space
widget. The TextView
will be positioned at the bottom the the Space
view ignoring the margin that was set.
The following is the XML that accomplishes this effect. I will note that I use Space
because it is lightweight and intended for this type of use, but I could have used another type of View
and made it invisible. (You will probably need to make adjustments, though.) You could also define a View
with zero margins and the height of the inset margin you want, and constrain the top of the TextView
to the top of the inset View
.
Yet another approach would be to overlay the TextView
on top of the ImageView
by aligning tops/bottoms/lefts/right and make suitable adjustments to margins/padding. The benefit of the approach demonstrated below is that a negative margin can be created without a lot of computation. That is all to say that there are several ways to approach this.
Update: For a quick discussion and demo of this technique, see the Google Developers Medium blog post.
Negative Margin for ConstraintLayout
XML
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/ic_launcher" />
<android.support.v4.widget.Space
android:id="@+id/marginSpacer"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="22dp"
app:layout_constraintBottom_toBottomOf="@+id/imageView"
app:layout_constraintLeft_toLeftOf="@id/imageView"
app:layout_constraintRight_toRightOf="@id/imageView" />
<TextView
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Say my name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/marginSpacer" />
</android.support.constraint.ConstraintLayout>
回答2:
Another way is using translationX
or translationY
like this:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:translationX="25dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
it will work like android:layout_marginRight="-25dp"
回答3:
Negative margins have never been officially supported in RelativeLayout. Negative margins will not be supported in ConstraintLayout. [...]
-- Romain Guy on Jun 8, 2016
Follow these two issues:
https://code.google.com/p/android/issues/detail?id=212499 https://code.google.com/p/android/issues/detail?id=234866
回答4:
I found a way to do it much simpler.
Basically have the ImageView, then on the Text View add top constraint to match the top constraint of the image and just add the margin top of the TextView to match to achieve the -ve margin type behavior.
回答5:
This is what I figured out after hours of trying to find a solution.
Let us consider two images, image1 and image2. Image2 is to be placed on top of image1 positioned to the bottom-right side.
Overlapping Views Example
We can use Space widget for overlapping views.
Constraint the Space widget's four sides with the four sides of the image1 respectively. For this example, constraint the image2's left side with the Space widget's right side and the image2's top side with the Space widget's bottom side. This will tie image2 with the Space widget and since the Space widget is constrained from all the sides, we can define required horizontal or vertical bias which will move image2 as required.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Player">
<ImageView
android:id="@+id/image1"
android:layout_width="250dp"
android:layout_height="167dp"
android:src="@android:color/holo_green_dark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Space
android:id="@+id/space"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@+id/image1"
app:layout_constraintEnd_toEndOf="@+id/image1"
app:layout_constraintHorizontal_bias="0.82"
app:layout_constraintStart_toStartOf="@+id/image1"
app:layout_constraintTop_toTopOf="@+id/image1"
app:layout_constraintVertical_bias="0.62" />
<ImageView
android:id="@+id/image2"
android:layout_width="82dp"
android:layout_height="108dp"
android:src="@android:color/holo_green_light"
app:layout_constraintStart_toEndOf="@+id/space"
app:layout_constraintTop_toBottomOf="@+id/space" />
</android.support.constraint.ConstraintLayout>
Additionally, to position image2 on the center-bottom of image1, we can constraint image2's left and right sides with Space widget's left and right sides respectively. Similarly, we can place image2 anywhere by changing image2's constraints with Space widget.
回答6:
This will help many
In my case i want my design like this:
Means i want my image is display half of their width so the basically i need negative margin of half of the actual image width but my whole layout in constraint layout and constraint layout does not allowed negative margin so i achieved this with below code
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="centerCrop"
android:src="@drawable/ic_launcher_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/guideline"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="50dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
So that ImageView will end at the starting of the guideline. and the effect is same as like negative margin at the start of 50dp.
And also if your view's width is not fixed and it's in percentage so that you can place guideline with percentage and achieve whatever effect you want
Happy Coding:)
回答7:
A Simple Way.
I'm not sure best way.
Just wrap using LinearLayout
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<View
android:layout_width="wrap_content"
android:layout_marginLeft="-20dp"
android:layout_height="wrap_content"/>
</LinearLayout>