簡體   English   中英

如何在約束布局上實現重疊/負邊距?

[英]How to achieve overlap/negative margin on Constraint Layout?

是否可以在約束布局上實現負邊距以實現重疊? 我試圖讓圖像以布局為中心,並有一個文本視圖,使其與 x dp 重疊。 我嘗試設置負邊際值但沒有運氣。 如果有辦法實現這一目標,那就太好了。

更新ConstraintLayout現在支持 2.1.0-alpha2 版本的負邊距。 簡單說明

android:layout_marginTop="-25dp"

負 25dp 邊距。 (他們說這不可能完成!)



澄清:下面的答案仍然有效,但我想澄清一些事情。 原始解決方案將放置一個視圖,該視圖相對於另一個視圖具有事實上的負偏移量,並將出現在如圖所示的布局中。

另一種解決方案是使用 Amir Khorsandi here建議的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>

現在,讓我們通過指定將“Say my name” TextView向上翻譯50dp

android:translationY="-50dp"

這會產生以下結果:

在此處輸入圖片說明

“Say my name” TextView已按預期向上移動,但“Say it” TextView並沒有像我們預期的那樣跟進。 這是因為翻譯發生在布局后 盡管視圖在布局后移動,但它仍然可以在新位置點擊。

因此,IMO,如果上面的警告不影響您的布局,請使用translationXtranslationY用於ConstraintLayout 中的負邊距; 否則,請使用下面概述的空間小部件。

另一個警告:正如 Salam El-Banna 在對另一個答案的評論中所述, translationX將不是 RTL 布局的一個好的解決方案,因為翻譯的符號將決定移位的方向(左/右),而不管 RTL 或LTR 布局的性質。


原答案

盡管ConstraintLayout似乎不支持負邊距,但有一種方法可以使用可用和支持的工具來實現這種效果。 這是一張圖像,其中圖像標題與圖像底部重疊22dp - 實際上是-22dp邊距:

在此處輸入圖片說明

這是通過使用底部邊距等於所需偏移量的Space小部件來實現的。 然后Space小部件的底部被限制在ImageView的底部。 現在您需要做的就是將帶有圖像標題的TextView的頂部限制在Space小部件的底部。 TextView將位於Space視圖的底部,忽略設置的邊距。

下面是實現這種效果的 XML。 我會注意到我使用Space是因為它是輕量級的,適用於這種類型的用途,但我可以使用另一種類型的View並使其不可見。 (不過,您可能需要進行調整。)您還可以定義一個具有零邊距的View和所需的插入邊距的高度,並將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>

另一種方法是使用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"

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

這是我在嘗試尋找解決方案數小時后得出的結論。

讓我們考慮兩個圖像,image1 和 image2。 Image2 將放置在位於右下側的 image1 的頂部。

重疊視圖示例圖片

我們可以使用Space小部件來重疊視圖。

分別用 image1 的四個邊約束 Space 小部件的四個邊。 對於此示例,將圖像 2 的左側與空間小部件的右側和圖像 2 的頂部與空間小部件的底部進行約束。 這會將 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 上添加頂部約束以匹配圖像的頂部約束,只需添加 TextView 的邊距頂部以匹配以實現 -ve 邊距類型行為。

這將幫助許多

就我而言,我希望我的設計是這樣的:

后

意味着我希望我的圖像顯示其寬度的一半,所以基本上我需要實際圖像寬度一半的負邊距,但我在約束布局和約束布局中的整個布局不允許負邊距,所以我用下面的代碼實現了這一點

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

將背景視圖放在主題視圖后面

我想使用負邊距在比主題視圖成比例大的主題視圖后面添加一個視圖。 我找到的解決方案是縮放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" />

這是一個老問題,但問得很多,實現這一目標的最快方法是將頂部和底部限制在您想要錨定的視圖的一側,如下所示:

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

這將它在視圖的底線居中,水平居中。

可以試試這個方法,這個簡單多了

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

使用 translationX 和 translationY 可能適用於您的情況。

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

一個簡單的方法。

我不確定最好的方法。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM