是否有可能在约束布局上实现负裕度以实现重叠? 我试图有一个以布局为中心的图像,并有一个文本视图,使其重叠的 x dp。我试过设置负的边际价值,但没有运气。 如果有办法做到这一点,那就太好了。
在 RelativeLayout 中从未正式支持过负边距 —— Romain Guy on Jun 8,20162016年6月8日
在 RelativeLayout 中从未正式支持过负边距
—— Romain Guy on Jun 8,20162016年6月8日
关注以下两个问题:
Https://code.google.com/p/android/issues/detail?id=212499 Https://code.google.com/p/android/issues/detail?id=234866
更新 ConstraintLayout 现在在版本2.1.0-alpha2中支持负边距
android:layout_marginTop="-25dp"
利润为负25个百分点。(这只有在视图顶部受到约束时才能工作。如果边距的侧面不受限制,则边距在 约束布局中没有作用。)
澄清: 下面的答案仍然有效,但是我想澄清一些事情。原始的解决方案将放置一个视图与另一个视图的 事实上负偏移量,如上所述,并将在布局中显示。
另一个解决方案是使用 Amir Khorsandi 给你建议的 翻译属性。我更喜欢这种简单的解决方案,但有一点需要注意: 转换发生在 布局后,因此受限于被替换视图的视图将不会跟随转换。
例如,下面的 XML 在图像的正下方显示两个 文本视图。每个视图都受到自上而下的约束,视图就出现在视图的正上方。
<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>
现在,让我们通过指定
android:translationY="-50dp"
这产生了以下结果:
“说出我的名字”文本视图已经如我们预期的那样向上移动,但是“说出来”文本视图并没有像我们预期的那样跟进。这是因为翻译发生在 布局后。尽管视图在布局之后移动,但仍然可以在新位置中单击它。
所以,我的意思是,如果上面的警告不会影响你的布局,那么在 约束布局中使用 翻译 X和 翻译的负边距; 否则,使用下面概述的 空间小部件。
另一个警告: 正如 Salam El-Banna 在对另一个答案的评论中所说的那样,翻译 X对于 RTL 布局来说不是一个好的解决方案,因为无论布局的 RTL 或 LTR 性质如何,翻译的标志都会指示移动的方向(左/右)。
原始答案
虽然在 ConstraintLayout中似乎不支持负边距,但是有一种方法可以使用现有的和支持的工具来实现这种效果。这是一张图片,图片标题与图片底部的 22dp重叠——实际上是一个 -22dp边距:
ConstraintLayout
22dp
-22dp
这是通过使用底部边距等于所需偏移量的 Space小部件实现的。然后,Space小部件的底部被约束到 ImageView的底部。现在您需要做的就是将图像标题限制在 TextView的顶部到 Space小部件的底部。TextView将定位在 Space视图的底部,忽略已设置的边距。
Space
ImageView
TextView
下面是实现此效果的 XML。我将注意到,我使用 Space是因为它是轻量级的,并且用于这种类型的使用,但是我可以使用另一种类型的 View并使其不可见。(不过,您可能需要做出一些调整。)您还可以定义一个边距为零的 View和所需的插入边距高度,并将 TextView的顶部约束为插入 View的顶部。
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 的边距顶部来匹配来实现-ve 边距类型行为。
简单的方法。
我不知道最好的办法。
使用 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>
另一种方法是像这样使用 translationX或 translationY:
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"一样工作
android:layout_marginRight="-25dp"
这是我花了几个小时想出来的解决办法。
让我们考虑两个图像,image 1和 image 2。将 Image2放置在 Image1的顶部,定位在右下角。
重叠视图示例
我们可以对重叠视图使用 太空小部件。
分别用图像1的四条边约束 Space 小部件的四条边。对于这个示例,用 Space 小部件的右侧约束 image 2的左侧,用 Space 小部件的底部约束 image 2的顶部。这将把 image 2与 Space 小部件绑定在一起,由于 Space 小部件受到所有方面的限制,我们可以定义所需的水平或垂直偏差,这将根据需要移动 image 2。
<?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>
此外,为了将 image 2放置在 image 1的中心底部,我们可以分别使用 Space 小部件的左右两侧来约束 image 2的左右两侧。类似地,我们可以通过使用 Space 小部件更改 image 2的约束来将 image 2放置在任何地方。
这将有助于许多
在我的情况下,我希望我的设计是这样的:
意思是我想我的图像是显示宽度的一半,所以基本上我需要实际图像宽度的一半负边距,但我的整个布局在约束布局和约束布局不允许负边距,所以我实现了以下代码
<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" />
这将使它在视图的底线处居中,水平居中。
将背景视图置于主题视图之后
我想使用负边距来添加一个主题视图后面的视图,这是比例大于主题视图。我发现的解决方案是缩放 android:scaleX="1.2"和 android:scaleY="1.2"的背景视图,同时将其限制在主题的各个方面。
android:scaleX="1.2"
android:scaleY="1.2"
<View android:id="@+id/subjectBackground" android:layout_width="0dp" android:layout_height="0dp" android:scaleY="1.2" android:scaleX="1.2" app:layout_constraintBottom_toBottomOf="@+id/subjectView" app:layout_constraintEnd_toEndOf="@+id/subjectView" app:layout_constraintStart_toStartOf="@+id/subjectView" app:layout_constraintTop_toTopOf="@+id/subjectView" />
你可以试试这个方法,这样简单多了
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" tools:context=".MyProfileFragment"> <ImageView android:id="@+id/imageViewUserPic" android:layout_width="@dimen/dp60" android:src="@mipmap/ic_launcher" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" android:layout_margin="20dp" android:layout_height="wrap_content"> </ImageView> <ImageView android:id="@+id/imageViewEdit" app:layout_constraintBottom_toBottomOf="@+id/imageViewUserPic" android:src="@drawable/ic_edit_red_round" app:layout_constraintEnd_toEndOf="@+id/imageViewUserPic" android:layout_width="wrap_content" android:layout_height="wrap_content"> </ImageView> </androidx.constraintlayout.widget.ConstraintLayout>
布局是这样的。
这就是我的解决方案
<com.oven.test.avatar android:id="@+id/imageview_a" android:layout_width="128dp" android:layout_height="128dp" android:layout_marginTop="28dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent"/> <com.oven.test.smallicon android:id="@+id/small_icon_overlap_a" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="30dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="@+id/imageview_a" app:layout_constraintTop_toTopOf="@+id/imageview_a" app:layout_constraintVertical_bias="1" android:layout_marginBottom="20dp"/>
在你的情况下,使用翻译 X 和翻译 Y 可能会有帮助。
<TextView android:id="@+id/tvText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text" android:translationX="-15dp" android:translationY="10dp" app:layout_constraintEnd_toEndOf="@+id/imageView" app:layout_constraintTop_toTopOf="@+id/imageView" />