Android 如何在约束布局上实现重叠/负边距?

Android 如何在约束布局上实现重叠/负边距?,android,android-constraintlayout,constraint-layout-chains,Android,Android Constraintlayout,Constraint Layout Chains,是否可以在约束布局上实现负边距以实现重叠? 我试图有一个以布局为中心的图像,并有一个文本视图,使其与一个x dp重叠。我尝试设置负的边距值,但没有成功。 如果有办法做到这一点,那就太好了 在RelativeLayout中,官方从未支持负利润率CONSTRAINTLAOUT中不支持负边距。[…] --2016年6月8日Romain Guy 关注以下两个问题: 更新 ConstraintLayout现在支持2.1.0-alpha2版本的负边距。简单陈述 android:layout_marginT

是否可以在约束布局上实现负边距以实现重叠? 我试图有一个以布局为中心的图像,并有一个文本视图,使其与一个x dp重叠。我尝试设置负的边距值,但没有成功。 如果有办法做到这一点,那就太好了

在RelativeLayout中,官方从未支持负利润率CONSTRAINTLAOUT中不支持负边距。[…]

--2016年6月8日Romain Guy

关注以下两个问题:

更新 ConstraintLayout现在支持2.1.0-alpha2版本的负边距。简单陈述

android:layout_marginTop="-25dp"
对于负25dp余量。(他们说这是办不到的!)



澄清:下面的答案仍然有效,但我想澄清几件事。原始解决方案将放置一个相对于另一个视图实际负偏移的视图,如图所示,并将显示在布局中

另一个解决方案是使用Amir Khorsandi建议的translationY属性。我更希望该解决方案更简单,但有一点需要注意:转换发生在布局后,因此受置换视图约束的视图不会跟随转换

例如,下面的XML在图像的正下方显示两个文本视图。每个视图都受到从上到下的约束,且视图显示在其正上方

这将产生以下结果:

“说出我的名字”文本视图已按预期向上移动,但“说出我的名字”文本视图并没有按预期向上移动。这是因为翻译发生在布局后。尽管视图移动了后期布局,但仍可以在新位置单击该视图

因此,在我看来,如果上述警告不影响您的布局,请在ConstraintLayout中使用translationX和translationY作为负边距;否则,使用下面概述的space小部件

另一个警告:正如Salam El Banna在对另一个答案的评论中所述,translationX对于RTL布局不是一个好的解决方案,因为无论布局的RTL或LTR性质如何,翻译的符号将指示移位的方向(左/右)


原始答案

虽然
ConstraintLayout
中似乎不支持负边距,但有一种方法可以使用可用和支持的工具实现此效果。这是一幅图像,其中图像标题与图像底部的
22dp
重叠-实际上是
-22dp
边距:

这是通过使用一个底部边距等于所需偏移量的小部件来实现的。然后,
空间
小部件将其底部约束到
图像视图
的底部。现在,您需要做的就是将带有图像标题的
文本视图的顶部约束到
空间
小部件的底部。
TextView
将位于
空间的底部
视图,忽略已设置的边距

以下是实现此效果的XML。我会注意到我使用了
空间
,因为它是轻量级的,适合这种类型的使用,但我可以使用另一种类型的
视图
,使其不可见。(不过,您可能需要进行调整。)您还可以定义一个边距和插入边距高度为零的
视图,并将
文本视图的顶部约束到插入
视图的顶部

另一种方法是通过对齐顶部/底部/左侧/右侧,将
文本视图
覆盖在
图像视图
的顶部,并对边距/填充进行适当调整。下面演示的方法的好处是,无需大量计算即可创建负裕度。也就是说,有几种方法可以实现这一点

更新:有关此技术的快速讨论和演示,请参阅Google开发者媒体

约束列表的负边距
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,然后在文本视图上添加top constraint以匹配图像的top constraint,只需添加TextView的边距top以匹配即可实现-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
如下:

  <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\u marginRight=“-25dp”

经过数小时的努力,我终于找到了解决方案

我们考虑两个图像IMAGE1和IMAGE2。将图像2放置在图像1的顶部,图像1位于右下侧

重叠视图示例

我们可以使用Space小部件处理重叠视图

分别用image1的四边约束空间小部件的四边。对于本例,将image2的左侧约束为空间小部件的右侧,将image2的顶部约束为空间小部件的底部。这将把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的中间底部,我们可以分别用空格小部件的左侧和右侧约束image2的左侧和右侧。类似地,我们可以通过使用Space widget更改image2的约束来将image2放置在任何位置。

这将帮助许多人

在我的情况下,我希望我的设计如下:

  <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" 
                android:translationX="25dp"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"/>

表示我希望我的图像显示其宽度的一半,以便
<?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>
<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>
<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" />
<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"/>