RelativeLayout birleştirme ve dahil etme ile nasıl çalıştırılır?


114

Şimdi çeşitli düzeylerde kullanmaktan dönüştürerek benim düzenleri daha verimli hale getirmek için birkaç gün çalışıyorlar iç içe LinearLayoutsbirine RelativeLayoutve ben cenneti için geçici bir çözüm bulmak mümkün değil birkaç sorun rastlamak ...

Android yeni başlayanlar grubunu ve bu siteyi araştırdım ve sorunu çözmeme yardımcı olacak hiçbir şey bulamadım.

Düzenleri birleştirme ile birleştirebileceğiniz ve etiket ekleyebileceğiniz bloglardan birinde okudum. Yani, sahip olduğum şey, bir RelativeLayoutkök öğesi olan bir ana düzen dosyası . Bunun içinde, her biri kök için bir birleştirme öğesine sahip 5 farklı xml düzen dosyasına başvuran 5 etiket ekledim (tüm birleştirme dosyalarım, içlerindeki kimlikler dışında aynıdır).

Yerleşim kodumun basitleştirilmiş bir sürümünü yayınladıktan sonra açıklayacağım iki problemle karşılaşıyorum:

Örnek Ana Düzen Dosyası:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/translucent_gray" >

    <include 
        android:id="@+id/running_gallery_layout_id"
        layout="@layout/running_gallery_layout" />

    <include 
        android:id="@+id/recent_gallery_layout_id" 
        layout="@layout/recent_gallery_layout"
        android:layout_below="@id/running_gallery_layout_id" />

    <include
        android:id="@+id/service_gallery_layout_id"
        layout="@layout/service_gallery_layout"
        android:layout_below="@id/recent_gallery_layout_id" />

    <include
        android:id="@+id/process_gallery_layout_id"
        layout="@layout/process_gallery_layout"
        android:layout_below="@id/service_gallery_layout_id" />

</RelativeLayout>

Dahil edilen birleştirme dosyası örneği:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView 
        style="@style/TitleText"
        android:id="@+id/service_gallery_title_text_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="left"
        android:text="@string/service_title" />

    <Gallery
        android:id="@+id/service_gallery_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_below="@id/service_gallery_title_text_id" />

    <TextView 
        style="@style/SubTitleText"
        android:id="@+id/service_gallery_current_text_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/service_gallery_title_text_id"
        android:layout_above="@id/service_gallery_id" />
</merge>

İki sorunla karşılaşıyorum:

1) android:layout_*İçerme etiketinde kullanıldığında öznitelikler göz ardı ediliyor gibi görünüyor ve birleştirilmiş tüm düzenler birbirinin üstünde görüntüleniyor. Bu gönderiye göre ( http://developer.android.com/resources/articles/layout-tricks-reuse.html ) " etiketle herhangi bir android:layout_*özellik kullanılabilir <include />"

2) Bu çalışmayı yapamadığım android:layout_belowiçin, TextViewher bir birleştirme düzeni dosyasındaki ilk öğeye bir öznitelik eklemeyi denemeye karar verdim , yani her bir birleştirme dosyası, başka bir birleştirme düzeni dosyasından bir kimliği referans alacaktır ... Çoğunlukla bu gerçekten çalıştı ve düzenim iyi görünüyor. Ancak, android:layout_belowözniteliklerden birinde belirlediğim kimliği bulamadığını söyleyen bir hata alıyorum ... Doğru olduklarından emin olmak için kimlikleri iki ve üç kez kontrol ettim. İşin tuhaf yanı, AutoFillözniteliği ilk etapta özniteliğe koymak için özelliği kullanmış olmamdır .

Herhangi birinin herhangi bir önerisi veya geçici çözümü varsa, bunları denemekten çok mutlu olacağım. Ayrıca, birisi benim için 5 yerine sadece bir birleştirme xml düzen dosyasına sahip olmanın bir yolunu düşünebilirse, bu çok takdir edilecektir. Bunu yapmanın bir yolunu bulamadım çünkü çalışma zamanında birleştirme düzen dosyalarındaki her bir öğeye erişmem gerekiyor ...

Yanıtlar:


214

İnclude etiketiyle ilgili bir sorun var. Kontrol edin: https://issuetracker.google.com/issues/36908001

