Apakah menggunakan margin negatif di Android merupakan praktik yang buruk?

114

Demo margin negatif:

                         masukkan deskripsi gambar di sini

Skenario

Tampilan tumpang tindih dengan menyetel margin negatif ke salah satunya sehingga menyerbu kotak pembatas tampilan lain.

Pikiran

Tampaknya berfungsi seperti yang Anda harapkan dengan tumpang tindih tata letak jika seharusnya. Tetapi saya tidak ingin mengalami masalah yang lebih besar karena tanpa sadar tidak melakukan sesuatu dengan benar. Emulator, perangkat fisik, sebut saja, ketika Anda menggunakan margin negatif semuanya tampak bekerja dengan benar, satu tampilan menyerang kotak pembatas tampilan lain dan bergantung pada bagaimana itu dinyatakan dalam tata letak itu akan berada di atas atau di bawah tampilan lain.

Saya juga menyadari bahwa karena API 21 kita dapat mengatur atribut translationZdan elevationuntuk membuat tampilan muncul di atas atau di bawah tampilan lain tetapi perhatian saya pada dasarnya berasal dari fakta bahwa dalam dokumentasi untuk layout_marginatribut itu dengan jelas ditentukan bahwa nilai margin harus positif , biarkan saya mengutip:

Kutipan:
Menentukan ruang ekstra di sisi kiri, atas, kanan dan bawah tampilan ini. Ruang ini berada di luar batas tampilan ini. Nilai margin harus positif . Harus berupa nilai dimensi, yang merupakan bilangan titik mengambang yang ditambahkan dengan unit seperti "14.5sp". Satuan yang tersedia adalah: px (piksel), dp (piksel tanpa kerapatan), sp (piksel yang diskalakan berdasarkan ukuran font yang disukai), dalam (inci), mm (milimeter) ...

Pada tahun-tahun sejak awalnya mengajukan pertanyaan ini, saya tidak memiliki masalah dengan margin negatif, mencoba menghindari penggunaannya sebanyak mungkin, tetapi tidak mengalami masalah apa pun, jadi meskipun dokumentasi menyatakan bahwa, saya tidak juga. khawatir tentang itu.

Juan Cortés
sumber
1
saya tahu tes espresso tidak akan dapat melihat objek jika salah satu marginnya negatif ... jadi itu alasan untuk tidak menggunakannya
Tim Boland

Jawaban:

192

Pada tahun 2010, @RomainGuy (insinyur Android inti) menyatakan bahwa margin negatif memiliki perilaku yang tidak ditentukan .

Pada tahun 2011, @RomainGuy menyatakan bahwa Anda dapat menggunakan margin negatif pada LinearLayoutdanRelativeLayout .

Pada tahun 2016, @RomainGuy menyatakan bahwa mereka tidak pernah didukung secara resmi dan tidak akan didukung olehConstraintLayout .

Sangat mudah untuk mengatasi batasan ini.

Tambahkan tampilan pembantu (tinggi 0dp, lebar dibatasi ke induk) di bagian bawah tampilan dasar Anda, di bagian bawah tambahkan margin yang Anda inginkan.
Kemudian posisikan tampilan Anda di bawah yang satu ini, secara efektif memungkinkannya memiliki margin "negatif" tetapi tanpa harus menggunakan nilai negatif yang tidak didukung.

