Как добиться перекрытия / отрицательной маржи в макете ограничений?

Можно ли достичь отрицательной маржи на схеме ограничений для достижения перекрытия? Я пытаюсь расположить изображение по центру макета и иметь текстовое представление таким образом, чтобы оно перекрывалось на x dp. Я попытался установить отрицательное значение маржи, но не повезло. Было бы здорово, если бы был способ достичь этого.

13 ответов

Решение

Хотя не похоже, что отрицательные поля будут поддерживаться в ConstraintLayoutЕсть способ добиться эффекта, используя инструменты, которые доступны и поддерживаются. Вот изображение, где заголовок изображения перекрывается 22dp от нижней части изображения - эффективно -22dp поле:

Это было достигнуто с помощью SpaceВиджет с нижним полем, равным смещению, которое вы хотите.Spaceвиджет затем имеет свое дно, ограниченное в нижней частиImageView, Теперь все, что вам нужно сделать, это ограничить вершину TextView с названием изображения в нижней части Spaceвиджет. TextView будет расположен в нижней части Space просмотр игнорируя установленное поле.

Ниже приведен XML, который выполняет этот эффект. Отмечу, что пользуюсьSpaceпотому что это легкий и предназначен для этого типа использования, но я мог бы использовать другой типViewи сделал это невидимым. (Возможно, вам придется внести коррективы.) Вы также можете определить View с нулевыми полями и высотой поля вставки вы хотите, и ограничить вершину TextView к началу вставки View,

Еще один подход заключается в наложенииTextViewна вершинеImageViewвыровняв верхние / нижние / левые / правые и сделав соответствующие корректировки полей / отступов. Преимущество подхода, продемонстрированного ниже, состоит в том, что отрицательный запас может быть создан без большого количества вычислений. Это все, чтобы сказать, что есть несколько способов приблизиться к этому.

Обновление. Краткое обсуждение и демонстрация этой техники см. В блоге Google Developers Medium.

Отрицательная маржа дляConstraintLayoutXML

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

Другой способ использования 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 8 июня 2016 г.

Следуйте этим двум вопросам:

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

Это то, что я понял после нескольких часов попыток найти решение.

Давайте рассмотрим два изображения, image1 и image2. Изображение 2 должно быть размещено поверх изображения 1, расположенного справа внизу.

Пример перекрывающихся видов образ

Мы можем использовать виджет Space для перекрывающихся видов.

Ограничьте четыре стороны виджета Space четырьмя сторонами изображения1 соответственно. В этом примере ограничьте левую сторону 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, мы можем ограничить левую и правую стороны image2 левой и правой сторонами виджета Space соответственно. Точно так же мы можем разместить image2 где угодно, изменив ограничения image2 с помощью виджета Space.

Я нашел способ сделать это намного проще.

По сути, есть ImageView, затем в текстовом представлении добавьте ограничение top, чтобы соответствовать верхнему ограничению изображения, и просто добавьте верхнюю границу Text View, чтобы соответствовать, чтобы достигнуть поведения типа поля -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.

А также, если ширина вашего вида не фиксирована, а в процентах, так что вы можете разместить направляющую в процентах и ​​добиться желаемого эффекта

Удачного кодирования:)

Поместите фоновое изображение позади предметного обзора

Я хотел использовать отрицательное поле, чтобы добавить вид позади предметного обзора, который пропорционально больше, чем предметный вид. Решение, которое я нашел, заключалось в масштабировании 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" />

Вам нужно только использовать виджет 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" />

Использование 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" />

Это старый вопрос, но его очень часто задают, самый быстрый способ добиться этого - ограничить верх и низ стороны представления, к которому вы хотите привязаться, например:

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

Простой путь

Я не уверен, лучший способ.

Просто оберните, используя 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>
Другие вопросы по тегам