Düzeltmek için, HER İKİSİNİN üzerine yazdığınızdan layout_widthve layout_heightdahil ettiğinizden emin olun , aksi takdirde her şey göz ardı edilecektir.


15
Gereksiz bir düzen nesnesi oluşturmaktan kaçındığı için bu, kabul edilen çözümden daha iyi bir çözümdür. Ayrıca, Android geliştiricilere göre bunun iyi olduğu da berbat.
mikołak

4
Bu, <include /> 'i başka bir düzende paketlemekten gerçekten daha kolay, daha az kodlanmış ve daha optimize bir çözümdür. Listelerle çalışırsanız ne yapardınız bir düşünün.
teoREtik

2
Bu, kabul edilen cevaptan çok daha iyi çalışıyor. Çok teşekkürler! Ve ... hadi google, bu sorunu şimdiden düzelt, bu BS! :)
Felipe Caldas

2
@JeffAxelrod, LayoutInflater kaynak kodu, maalesef kök öğe bir birleştirme etiketi olduğunda id, visibility ve layout_ * etiketlerinin geçersiz kılınmasının uygulanmadığını gösterir. Eğer xml kökü olarak bir görünümü yok gibi, biz orada fazladan ViewGroup ... olmalı
Rafael Nobre

13
Benim için işe yaramadı. Bende ikisi de var layout_widthve layout_heighton my setted <include>. Ayrıca ayarlama çalıştı layout_widthve layout_heighton my <merge>ancak başarılı olamadı. Neyi kaçırıyorum ?
dum4ll3

33

Aşağıdaki daha çok oylanan yanıta bakın. Benimki ne yazık ki modası geçmiş


Justin'in gündeme getirdiği bir sorunu ele alabilirim : RelativeLayout'un bir dahil etmenin konumlandırmasını yönetememesi (en azından bu basit durumda, 1.6 emülatörde)

CommonsWare eşsiz ebeveyn kapta içerir sarma önerir, ancak içinde aynı ada Görüntüleme adresleme & kapsam yardımcı olmak amacıyla yapar Justin'in içerir

Her birinin benzersiz bir üst kapsayıcıya sahip olması gerekir ve bu kapsayıcıda (ViewGroup), Activity yerine findViewById () öğesini çağırırsınız.

Aslında, RelativeLayout'un beklendiği gibi davranmasını sağlamak için de bunu yapmalısınız :

Bu işe yarar ( altbilgi iyi konumlandırılmış):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent">
    <include android:id="@+id/header" layout="@layout/header"
        android:layout_alignParentTop="true" />
    <WebView android:id="@+id/webView" android:layout_below="@id/header"
        android:background="#77CC0000" android:layout_height="wrap_content"
        android:layout_width="fill_parent" android:focusable="false" />
    <LinearLayout android:layout_alignParentBottom="true"
        android:layout_height="wrap_content" android:layout_width="fill_parent">
        <include android:id="@+id/footer" layout="@layout/footer" />
    </LinearLayout>
</RelativeLayout>

Bu değil ( altbilgi ekranın üst kısmında kayıyor):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent">
    <include android:id="@+id/header" layout="@layout/header"
        android:layout_alignParentTop="true" />
    <WebView android:id="@+id/webView" android:layout_below="@id/header"
        android:background="#77CC0000" android:layout_height="wrap_content"
        android:layout_width="fill_parent" android:focusable="false" />
    <include android:id="@+id/footer" layout="@layout/footer"
        android:layout_alignParentBottom="true" />
</RelativeLayout>

Çıplak altbilgi dahil, çevreleyen LinearLayout olmadan üst öğenin altına hizalanmayacaktır .. Bu beklenen davranış demezdim.

Ek olarak, WebView kendini başlığa kimliğe göre güzelce ekliyor gibi görünüyor , ancak bunun bir yanılsama olduğuna inanıyorum, çünkü başlığın altında dikey olarak akıyor. Ayrıca, altbilginin hemen üstüne bir düğme yerleştirmeye çalıştım, ancak hepsi havada ve yanlıştı

RelativeLayout 1.5 sürümünde daha fazla problem yaşadı ama yine de hoşuma gidiyor :)


