Как добиться перекрытия / отрицательной маржи в макете ограничений?
Можно ли достичь отрицательной маржи на схеме ограничений для достижения перекрытия? Я пытаюсь расположить изображение по центру макета и иметь текстовое представление таким образом, чтобы оно перекрывалось на x dp. Я попытался установить отрицательное значение маржи, но не повезло. Было бы здорово, если бы был способ достичь этого.
13 ответов
Хотя не похоже, что отрицательные поля будут поддерживаться в ConstraintLayout
Есть способ добиться эффекта, используя инструменты, которые доступны и поддерживаются. Вот изображение, где заголовок изображения перекрывается 22dp
от нижней части изображения - эффективно -22dp
поле:
Это было достигнуто с помощью Space
Виджет с нижним полем, равным смещению, которое вы хотите.Space
виджет затем имеет свое дно, ограниченное в нижней частиImageView
, Теперь все, что вам нужно сделать, это ограничить вершину TextView
с названием изображения в нижней части Space
виджет. TextView
будет расположен в нижней части Space
просмотр игнорируя установленное поле.
Ниже приведен XML, который выполняет этот эффект. Отмечу, что пользуюсьSpace
потому что это легкий и предназначен для этого типа использования, но я мог бы использовать другой типView
и сделал это невидимым. (Возможно, вам придется внести коррективы.) Вы также можете определить View
с нулевыми полями и высотой поля вставки вы хотите, и ограничить вершину TextView
к началу вставки View
,
Еще один подход заключается в наложенииTextView
на вершинеImageView
выровняв верхние / нижние / левые / правые и сделав соответствующие корректировки полей / отступов. Преимущество подхода, продемонстрированного ниже, состоит в том, что отрицательный запас может быть создан без большого количества вычислений. Это все, чтобы сказать, что есть несколько способов приблизиться к этому.
Обновление. Краткое обсуждение и демонстрация этой техники см. В блоге Google Developers Medium.
Отрицательная маржа для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>
Другой способ использования 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>