Menempatkan / Tumpang tindih (indeks-z) tampilan di atas tampilan lain di android

230

Saya memiliki tata letak linier yang terdiri dari tampilan gambar dan tampilan teks, satu di bawah yang lain dalam tata letak linier.

<LinearLayout android:orientation="horizontal" ... >
 <ImageView 
     android:id="@+id/thumbnail"
     android:layout_weight="0.8" 
     android:layout_width="0dip"
     android:layout_height="fill_parent">
 </ImageView>
 <TextView 
    android:id="@+id/description"
    android:layout_weight="0.2"
    android:layout_width="0dip"
    android:layout_height="wrap_content">
 </TextView>

Beberapa aturan mungkin hilang, ini untuk memberikan gambaran, bagaimana tata letak terlihat. Saya ingin tampilan teks kecil lain katakan 50dip panjang dan lebar, ditempatkan di atas imageview, dengan "lebih" Maksud saya z-indeks lebih dari imageview, saya ingin menempatkan ini, di tengah dan di atas (tumpang tindih) imageview.

Saya ingin tahu bagaimana kita dapat menempatkan satu tampilan di atas yang lain, dengan indeks-z yang bervariasi (lebih disukai dalam tata letak linier)?

duduk
sumber

Jawaban:

295

Anda tidak bisa menggunakan LinearLayout untuk ini, tetapi Anda bisa menggunakan a FrameLayout. Dalam a FrameLayout, indeks-z ditentukan oleh urutan penambahan item, misalnya:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/my_drawable"
        android:scaleType="fitCenter"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center"
        android:padding="5dp"
        android:text="My Label"
        />
</FrameLayout>

Dalam hal ini, TextView akan digambar di atas ImageView, di sepanjang tengah bawah gambar.

Kevin Coppock
sumber
Ya saya melakukannya menggunakan tata letak bingkai sendiri setelah melalui dokumentasi. Terima kasih.
Duduk
11
Apakah ada keuntungan menggunakan FrameLayout, bukan RelativeLayout untuk ini?
Ixx
12
FrameLayout tidak berhubungan dengan tampilan lain dalam grup, itu hanya lapisan mereka sehubungan dengan orangtua. RelativeLayout lebih untuk penentuan posisi relatif terhadap item lain.
Kevin Coppock
3
Hai kcoppock ponsel saya (hdpi) tidak menghormati z-order dalam tata letak bingkai, tetapi saya punya yang lain (xhdpi) dan menghormati pesanan ini, apakah Anda tahu mengapa melakukan ini? Terima kasih sebelumnya! : D
Merlí Escarpenter Pérez
1
Pada API 21 / KitKat sekarang Anda dapat menggunakan setZ dan translationZ; hack FrameLayout tidak lagi diperlukan (akhirnya!). Ini harus menjadi jawaban yang disukai untuk pengembangan 5.0+ modern: stackoverflow.com/a/29703860/358578
pbarranis
183

Cobalah .bringToFront() :

http://developer.android.com/reference/android/view/View.html#bringToFront%28%29

diyism
sumber
3
dapatkah kita menggunakan ini dalam file xml juga?
Iklan
2
Saya sedang mencari sesuatu seperti membawa pandangan saya untuk mengubah itz zindex selama animasi terjemahan.
DeltaCap019
Bisakah Anda menemukan solusi untuk animasi terjemahan?
nAkhmedov
9
bringChildToFront () baru saja mengubah indeks Tampilan di dalam induknya
Zar E Ahmer
4
ini
mengacaukan
66

RelativeLayout bekerja dengan cara yang sama, gambar terakhir dalam tata letak relatif menang.

jt-gilkeson
sumber
14
Kecuali Anda menggunakan elevasi, maka Anda juga membutuhkan nilai terbesar dalam hal itu.
Sami Kuhmonen
5
Pertanyaan ini ditanyakan dan dijawab sebelum elevasi ada. Menggunakan elevasi tidak akan memperbaiki masalah jika aplikasi Anda memiliki minSdk kurang dari Lollipop (pada ponsel pra-lollipop tata letak akan terlihat salah jika Anda hanya mengandalkan elevasi) - Anda masih harus memperhatikan urutan tata letak. Anda benar, bahwa jika Anda menggunakan elevasi pada komponen bawah - Anda pasti harus memiliki setidaknya yang sama atau lebih tinggi di atas.
jt-gilkeson
27

Mengubah urutan undian

Alternatifnya adalah mengubah urutan pandangan yang diambil oleh orang tua. Anda dapat mengaktifkan fitur ini dari ViewGroup dengan memanggil setChildrenDrawingOrderEnabled (true) dan mengganti getChildDrawingOrder (int childCount, int i) .

Contoh:

/**
 * Example Layout that changes draw order of a FrameLayout
 */
public class OrderLayout extends FrameLayout {

    private static final int[][] DRAW_ORDERS = new int[][]{
            {0, 1, 2},
            {2, 1, 0},
            {1, 2, 0}
    };

    private int currentOrder;

    public OrderLayout(Context context) {
        super(context);
        setChildrenDrawingOrderEnabled(true);
    }

    public void setDrawOrder(int order) {
        currentOrder = order;
        invalidate();
    }

    @Override
    protected int getChildDrawingOrder(int childCount, int i) {
        return DRAW_ORDERS[currentOrder][i];
    }
}