2
1 artırdım ve ardından @Macarse tarafından yapılan yorumu görerek geri döndüm, bunu yapmanın doğru yolu bu.
Jayshil Dave

Lütfen bu yanıltıcı yanıtı kaldırın :(
Daniel Smith

8

Dostum, bu eski, ama aramaların başında geliyor, bu yüzden yorum yapacağım.

Bence buradaki püf noktası, <merge>etiketle birleştirilen <include>etiketin o düzeydeki her tür "üst" görünüm grubunu esasen kaldırmasıdır. Öyleyse, tam olarak kimden başka birinden "layout_below" olmasını istiyorsunuz? Hiç kimse. O seviyede manzara yok.

<merge>Etiket çocuk görüşlerini alır ve sağ ebeveyni içine açılan <include>etiketi. Bu nedenle, dahil ettiğiniz düzendeki çocuklardan kendilerini buna göre sabitlemelerini istemelisiniz.


4

Konumlandırmanın RelativeLayout üzerinde çalışması için layout_ * parametrelerini ana düzen dosyasında değil içerme dosyasında ayarlamanız gerekir. Bu şekilde

main_layout.xml

<RelativeLayout
  android:id="@+id/header"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
   ....
</RelativeLayout>

<RelativeLayout 
  android:id="@+id/footer"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true">
    .....
</RelativeLayout>

<include layout="@layout/content_layout" />

content_layout.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
    android:id="@+id/content"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_above="@id/footer"
    android:layout_below="@id/header" >

    ....
</RelativeLayout>
</merge>

Açıkçası biz geliştiricilerin istediği şey bu değil, ancak xml'yi kopyalamaktan kaçınmak için bulduğum tek çözüm bu.


1
Neden olumlu oy yok? Bu benim için çalıştı. Parametreleri, onlara ihtiyaç duymayan bir düzene dahil edilebilecek bir nesneye yapıştırmaya aşık değilim, ancak bir LinLay ise, Görünüşe göre RelLay'in layout_ * göz ardı ediliyor. Bir şey mi kaçırıyorum?
QED

1

Android: layout_ * öznitelikleri include etiketinde kullanıldıklarında göz ardı ediliyor gibi görünüyor ve birleştirilmiş tüm düzenler birbirinin üstünde görüntüleniyor.

Tahminimce, düzen kurallarından, elemanlar android:idüzerinde tanımlanan özniteliklere <include>, sadece "gerçek" gereçler ve kaplar üzerinde olanlara atıfta bulunamazsınız .

Ayrıca, birisi benim için 5 yerine sadece bir birleştirme xml düzen dosyasına sahip olmanın bir yolunu düşünebilirse, bu çok takdir edilecektir.

Basit: hepsini tek bir dosyaya koyun.

Bunu yapmanın bir yolunu bulamadım çünkü çalışma zamanında birleştirme düzeni dosyalarındaki her bir öğeye erişmem gerekiyor

İster bir <include>öğeniz ister 1.000 öğeniz olsun, tüm içerik çalışma zamanında erişilebilir olmalıdır. Bir istisna, yinelenen android:idözniteliklere sahip olmanızdır - findViewById()tıpkı bir ListView satırından pencere öğeleri alırken yapmanız gerektiği gibi, doğru olanı elde etmek için aramalarınızın kapsamını doğru bir şekilde belirlemeniz gerekir .

Eğer kullanır 2+ birleştirme dosyaları içeriği olduklarını göstermek anlamına örnek bir proje oluşturabilirsiniz Eğer değil zamanında erişilebilir, bana bildirin.


1
Hepsini tek bir büyük düzen dosyasına koymak istemiyorum çünkü uzun vadede bunu yönetmek daha zor ... Bu yüzden tek bir birleştirme dosyasıyla bir ana xml'ye sahip olma olasılığını istedim ... çünkü şu anda Kimliklerin farklı olması dışında tam olarak aynı düzene sahip kök olarak birleştirme öğesi olan 5 dosyam var. Bu şekilde yapıyorum, böylece onlara çalışma zamanında erişebiliyorum. Görünüşe göre findViewById () çağrımın kapsamını belirlemek benim yapmak istediğim şey. Aynı düzen dosyasını birden çok kez dahil edebilmek ve yine de çalışma zamanında tüm bileşenlere erişebilmek için bu çağrının kapsamını nasıl alırsınız?
Justin

1
Cevabınız için teşekkürler. Ben buna bakacağım. Bu arada, (ve belki de burada cehaletimi açığa vuruyorum) her bir include etiketini bir üst kapsayıcıya sarmak RelativeLayout kullanma amacını bozmaz mı? RelativeLayout'un tüm yutturmaca, iç içe geçmiş düzenlerden kaçınmaktır ...
Justin

3
Bunu sormamın tek nedeni, yerden tasarruf etmek ve iyi bir tasarım bulmaktı ... Burada düzenin yeniden kullanılabilirliğini okudum: developer.android.com/resources/articles/… ve kulağa hoş geldiğini düşündüm. Uygulamayı denediğimde bazı sorunlarla karşılaştım. Şu anda, içlerindeki kimliklerin dışında esasen çoğaltılmış 5 düzenim var ... bu yüzden düzenin yeniden kullanılabilirliğinin iyi bir aday olacağını düşündüm. Belki burada bir şey özlüyorum, ama görünüşe göre RelativeLayout lanse edilen tek şey değil ...
Justin

1
Vay ... öylesine olduğun için teşekkürler inanılmaz yararlı. Genel olarak yanıtlarınız oldukça yararlıdır, bu nedenle kötü bir gün mü yaşıyorsunuz bilmiyorum, ancak ben sadece RelativeLayout, include etiketi ve birleştirme etiketinin arkasındaki kavramları daha iyi anlamaya çalışıyordum. Okudum ve ulaşmak istediğim düzene uygun bir çözüm bulmaya çalışıyorum.
Justin

1
"Ve gerçek yeniden kullanım için, özel bir View sınıfı kozlarının oluşturulması" Kabul edildi. Basit düzenleri kullanmanın görece kolay bir yolu olsaydı bunu yapmak istemedim ... "Bir tavrını yakaladınız - lütfen insanlar buna tepki gösterdiğinde şaşırmayın. En son yorumum ise yüksek seviyede, puanlar hala geçerli "Bir şeyi atlattım çünkü cevaplarınızda yaptığınızı hissettim. "ListView'de satırlara geçmek daha iyi olabilir." Listview, uygulamamın görünümüyle çalışmayacak. Piyasadaki uygulamam AppSwipe! ne yaptığımı bilmek istiyorsan ...
Justin

1

Deneyin :

<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:showIn="@layout/activity_home">

0

Benim durumumda eklemeye çalıştığım düzen <mergeetiketi ile başlıyor . Bir düzene değiştirdiğimde, <RelativeLayoutişe yaradığını söyle . Aşağıdaki resimdir.

ÇALIŞMA

<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:showIn="@layout/activity_home">

ÇALIŞMIYOR

<merge xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:showIn="@layout/activity_home">

bu, optimum çözüm olmayan başka bir iç içe geçmiş katman oluşturacaktır
Silvia H

0

Aynı sorunu yaşadım ve hatta tanımladım layout_widthve layout_heightişe yaramadı. Sorun, dahil ettiğim düzende etiketler olması ve onları kaldırdıktan sonra her şeyin bir cazibe gibi çalışmasıydı. Sanırım birleştirme bir düzen etiketi değil ve bu nedenle konumlandırma ve boyut parametrelerini alamıyor. Tanımladığınız her şey iç ana mizanpajına aktarıldığından, ayarlar atıldı.

TL: DR: Sadece etiketleri kaldırın, xmlns tanımlarını gerçek bir düzen görüntüleyicisine taşıyın ve iyi olmalısınız.

Önce:

<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <...ui.component.BorderCardView
        android:layout_width="112dp"
        android:layout_height="32dp"
        app:cardCornerRadius="4dp"
        app:cardUseCompatPadding="true">

        <ImageView
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:src="@drawable/ic_logout"
            android:tint="@color/divider" />

    </...ui.component.BorderCardView>
</merge>

Çalışma:

<...ui.component.BorderCardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="112dp"
    android:layout_height="32dp"
    app:cardCornerRadius="4dp"
    app:cardUseCompatPadding="true">

    <ImageView
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:src="@drawable/ic_logout"
        android:tint="@color/divider" />

</...ui.component.BorderCardView>
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.