Android'de başka bir görünümün üzerine bir görünüm yerleştirme / Çakıştırma (z-endeksi)


230

Görüntü ve metin görünümü, doğrusal bir düzen içinde birbiri ardına oluşan doğrusal bir düzen var.

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

Bazı kurallar eksik olabilir, bu, düzenin nasıl göründüğü hakkında bir fikir vermek içindir. Başka bir küçük metin görünümü 50dip uzunluğunda ve genişliğinde, görüntü üzerinde yerleştirilmiş, "üzerinde" ile ben daha fazla z-endeksi daha fazla görüntü-görüntüleme demek, ben, orta ve yukarıda (üst üste) görüntü yerleştirmek istiyorum.

Değişen z-endeksiyle (tercihen doğrusal düzende) bir görünümü diğerinin üzerine nasıl yerleştirebileceğimizi bilmek isterim?

Yanıtlar:


295

Bunun için bir LinearLayout kullanamazsınız, ancak a kullanabilirsiniz FrameLayout. A'da FrameLayout, z-endeksi, öğelerin eklendiği sıra ile tanımlanır, örneğin:

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

Bu durumda, TextView, ImageView'in üstüne, görüntünün alt merkezi boyunca çizilir.


Evet, dokümantasyondan sonra çerçeve düzenini kullanarak yaptım. Teşekkür ederim.
sat

11
Bunun için FrameLayout yerine RelativeLayout kullanmanın bir avantajı var mı?
Ixx

12
FrameLayout, gruptaki diğer görünümlerle ilgili değildir, bunları yalnızca üst öğeye göre katmanlar. RelativeLayout, diğer öğelere göre konumlandırma için daha fazladır.
Kevin Coppock

3
Merhaba kcoppock cep telefonum (hdpi) çerçeve düzeninde z sırasına saygı duymuyor, ancak başka bir (xhdpi) var ve bu sıraya saygı duyuyorum, neden bunu biliyor musunuz? Şimdiden teşekkürler! : D
Merlí Escarpenter Pérez

1
API 21 / KitKat'tan itibaren artık setZ ve translationZ kullanabilirsiniz; FrameLayout kesmek artık gerekli değildir (sonunda!). Modern 5.0+ geliştirme için tercih edilen cevap bu olmalıdır: stackoverflow.com/a/29703860/358578
pbarranis

183

3
bunu xml dosyalarında da kullanabilir miyiz?
Reklamlar

2
Çeviri animasyonu sırasında itz zindex değiştirmek için benim görüş getirmek için böyle bir şey arıyordu.
DeltaCap019

Çeviri animasyonu için bir çözüm bulabilir misiniz?
nAkhmedov

9
bringChildToFront () sadece üst içerisindeki Görünümün dizinini değiştirir
Zar E Ahmer

4
Bu tüm düzen sırasını vidalar
Jemshit Iskenderov

66

RelativeLayout da aynı şekilde çalışır, göreceli mizanpajdaki son görüntü kazanır.


14
Yükseklik kullanmadığınız sürece, bu durumda en büyük değere de ihtiyacınız vardır.
Sami Kuhmonen

5
Bu soru, yükseklik bulunmadan önce sorulmuş ve cevaplanmıştır. Uygulamanızın Lollipop'tan minSdk'den daha az olması durumunda yükseklik kullanımı sorunu çözmez (lolipop öncesi telefonlarda, yalnızca yükselmeye güvenirseniz düzen yanlış görünecektir) - yine de düzenin sırasına dikkat etmeniz gerekir. Yine de haklısınız, eğer alt bileşende yükseklik kullanırsanız - kesinlikle en azından aynı veya daha üstte olmanız gerekir.
jt-gilkeson

27

Çekiliş sırasını değiştirme

Bir alternatif, görünümlerin ebeveyn tarafından çizilme sırasını değiştirmektir. SetChildrenDrawingOrderEnabled (true) öğesini çağırarak ve getChildDrawingOrder (int childCount, int i) üzerine yazarak bu özelliği ViewGroup'tan etkinleştirebilirsiniz .

Misal:

