Это плохая практика, чтобы использовать отрицательные поля в Android?


демонстрация отрицательной маржи:

сценарий

перекрывающиеся виды, устанавливая отрицательное поле для одного из них, чтобы он вторгался в ограничивающую рамку другого вида.

мысли

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

Я также знаю, что с API 21 мы можем установить translationZ и elevation атрибуты, чтобы сделать вид появляются выше или ниже других видов, но моя забота в основном исходит из того, что в документация на layout_margin атрибуты это четко указано, что значения маржи должны быть положительными позвольте мне процитировать:

выдержка:
указывает дополнительное пространство на левой, верхней, правой и нижней сторонах этого вида. Это пространство находится за пределами этого представления. значения маржи должны быть положительными. Должно быть значение измерения, которое представляет собой число с плавающей запятой, добавленное с единицей измерения, такой как "14.5 sp". Доступный единицы измерения: px (пиксели), dp (независимые от плотности пиксели), sp (масштабированные пиксели на основе предпочтительного размера шрифта), in (дюймы), mm (миллиметры)...

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

7 97

7 ответов:

В 2010 году @RomainGuy (core Android engineer) заявил, что отрицательные поля имели неопределенное поведение.

В 2011 году @RomainGuy заявил, что вы можете использовать отрицательные поля на LinearLayout и RelativeLayout.

В 2016 году @RomainGuy заявил, что они никогда официально не поддерживались и не будут поддерживаться ConstraintLayout.

это легко обойти это ограничение, хотя.

добавить вспомогательный вид (высота 0dp, ширина ограничена родительским) в нижней части базового вида, в нижней части добавить поле, которое вы хотите.
Затем поместите свой взгляд ниже этого, эффективно позволяя ему иметь "отрицательный" запас, но без необходимости использовать любое неподдерживаемое отрицательное значение.

Если вы хотите использовать отрицательное поле, установите достаточное заполнение для контейнера и его clipToPadding для false и установить отрицательное поле для его детей, так что он не будет обрезать представление ребенка!

возможно, это была плохая практика в прошлом, но с материальным дизайном и его плавающими кнопками действия это кажется неизбежным и необходимым во многих случаях сейчас. В принципе, когда у вас есть два отдельных макета, которые вы не можете поместить в один RelativeLayout, потому что им нужна отчетливо отдельная обработка (например, заголовок и содержимое think), единственный способ перекрыть FAB-это заставить его торчать из одного из этих макетов, используя отрицательные поля. И это создает дополнительные проблемы с областей.

надеюсь, это поможет кому-то. Вот рабочий пример кода с помощью ConstraintLayout на основе ответа @CommonsWare:

добавить вспомогательный вид (высота 0dp, ширина ограничена родительским) на в нижней части базового вида, в нижней части добавить поле, которое вы хотите. Затем расположите свой взгляд ниже этого, эффективно позволяя ему иметь "отрицательная" маржа, но без необходимости использовать какой-либо неподдерживаемый негатив значение.

образец код:

<TextView
    android:id="@+id/below"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#F1B36D"
    android:padding="30dp"
    android:text="I'm below"
    android:textColor="#ffffff"
    android:textSize="48sp"
    android:textAlignment="center"
    tools:layout_editor_absoluteX="129dp"
    tools:layout_editor_absoluteY="0dp" />

<android.support.v4.widget.Space
    android:id="@+id/space"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_marginBottom="32dp"
    app:layout_constraintBottom_toBottomOf="@+id/below"
    app:layout_constraintLeft_toLeftOf="@id/below"
    app:layout_constraintRight_toRightOf="@id/below" />

<TextView
    android:id="@+id/top"
    android:layout_width="100dp"
    android:layout_height="60dp"
    android:textAlignment="center"
    android:textColor="#ffffff"
    android:text="I'M ON TOP!"
    android:background="#676563"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/space" />

выход:

enter image description here

для меня и относительно установки отрицательного поля на TextView (я понимаю, что OP относится к ViewGroup, но я искал проблемы с установкой отрицательных полей, и я приземлился здесь)... Я нашел проблему только с 4.0.3 (API 15) и настройкой android:layout_marginTop или android:layout_marginBottom к отрицательному значению, например-2dp.

по какой-то причине TextView не отображается вообще. Он кажется "ушедшим" из поля зрения (а не просто невидимым).

когда я попробовал это с другим 3 версии layout_margin, я не вижу проблемы.

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

у меня есть успех с уменьшением нижнего поля TextView с помощью android:lineSpacingExtra="-2dp", который работает, хотя у меня есть android:singleLine="true" (и поэтому я бы не подумал, что межстрочный интервал будет фактор.)

нет, вы не должны использовать negative margin. вместо этого вы должны использовать translate. Даже если отрицательная маржа когда-нибудь сработает, когда вы измените макет программно, translate поможет. И вид не может переполнить экран, когда вы используете маржу.

Я только знал, что это было возможно в течение довольно короткого периода времени. Но я не вижу в этом никаких проблем. Просто имейте в виду размеры экрана и такие, так что вы уверены, что не случайно сделать, чтобы элементы, которые не должны появляться перекрываются на экране. (т. е. текст поверх текста, вероятно, плохая идея.)