CommonsWare
sumber
1
Tampaknya menjadi hal yang tidak berbahaya kemudian, dibiarkan terbuka jika ada yang memiliki wawasan lain
Juan Cortés
1
@DrewLeSueur: Saya tidak akan membuat asumsi itu. Saya tidak tahu apa arti padding negatif.
CommonsWare
1
@CommonsWare dapatkah Anda memberi tahu saya, apakah mungkin melakukan sesuatu seperti itu `- @ dimen / anyvalue"? Saya ingin menyebut nilai yang dinyatakan tetapi negatif. Tolong.
deadfish
2
@ 100kg: Maaf, tapi itu tidak didukung.
CommonsWare
21
Saya perhatikan bahwa di Android 4.4 KitKat, ada sesuatu yang berubah sehubungan dengan margin negatif (dibandingkan dengan 4.3; setidaknya pada Asus Nexus 7). Ternyata Anda membutuhkan android:clipChildren="false"dan di android:clipToPadding="false"mana sebelumnya tidak, atau hal - hal rusak seperti ini .
Jonik
18

Semoga ini bisa membantu seseorang. Berikut adalah kode contoh yang berfungsi menggunakan ConstraintLayoutberdasarkan jawaban @ CommonsWare:

Tambahkan tampilan pembantu (tinggi 0dp, lebar dibatasi ke induk) di bagian bawah tampilan dasar Anda, di bagian bawah tambahkan margin yang Anda inginkan. Kemudian posisikan tampilan Anda di bawah yang satu ini, secara efektif memungkinkannya memiliki margin "negatif" tetapi tanpa harus menggunakan nilai negatif yang tidak didukung.

Kode sampel:

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

Keluaran:

masukkan deskripsi gambar di sini

Vikasdeep Singh
sumber
16

Jika Anda ingin menggunakan margin negatif, setel padding yang cukup untuk container dan clipToPaddingnya ke false dan setel margin negatif untuk anak-anaknya sehingga tidak akan memotong tampilan anak!

Ali
sumber
4

Ini mungkin merupakan praktik yang buruk di masa lalu, tetapi dengan Desain Material dan tombol aksi mengambangnya, tampaknya tidak dapat dihindari dan diperlukan dalam banyak kasus sekarang. Pada dasarnya, ketika Anda memiliki dua tata letak terpisah yang tidak dapat Anda masukkan ke dalam RelativeLayout tunggal karena keduanya memerlukan penanganan terpisah yang jelas (pikirkan header dan konten, misalnya), satu-satunya cara untuk tumpang tindih dengan FAB adalah membuatnya menonjol dari salah satunya. tata letak menggunakan margin negatif. Dan ini menciptakan masalah tambahan dengan area yang dapat diklik.

Gábor
sumber
3

Bagi saya, dan mengenai pengaturan margin negatif pada TextView (saya menyadari OP mengacu pada ViewGroup, tetapi saya sedang mencari masalah dengan pengaturan margin negatif dan saya mendarat di sini) ... Saya menemukan masalah dengan 4.0.3 ( API 15) HANYA dan pengaturan android:layout_marginTopatau android:layout_marginBottomke nilai negatif seperti -2dp.

Untuk beberapa alasan, TextView tidak ditampilkan sama sekali. Tampaknya "hilang" dari tampilan (bukan hanya tak terlihat).

Ketika saya mencoba ini dengan 3 versi layout_margin lainnya, saya tidak melihat masalahnya.

Perhatikan bahwa saya belum mencoba ini di perangkat nyata, ini menggunakan emulator 4.0.3. Ini adalah hal aneh ke-2 yang saya temukan yang hanya memengaruhi 4.0.3, jadi aturan baru saya adalah selalu menguji dengan emulator 4.0.3 :)

Saya berhasil mengurangi margin bawah TextView dengan menggunakan android:lineSpacingExtra="-2dp" yang berfungsi meskipun saya kebetulan memilikinya android:singleLine="true"(jadi saya tidak akan berpikir bahwa spasi baris akan menjadi faktor).

GaryAmundson
sumber
1
Saya menemukan perilaku serupa pada Nexus 4 (yaitu xhdpi) dan 4.2.2. Ada tata letak tanpa bantalan, meskipun tata letak induk memiliki bantalan. Ada TextView di dalam dengan marginTop negatif. Pada 5.0 itu bekerja dengan baik. Pada 4.2.2 di perangkat dan di emulator untuk Nexus 4, itu menghilang. Solusinya adalah memindahkan padding ke tata letak yang berisi TextView.
louielouie
3

Tidak, sebaiknya jangan gunakan negative margin. sebagai gantinya Anda harus menggunakan translate. Bahkan jika margin negatif kadang-kadang berfungsi, ketika Anda mengubah tata letak secara terprogram, menerjemahkan akan membantu. Dan tampilan tidak dapat memenuhi layar saat Anda menggunakan margin.

Cheung Sean
sumber
0

Saya hanya tahu bahwa itu mungkin untuk waktu yang agak singkat. Tapi saya tidak melihat ada masalah dengan itu. Berhati-hatilah dengan ukuran layar dan semacamnya sehingga Anda yakin untuk tidak secara tidak sengaja membuat item yang seharusnya tidak tampak tumpang tindih di layar. (yaitu teks di atas teks kemungkinan besar merupakan ide yang buruk.)

FoamyGuy
sumber