¿Es una mala práctica utilizar márgenes negativos en Android?


Demostración del margen negativo:

                         introduzca la descripción de la imagen aquí

El escenario

Superponer vistas estableciendo un margen negativo en una de ellas para que invada el cuadro delimitador de otra vista.

Pensamientos

Parece que funciona de la manera que esperarías con la superposición de los diseños si es que lo hacen. Pero no quiero encontrarme con un problema mayor por no hacer las cosas bien sin saberlo. Emuladores, dispositivos físicos, lo que sea, cuando se utiliza márgenes negativos todo parece funcionar correctamente, una vista invade el cuadro delimitador de otras vistas y dependiendo de cómo se declare en el diseño, estará por encima o por debajo de la otra vista.

También soy consciente de que desde API 21 podemos establecer la translationZ y elevation atributos para hacer que la vista aparezca por encima o por debajo de otras vistas, pero mi preocupación básicamente proviene del hecho de que en la documentación para los atributos layout_margin se especifica claramente que los valores de margen deben ser positivos, permítanme citar:

Extracto:
Especifica espacio adicional en los lados izquierdo, superior, derecho e inferior de esta vista. Este espacio está fuera de los límites de esta vista. Los valores del margen deben ser positivos. Debe ser un valor de dimensión, que es un número de punto flotante agregado con una unidad como "14.5 sp". Las unidades disponibles son: px (píxeles), dp (píxeles independientes de la densidad), sp (píxeles escalados según el tamaño de fuente preferido), in (pulgadas), mm (milímetros)...

En los años desde que hice esta pregunta originalmente no he tenido ningún problema con márgenes negativos, intenté evitar usarlos tanto como me fue posible, pero no encontré ningún problema, así que a pesar de que la documentación dice eso, no estoy demasiado preocupado por eso.

Author: Juan Cortés, 2012-05-20

7 answers

En 2010, @RomainGuy (ingeniero principal de Android) declaró que los márgenes negativos tenían un comportamiento no especificado.

En 2011, @ RomainGuy declaró que puede usar márgenes negativos en LinearLayout y RelativeLayout.

En 2016, @ RomainGuy declaró que nunca han sido soportados oficialmente y no serán soportados por ConstraintLayout.

Sin embargo, es fácil trabajar alrededor de esta limitación.

Agregue una vista auxiliar (altura 0dp, ancho restringido al padre) en la parte inferior de su vista base, en la parte inferior agregue el margen que desee.
Luego coloque su vista debajo de esta, permitiéndole efectivamente tener un margen "negativo" pero sin tener que usar ningún valor negativo no compatible.

 163
Author: CommonsWare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-16 12:09:00

En caso de que desee utilizar el margen negativo,establezca suficiente relleno para el contenedor y su clipToPadding a false y establezca el margen negativo para sus hijos para que no recorte la vista hija!

 11
Author: Ali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-17 15:26:23

Podría haber sido una mala práctica en el pasado, pero con Material Design y sus botones de acción flotante, parece ser inevitable y requerido en muchos casos ahora. Básicamente, cuando tienes dos diseños separados que no puedes poner en un solo RelativeLayout porque necesitan un manejo claramente separado (piensa en encabezado y contenido, por ejemplo), la única manera de superponer el FAB es hacerlo sobresalir de uno de esos diseños usando márgenes negativos. Y esto crea problemas adicionales con áreas en las que se puede hacer clic.

 4
Author: Gábor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-21 19:27:59

Espero que esto ayude a alguien. Aquí está el código de ejemplo de trabajo usando ConstraintLayout basado en la respuesta de @CommonsWare:

Agregar una vista auxiliar (altura 0dp, ancho restringido al padre) en el en la parte inferior de la vista base, en la parte inferior agregue el margen que desee. Entonces posicione su vista debajo de esta, permitiéndole efectivamente tener un margen "negativo" pero sin tener que utilizar ningún negativo no admitido valor.

Muestra código:

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

Salida:

introduzca la descripción de la imagen aquí

 4
Author: VicJordan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-07 06:47:27

Para mí, y con respecto a establecer un margen negativo en un TextView (me doy cuenta de que el OP se refiere a un ViewGroup, pero estaba buscando problemas con el establecimiento de márgenes negativos y aterricé aquí)... Encontré un problema con 4.0.3 (API 15) SOLAMENTE y la configuración de android:layout_marginTop o android:layout_marginBottom a un valor negativo como-2dp.

Por alguna razón el TextView no se muestra en absoluto. Parece haber "desaparecido" de la vista (no solo invisible).

Cuando probé esto con las otras 3 versiones de layout_margin, no vi el problema.

Tenga en cuenta que no he probado esto en un dispositivo real, esto está utilizando un emulador 4.0.3. Esta es la segunda cosa extraña que he encontrado que solo afectó a 4.0.3, por lo que mi nueva regla es siempre probar con un emulador 4.0.3:)

Tengo éxito con la reducción del margen inferior de un TextView mediante el uso de android:lineSpacingExtra="-2dp" que funciona a pesar de que resulta que tengo android:singleLine="true" (y por lo que no habría pensado que el interlineado sería un factor).

 3
Author: GaryAmundson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-03 16:13:34

No, no debe usar negative margin. en su lugar, debe usar translate. Incluso si el margen negativo funciona en algún momento, cuando cambia el diseño de forma programable, traducir ayudaría. Y la vista no puede desbordar la pantalla cuando se utiliza el margen.

 1
Author: Cheung Sean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-28 05:48:54

Solo he sabido que era posible por un corto período de tiempo. Pero no veo ningún problema con eso. Solo tenga en cuenta los tamaños de pantalla y tales para que esté seguro de no hacer accidentalmente a los elementos que no deben aparecer superpuestos en la pantalla. (es decir, el texto encima del texto es probablemente una mala idea.)

 0
Author: FoamyGuy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-20 12:49:03