Answers:
澄清:以下答案仍然有效,但我想澄清两点。原始解决方案将相对于另一个视图放置一个实际上具有负偏移的视图,并将其显示在所示的布局中。
另一个解决方案是使用Amir Khorsandi 此处建议的translationY属性。我希望该解决方案更简单,但有一个警告:平移是在布局后进行的,因此受限于位移视图的视图将不跟随平移。
例如,以下XML 在图像下方立即显示两个TextView。每个视图从上到下都受紧随其上方出现的视图的约束。
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="150dp"
android:layout_height="150dp"
android:tint="#388E3C"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_action_droid" />
<TextView
android:id="@+id/sayName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Say my name."
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintTop_toBottomOf="@+id/imageView"
app:layout_constraintEnd_toEndOf="@+id/imageView"
app:layout_constraintStart_toStartOf="@+id/imageView" />
<TextView
android:id="@+id/sayIt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Say it."
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintEnd_toEndOf="@+id/sayName"
app:layout_constraintStart_toStartOf="@+id/sayName"
app:layout_constraintTop_toBottomOf="@id/sayName" />
</androidx.constraintlayout.widget.ConstraintLayout>
现在,让我们来翻译“说我的名字” 的TextView达50dp
指定
android:translationY="-50dp"
这将产生以下结果:
在“说我的名字” 的TextView已经上移的预期,但“说” 的TextView没有遵循它,因为我们所期望的。这是因为翻译发生在布局后。尽管视图在布局后移动,但仍可以在新位置将其单击。
因此,如果上面的注意事项不影响您的布局,那么IMO,请在ConstraintLayout中使用translationX和translationY获得负边距。否则,请按照以下概述使用空间小部件。
原始答案
尽管似乎没有支持负边距的功能ConstraintLayout
,但仍有一种方法可以使用可用和受支持的工具来实现效果。这是图像标题与图像22dp
底部重叠的图像-有效地是-22dp
空白:
这是通过使用Space
底部边距等于所需偏移量的小部件来完成的。Space
然后,将小部件的底部限制为的底部ImageView
。现在,您需要做的就是将顶部TextView
的图像标题限制在Space
小部件的底部。的TextView
将被定位在所述底部Space
忽略所设定的余量视图。
以下是实现此效果的XML。我会注意到我使用Space
它是因为它是轻量级的,并且打算用于这种类型的使用,但是我可以使用另一种类型的View
并使它不可见。(不过,您可能需要进行调整。)您还可以定义一个View
具有零边距的a和想要的插图边距的高度,并将的顶部约束TextView
到插图的顶部View
。
还有一种方法是通过对齐顶部/底部/左侧/右侧来TextView
对顶部进行覆盖,并对ImageView
边距/填充进行适当的调整。下面演示的方法的好处在于,无需大量计算即可创建负余量。就是说,有几种方法可以解决此问题。
更新:有关此技术的快速讨论和演示,请参阅Google Developers Medium 博客文章。
ConstraintLayout
XML的负边距
<android.support.constraint.ConstraintLayout
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>
ImageView
以父项为中心,在TextView
上方重叠ImageView
。然后Space
,当应用程序从后台返回时,会产生错误。我认为0dp,0dp会带来一些麻烦。怎么用呢Guideline
。
另一种方法是使用translationX
或translationY
类似这样:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:translationX="25dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
它会像 android:layout_marginRight="-25dp"
RelativeLayout从未正式支持负边距。ConstraintLayout将不支持负边距。[...]
-罗曼·盖伊(Romain Guy)2016年6月8日
请遵循以下两个问题:
https://code.google.com/p/android/issues/detail?id=212499 https://code.google.com/p/android/issues/detail?id=234866
经过数小时的寻找解决方案,我才明白这一点。
让我们考虑两个图像,图像1和图像2。Image2将放置在image1的顶部,并位于右下侧。
我们可以使用Space小部件来重叠视图。
将Space小部件的四个面分别限制为image1的四个面。在此示例中,将image2的左侧限制为Space小部件的右侧,将image2的顶部限制为Space小部件的底部。这会将image2与Space小部件联系在一起,并且由于Space小部件受到了所有侧面的约束,因此我们可以定义所需的水平或垂直偏差,以根据需要移动image2。
<?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>
另外,要将image2定位在image1的中心底部,我们可以分别用Space小部件的左侧和右侧约束image2的左侧和右侧。同样,我们可以通过使用Space小部件更改image2的约束,将image2放置在任何地方。
我找到了一种更简单的方法。
基本上有ImageView,然后在Text View上添加top约束以匹配图像的top约束,并仅添加TextView的margin top进行匹配以实现-ve margin类型的行为。
这将帮助许多人
就我而言,我想要这样的设计:
意味着我希望我的图像显示的是其宽度的一半,所以基本上我需要一半为实际图像宽度的负边距,但是我在约束布局和约束布局中的整个布局都不允许负边界,所以我用下面的代码实现了这一点
<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>
这样ImageView将在指南的开头结束。其效果与50dp开始时的负余量相同。
另外,如果视图的宽度不是固定的,而是以百分比为单位的,那么您可以按百分比放置准则,并实现所需的效果
快乐编码:)
您只需要在布局中使用Space小部件
<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">
<Space
android:id="@+id/negative_margin"
android:layout_width="16dp"
android:layout_height="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toLeftOf="parent"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Widget who needs negative margin"
app:layout_constraintTop_toBottomOf="@+id/negative_margin"
app:layout_constraintLeft_toLeftOf="@+id/negative_margin" />
这是一个古老的问题,但仍然存在很多问题,实现此目标的最快方法是将视图的顶部和底部限制在要锚定的视图的侧面,如下所示:
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="55dp"
android:layout_height="55dp"
app:layout_constraintBottom_toBottomOf="@+id/parent_view_id"
app:layout_constraintTop_toBottomOf="@+id/parent_view_id"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
这将使它在视图的底线居中,水平居中。
一个简单的方法。
我不确定最好的方法。
只需使用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>