Чи погана практика використовувати негативні маржі в Android?


114

Демонстрація від'ємної маржі:

                         введіть тут опис зображення

Сценарій

Перекривання подань, встановивши для одного з них негативний запас, щоб він вторгся у обмежувальне поле іншого подання.

Думки

Здається, це працює так, як ви очікували, перекриваючи макети, якщо вони повинні. Але я не хочу стикатися з більшою проблемою за те, що несвідомо не робити все правильно. Емулятори, фізичні пристрої, ви називаєте це, коли ви використовуєте негативні поля, все, здається, працює нормально, один вид вторкається в обмежувальне поле подань іншого, і залежно від того, як це оголошено в макеті, воно буде вище або нижче іншого.

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

Уривок:
Вказує додатковий простір зліва, у верхній, правій та нижній частині цього подання. Цей простір знаходиться поза межами цього перегляду. Значення маржі повинні бути позитивними . Повинно бути значенням розміру, яке є числом з плаваючою комою, додане до одиниці типу "14.5sp". Доступні одиниці: px (пікселі), dp (незалежні від щільності пікселі), sp (масштабовані пікселі на основі бажаного розміру шрифту), в (дюйми), mm (міліметри) ...

За роки, що спочатку задавали це питання, у мене не було жодних проблем з негативними полями, я намагався уникати їх використання якомога більше, але не стикався з жодними проблемами, тому, хоча в документації зазначено, що я не надто турбує це.


1
я знаю, що тести еспресо не зможуть побачити об’єкт, якщо один з його поля негативний ... так що це причина не використовувати їх
Тім Боланд

Відповіді:


192

У 2010 році @RomainGuy (основний інженер Android) заявив, що негативні маржі мають не визначене поведінку .

У 2011 році @RomainGuy заявив, що ви можете використовувати негативні націнки на LinearLayoutтаRelativeLayout .

У 2016 році @RomainGuy заявив, що вони ніколи не були офіційно підтримувані і не будуть підтримуватисяConstraintLayout .

Однак обходити це обмеження досить просто.

Додайте помічник подання (висота 0dp, ширина обмежена для батьків) внизу базового виду, внизу додайте потрібний запас.
Потім розташуйте свій погляд нижче цього, фактично дозволяючи йому мати "від'ємний" запас, але без використання жодного непідтримуваного негативного значення.


1
Тоді це здається нешкідливим, залишаючи відкритим, якщо хтось має інше розуміння
Хуан Кортес

1
@DrewLeSueur: Я б не робив цього припущення. Я поняття не маю, що навіть значить негативна накладка.
CommonsWare

1
@CommonsОбережно, ви можете мені сказати, чи можна зробити щось подібне `- @ dimen / anyvalue"? Я хочу зателефонувати оголошеним значенням, але негативним. Довідка.
Deadfish

2
@ 100 кг: Вибачте, але це не підтримується.
CommonsWare

21
Я помітив, що в Android 4.4 KitKat щось змінилося щодо негативних запасів (порівняно з 4.3; принаймні для Asus Nexus 7). Виявляється, вам потрібно android:clipChildren="false"і android:clipToPadding="false"там, де ви раніше цього не робили, або такі речі ламаються так .
Джонік

18

Сподіваюся, що це комусь допоможе. Тут працює зразок коду з використанням 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" />

Вихід:

введіть тут опис зображення


16

Якщо ви хочете використовувати негативну маржу, встановіть достатню кількість прокладки для контейнера та його clipToPadding на помилкові та встановіть негативну маржу для своїх дітей, щоб вона не обрізала дитячий вигляд!


4

Можливо, це було поганою практикою в минулому, але з дизайном матеріалу та його плаваючими кнопками дії це здається неминучим і потрібним у багатьох випадках зараз. В основному, якщо у вас є два окремі макети, які ви не можете скласти в один RelativeLayout, оскільки їм потрібно чітко окреме управління (наприклад, заголовок і вміст), єдиний спосіб перекрити FAB - це зробити його стирчаним з одного з цих макетів, використовуючи негативні маржі. А це створює додаткові проблеми з областями, які можна натискати.


3

Що стосується встановлення негативної маржі на TextView (я розумію, що ОП посилається на ViewGroup, але я шукав проблеми з встановленням негативних націнок, і я приземлився тут) ... Я знайшов проблему з 4.0.3 ( API 15) ТІЛЬКИ та налаштування android:layout_marginTopабоandroid:layout_marginBottom на негативне значення, таке як -2dp.

Чомусь TextView взагалі не відображається. Це, здається, "пішло" з виду (не просто невидимого).

Коли я спробував це з іншими 3 версіями layout_margin, я не бачив проблеми.

Зауважте, що я не пробував цього на реальному пристрої, для цього використовується емулятор 4.0.3. Це 2 дивна річ, яку я виявив, що це стосується лише 4.0.3, тому моє нове правило - завжди перевіряти емулятором 4.0.3 :)

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


1
Я виявив подібну поведінку на Nexus 4 (це xhdpi) та 4.2.2. Був макет без прокладки, хоча батьківський макет мав прокладку. Всередині був TextView з негативним marginTop. На 5.0 він працював чудово. 4.2.2 і на пристрої, і в емуляторі для Nexus 4 він зникає. Рішенням було перенести прокладку на макет, що містив TextView.
louielouie

3

Ні, не слід використовувати negative margin. замість цього слід використовувати translate. Навіть якщо негативний запас працює колись, коли ви програмово змінюєте макет, переклад допоможе. І перегляд не може переповнювати екран, коли ви використовуєте поле.


0

Я знав лише, що це було можливо за досить короткий проміжок часу. Але я не бачу в цьому жодної проблеми. Просто пам’ятайте про розміри екрана, і так ви впевнені, що випадково не зробите предмети, які не повинні відображатись на екрані. (тобто текст у верхній частині тексту, ймовірно, погана ідея.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.