Keluaran:

Memanggil OrderLayout#setDrawOrder(int)dengan hasil 0-1-2 di:

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Tobrun
sumber
Apakah Anda memanggil setDrawOrder (i) di onCreate aktivitas ()? Jika saya memiliki 6 widget di xml, apakah saya harus menginisialisasi setiap baris DRAW_ORDERS dengan array 6 angka (0-5)?
John Ward
@JohnWard tata letak yang ditunjukkan di atas hanya untuk tujuan contoh, Anda dapat menentukan perilaku Anda sendiri di getChildDrawingOrder ().
Tobrun
inilah pos terkait dengan kode yang lebih jelas: stackoverflow.com/questions/20524162/framelayout-in-reverse
Robert
20

Anda dapat menggunakan view.setZ(float)mulai dari API level 21. Di sini Anda dapat menemukan info lebih lanjut.

Vadim Kotov
sumber
3
Ini sekarang harus menjadi jawaban yang disukai untuk API 21 / KitKat / 5.0 atau lebih tinggi. Untungnya hack frameLayout lama tidak lagi diperlukan. Secara pribadi saya tidak mengerti perbedaan antara setZ dan translationZ, tetapi yang terakhir adalah atribut dan bekerja dengan baik untuk saya. Terima kasih!
pbarranis
Untuk apis sebelumnya, Anda dapat menggunakan ViewCompat # setZ () juga.
Ali Yucel Akgul
@AliYucelAkgul jika Anda melihat dokumen di sini , Anda dapat melihat Compatibility: API < 21: No-op . Jadi saya pikir itu tidak akan berhasil
Vadim Kotov
@VadimKotov, saya telah mencoba di aplikasi saya dan itu hanya berfungsi.
Ali Yucel Akgul
@ AliYucelAkgul yah, itu aneh. Mungkin ada kesalahan dalam dokumen? Apakah Anda 100% yakin itu berfungsi untuk API <21? Saya punya ide bahwa itu dapat mengubah urutan tampilan untuk API sebelumnya, tetapi tidak ada hal-hal mewah seperti ketinggian, dll.
Vadim Kotov
14

Saya memecahkan masalah yang sama dengan menambahkan android:elevation="1dp"ke tampilan yang Anda inginkan di atas yang lain. Tapi itu tidak bisa ditampilkan di bawah 5.0, dan itu akan memiliki sedikit bayangan, jika Anda bisa menerimanya, tidak apa-apa.

Jadi, solusi paling benar yaitu @kcoppock berkata.

tiga puluh yuan
sumber
7

Coba ini di RelativeLayout:

ImageView image = new ImageView(this);
image.SetZ(float z);

Ini bekerja untuk saya.

Rizzo
sumber
2
Anda harus menjelaskan sedikit lebih baik. Misalnya di mana Anda meletakkan kode ini?
DevB2F
Yah, saya memasukkannya ke metode OnCreate (). Setiap gambar yang ditambahkan memiliki indeks preferensi z daripada yang ditambahkan sebelumnya. Maksud saya, melalui indeks z saya dapat mengubah posisi berikutnya di belakang sebelumnya.
Rizzo
5

Ada cara untuk menggunakan LinearLayout. Cukup atur marginTop elemen Anda sebelumnya ke nilai negatif yang sesuai, dan pastikan elemen yang Anda inginkan di atas adalah setelah elemen yang Anda inginkan di bawah ini di XML Anda.

<linearLayout android:orientation="horizontal" ... >
<ImageView 
 android:id="@+id/thumbnail"
 android:layout_weight="0.8" 
 android:layout_width="0dip"
 android:layout_height="fill_parent"
>
</ImageView>
<TextView 
android:id="@+id/description"
android:layout_marginTop="-20dip"
android:layout_weight="0.2"
android:layout_width="0dip"
android:layout_height="wrap_content"
>
</TextView>
Tim
sumber
4

AFAIK Anda tidak dapat melakukannya dengan tata letak linier, Anda harus pergi untuk RelativeLayout .

Vincent Mimoun-Prat
sumber
RelativeLayout tidak memperpanjang frameLayout, apakah Anda yakin itu akan berhasil?
ekatz
Itu akan. Anda dapat menggunakan FrameLayout atau RelativeLayout. Masing-masing memiliki cara berbeda dalam menempatkan pandangan anak. Rujuk ke dokumen untuk mengetahui lebih lanjut tentang tata letak itu.
Vincent Mimoun-Prat
ini adalah cara untuk pergi
Albert James Teddy
0

Jika Anda menambahkan Lihat secara terprogram, Anda dapat menggunakan yourLayout.addView(view, 1);

mana 1 is the index.

Alexander Maslew
sumber
0

Saya menggunakan ini, jika Anda ingin hanya satu tampilan yang dibawa ke depan saat dibutuhkan:

containerView.bringChildToFront(topView);

containerView adalah wadah tampilan yang akan disortir, topView adalah tampilan yang ingin saya miliki sebagai yang teratas dalam wadah.

untuk beberapa tampilan diatur adalah akan menggunakan setChildrenDrawingOrderEnabled (true) dan mengesampingkan getChildDrawingOrder (int childCount, int i) seperti yang disebutkan di atas.

Milan Jurkulak
sumber