Layout Tricks: Merging Layouts
Artikkeleissa näytettiin, miten voit käyttää <include />
-tagia XML-layouteissa, uudelleenkäyttää ja jakaa layout-koodia. Tässä artikkelissa selitetään <merge />
-tunniste ja miten se täydentää <include />
-tunnistetta.
<merge />
-tunniste luotiin optimoimaan Android-asetteluja vähentämällä näkymäpuiden tasojen määrää. On helpompi ymmärtää ongelma, jonka tämä tagi ratkaisee, tarkastelemalla esimerkkiä. Seuraava XML-asettelu ilmoittaa asettelun, joka näyttää kuvan ja sen otsikon sen päällä. Rakenne on melko yksinkertainen; FrameLayout
:aa käytetään pinoamaan TextView
:aa ImageView
:n päälle:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="center" android:src="@drawable/golden_gate" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="20dip" android:layout_gravity="center_horizontal|bottom" android:padding="12dip" android:background="#AA000000" android:textColor="#ffffffff" android:text="Golden Gate" /></FrameLayout>
Tämä asettelu renderöityy hienosti, eikä siinä näytä olevan mitään vikaa:
Tilanteet muuttuvat mielenkiintoisemmiksi, kun lopputulosta tarkastellaan HierarchyViewerilla. Teimme käyttöliittymästä vain monimutkaisemman ilman hyvää syytä. Mutta miten voisimme päästä eroon tästä FrameLayout
:stä? Loppujen lopuksi XML-dokumentit vaativat juuritunnisteen ja XML-asettelun tunnisteet edustavat aina näkymäinstansseja.
Tässä kohtaa <merge />
-tunniste on kätevä. Kun LayoutInflater
kohtaa tämän tagin, se ohittaa sen ja lisää <merge />
-lapset <merge />
-vanhempaan. Hämmentynyt? Kirjoitetaan edellinen XML-asettelumme uudelleen korvaamalla FrameLayout
<merge />
:llä:
<merge xmlns:android="http://schemas.android.com/apk/res/android"> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="center" android:src="@drawable/golden_gate" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="20dip" android:layout_gravity="center_horizontal|bottom" android:padding="12dip" android:background="#AA000000" android:textColor="#ffffffff" android:text="Golden Gate" /></merge>
Tässä uudessa versiossa sekä TextView
että ImageView
lisätään suoraan ylimmän tasonFrameLayout
:een. Lopputulos on visuaalisesti sama, mutta näkymähierarkia on yksinkertaisempi:
Näköjään <merge />
käyttäminen toimii tässä tapauksessa, koska aktiviteetin sisältönäkymän vanhempana on aina FrameLayout
. Et voisi soveltaa tätä temppua, jos asettelusi käyttäisi esimerkiksi LinearLayout
tunnistetta juuritunnisteena. <merge />
voi kuitenkin olla hyödyllinen muissa tilanteissa. Se toimii esimerkiksi täydellisesti yhdistettynä <include />
-tagiin. Voit myös käyttää <merge/>
-tagia, kun luot mukautetun yhdistetyn näkymän. Katsotaanpa, miten voimme käyttää tätä tagia luodaksemme uuden näkymän nimeltä OkCancelBar
, joka yksinkertaisesti näyttää kaksi painiketta muokattavilla merkinnöillä. Voit myös ladata tämän esimerkin täydellisen lähdekoodin. Tässä on XML, jota käytetään tämän mukautetun näkymän näyttämiseen kuvan päällä:
<merge xmlns:android="http://schemas.android.com/apk/res/android" xmlns:okCancelBar="http://schemas.android.com/apk/res/com.example.android.merge"> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="center" android:src="@drawable/golden_gate" /> <com.example.android.merge.OkCancelBar android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:paddingTop="8dip" android:gravity="center_horizontal" android:background="#AA000000" okCancelBar:okLabel="Save" okCancelBar:cancelLabel="Don't save" /></merge>
Tämä uusi asettelu tuottaa laitteessa seuraavan tuloksen:
OkCancelBar
:n lähdekoodi on hyvin yksinkertainen, koska kaksipainiketta on määritelty ulkoisessa XML-tiedostossa, joka on ladattu LayoutInflate
:n avulla. Kuten seuraavasta pätkästä näkyy, XMLlayout R.layout.okcancelbar
on paisutettu siten, että OkCancelBar
on sen vanhempi:
public class OkCancelBar extends LinearLayout { public OkCancelBar(Context context, AttributeSet attrs) { super(context, attrs); setOrientation(HORIZONTAL); setGravity(Gravity.CENTER); setWeightSum(1.0f); LayoutInflater.from(context).inflate(R.layout.okcancelbar, this, true); TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.OkCancelBar, 0, 0); String text = array.getString(R.styleable.OkCancelBar_okLabel); if (text == null) text = "Ok"; ((Button) findViewById(R.id.okcancelbar_ok)).setText(text); text = array.getString(R.styleable.OkCancelBar_cancelLabel); if (text == null) text = "Cancel"; ((Button) findViewById(R.id.okcancelbar_cancel)).setText(text); array.recycle(); }}
Kaksi painiketta on määritelty seuraavassa XML-asettelussa. Kuten näet, käytämme <merge />
-tunnistetta lisätäksemme kaksi painiketta suoraanOkCancelBar
:een. Kukin painike sisällytetään samasta ulkoisesta XMLlayout-tiedostosta, jotta niitä olisi helpompi ylläpitää; me yksinkertaisesti ohitamme niiden id:
<merge xmlns:android="http://schemas.android.com/apk/res/android"> <include layout="@layout/okcancelbar_button" android:id="@+id/okcancelbar_ok" /> <include layout="@layout/okcancelbar_button" android:id="@+id/okcancelbar_cancel" /></merge>
Olemme luoneet joustavan ja helposti ylläpidettävän mukautetun näkymän, joka tuottaa tehokkaan näkymähierarkian:
Tagi <merge />
on erittäin hyödyllinen, ja se voi saada aikaan ihmeitä koodissasi. Sillä on kuitenkin pari rajoitusta:
-
<merge />
voidaan käyttää vain XML-asettelun juuritagina - Kun paisutat asettelua, joka alkaa
<merge />
:llä, sinun on määriteltävä vanhempiViewGroup
ja asetettavaattachToRoot
true
:ksitrue
:ksi (ks. dokumentaatioinflate(int, android.view.ViewGroup, boolean)
-metodista)
Leave a Reply