/**
 * 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];
    }
}

Çıktı:

OrderLayout#setDrawOrder(int)0-1-2 ile arama yapmak şu sonuçları verir:

resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin


Etkinliğin onCreate () öğesinde setDrawOrder (i) öğesini çağırıyor musunuz? Eğer benim xml 6 widget varsa, ben DRAW_ORDERS her satır 6 sayı dizisi (0-5) ile başlatmak gerekir?
John Ward

Yukarıda gösterilen düzen yalnızca örnek amaçlı olsa da, getChildDrawingOrder () içinde kendi davranışınızı tanımlayabilirsiniz.
17'de Tobrun


20

view.setZ(float)API düzeyi 21'den başlayarak kullanabilirsiniz . Burada daha fazla bilgi bulabilirsiniz.


3
Şimdi bu API 21 / KitKat / 5.0 veya üstü için tercih edilen cevap olmalıdır. Eski frameLayout kesmek neyse ki artık gerekli değildir. Şahsen setZ ve translationZ arasındaki farkı anlamıyorum, ancak ikincisi bir özelliktir ve benim için güzel çalıştı. Teşekkürler!
pbarranis

Önceki API'ler için ViewCompat # setZ () öğesini de kullanabilirsiniz.
Ali Yücel Akgül

@AliYucelAkgul Buradaki dokümanlara bakarsanız görebilirsiniz Compatibility: API < 21: No-op . Bu yüzden işe yaramayacağını düşünüyorum
Vadim Kotov

@VadimKotov, benim app denedim ve sadece çalışıyor.
Ali Yücel Akgül

@AliYucelAkgul iyi, bu garip. Belgelerde bir hata olabilir mi? API <21 için çalıştığından% 100 emin misiniz? Önceki API'ler için görünüm sırasını değiştirebilir, ancak yükseklik, vb gibi süslü şeyler değişebilir bir fikrim var.
Vadim Kotov

14

Aynı sorunu android:elevation="1dp"başka bir görünüm üzerinde istediğiniz görünüme ekleyerek çözdüm. Ancak 5.0'ın altında görüntülenemiyor ve küçük bir gölgesi olacak, kabul ederseniz sorun yok.

Yani, @kcoppock en doğru çözüm dedi.


7

Bir RelativeLayout'ta bunu deneyin:

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

Benim için çalışıyor.


2
Biraz daha iyi açıklamalısın. Örneğin bu kodu nereye koyardınız?
DevB2F

OnCreate () yöntemine koydum. Eklenen her görüntünün, daha önce eklenmiş olanlara göre bir z tercih endeksi vardır. Demek istediğim, z indeksi ile bir öncekinin bir sonrakinin konumunu değiştirebilirim.
Rizzo

5

LinearLayout'u kullanmanın bir yolu var. Önceki öğenizin marginTop değerini karşılık gelen negatif değere ayarlayın ve üstte istediğiniz öğenin, XML'nizde aşağıda istediğiniz öğeden sonra olduğundan emin olun.

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

4

AFAIK bunu doğrusal düzenlerle yapamazsınız, bir RelativeLayout'a gitmeniz gerekir .


RelativeLayout, frameLayout'u genişletmez, çalışacağından emin misiniz?
ekatz

Olacak. FrameLayout veya RelativeLayout öğelerinden herhangi birini kullanabilirsiniz. Her birinin çocuk görüşleri koymanın farklı yolları vardır. Bu düzenler hakkında daha fazla bilgi için dokümanlara bakın.
Vincent Mimoun-Prat

bu gitmek için bir yol
Albert James Teddy

0

Görünümü programlı olarak ekliyorsanız, yourLayout.addView(view, 1);

nerede 1 is the index.


0

Gerektiğinde yalnızca bir görünümün öne çıkmasını istiyorsanız bunu kullanıyorum:

containerView.bringChildToFront(topView);

containerView , sıralanacak görünümlerin kabıdır , topView , en çok kapta en üstte olmak istediğim görünümdür.

düzenlemek için birden fazla görünüm için setChildrenDrawingOrderEnabled (true) kullanmak ve yukarıda belirtildiği gibi getChildDrawingOrder (int childCount, int i) geçersiz kılmak üzeredir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.