如何在Constraint Layout上实现重叠/负边距?

时间:2017-03-23 19:08:08

标签: android android-constraintlayout constraint-layout-chains

是否有可能在约束布局上实现负余量以实现重叠? 我试图让一个图像以布局为中心,并有一个文本视图,使其重叠x x dp。我尝试设置负保证金值,但没有运气。 如果有办法实现这一目标会很棒。

12 个答案:

答案 0 :(得分:134)

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

enter image description here

这是通过使用Space窗口小部件完成的,其下边距等于您想要的偏移量。 Space窗口小部件的底部约束在ImageView的底部。现在,您需要做的就是将TextView的顶部约束为Space窗口小部件底部的图片标题。 TextView将位于Space视图底部,忽略设置的边距。

以下是实现此效果的XML。我会注意到我使用Space因为它是轻量级的并且打算用于此类用途,但我可以使用其他类型的View并使其不可见。 (不过,您可能需要进行调整。)您还可以定义一个零边距View和所需插入边距的高度,并将TextView的顶部约束到顶部插入View

另一种方法是通过对齐顶部/底部/左侧/右侧来覆盖TextView顶部ImageView,并对边距/填充进行适当调整。下面演示的方法的好处是可以在没有大量计算的情况下创建负余量。这就是说有几种方法可以解决这个问题。

更新:有关此技术的快速讨论和演示,请参阅Google Developers Medium blog post

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>

答案 1 :(得分:34)

另一种方法是像这样使用translationXtranslationY

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

答案 2 :(得分:20)

  

RelativeLayout从未正式支持负边距。 ConstraintLayout不支持负边距。 [...]

     

- 2016年6月8日的Romain Guy

请遵循以下两个问题:

https://code.google.com/p/android/issues/detail?id=212499 https://code.google.com/p/android/issues/detail?id=234866

答案 3 :(得分:11)

我找到了一种更简单的方法。

基本上有ImageView,然后在文本视图上添加顶部约束以匹配图像的顶部约束,只需添加TextView的边缘顶部以匹配以实现-ve边距类型行为。

答案 4 :(得分:6)

这是我在试图寻找解决方案数小时后才想到的。

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

重叠视图示例 image

我们可以使用 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放置在任何地方。

答案 5 :(得分:3)

这会帮助很多

在我的情况下,我想要这样的设计:

after

意味着我希望我的图像显示其宽度的一半,所以基本上我需要一半实际图像宽度的负边距,但是我在约束布局和约束布局中的整个布局都不允许负边界,所以我实现了这一点使用以下代码

<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开始时的负边距相同。

此外,如果视图的宽度不是固定的,而是以百分比为单位的,那么您可以按百分比放置辅助线,并实现所需的效果

快乐编码:)

答案 6 :(得分:1)

您只需要在布局中使用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" />

答案 7 :(得分:1)

将背景视图置于主题视图后面

我想使用负边距在主题视图后面添加一个比主题视图大的视图。我找到的解决方案是缩放 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" />

答案 8 :(得分:0)

这是一个古老的问题,但仍然存在很多问题,实现此目的的最快方法是将视图的顶部和底部限制在要锚定的视图的侧面,例如:

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

这会将其居中放置在视图的底部,水平居中。

答案 9 :(得分:0)

可以试试这个方法,这样简单多了

 <?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>

布局会是这样.. enter image description here

答案 10 :(得分:0)

这是我的解决方案

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

答案 11 :(得分:-1)

一个简单的方法。

我不确定最好的方式。

使用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>