Trucuri de machetare: Fuzionarea machetelor
Articolele v-au arătat cum să folosiți tag-ul <include />
în machetele XML, pentru a reutiliza și partaja codul de machetare. Acest articol explică tag-ul <merge />
și modul în care acesta completează tag-ul <include />
.
Tag-ul <merge />
a fost creat cu scopul de aoptimiza machetele Android prin reducerea numărului de niveluri în arborii de vizualizare. Estemai ușor de înțeles problema pe care o rezolvă această etichetă analizând un exemplu. Următorul aspect XML declară un aspect care afișează o imagine cu titlul acesteia deasupra. Structura este destul de simplă; un FrameLayout
este folosit pentru a suprapune un TextView
peste un ImageView
:
<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>
Acest layout se redă frumos și nu pare să aibă nimic în neregulă:
Lucrurile devin mai interesante atunci când inspectați rezultatul cu HierarchyViewer. Dacă vă uitați cu atenție la arborele rezultat, veți observa că FrameLayout
definit în fișierul nostru XML (evidențiat în albastru mai jos) este singurul copil al unui alt FrameLayout
:
Din moment ce FrameLayout
al nostru are aceeași dimensiune ca și părintele său, în virtutea folosirii constrângerilor fill_parent
, și nu definește nici un fundal, nici o umplutură suplimentară sau o gravitație, el este total inutil. Nu am făcut decât să facem mai complexă interfața utilizator fără niciun motiv întemeiat. Dar cum am putea să scăpăm de acest FrameLayout
? La urma urmei, documentele XML au nevoie de o etichetă rădăcină, iar etichetele din machetele XML reprezintă întotdeauna instanțe de vizualizare.
Acesta este locul unde eticheta <merge />
este utilă. Atunci cândLayoutInflater
întâlnește această etichetă, o sare și adaugă copiii <merge />
la <merge />
părintele <merge />
. Sunteți confuz? Să rescriem layout-ul nostru XML anterior înlocuindFrameLayout
cu <merge />
:
<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>
Cu această nouă versiune, atât TextView
cât și ImageView
vor fi adăugate direct la nivelul superiorFrameLayout
. Rezultatul va fi același din punct de vedere vizual, dar ierarhia vizualizărilor este mai simplă:
Evident, utilizarea <merge />
funcționează în acest caz deoarece părintele vizualizării conținutului unei activități este întotdeauna un FrameLayout
. Nu ați putea aplica acest truc dacă layout-ul dvs. ar folosi un LinearLayout
ca etichetă rădăcină, de exemplu. Totuși, <merge />
poate fi util în alte situații. De exemplu, funcționează perfect atunci când este combinat cu tagul<include />
. De asemenea, puteți utiliza <merge/>
atunci când creați o vizualizare compozită personalizată. Să vedem cum putem folosi acest tag pentru a crea o nouă vizualizare numită OkCancelBar
care afișează pur și simplu două butoane cu etichete personalizabile. Puteți descărca, de asemenea, codul sursă complet al acestui exemplu. Iată XML-ul folosit pentru a afișa această vizualizare personalizată deasupra unei imagini:
<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>
Acest nou aspect produce următorul rezultat pe un dispozitiv:
Codul sursă al lui OkCancelBar
este foarte simplu deoarece cele două butoane sunt definite într-un fișier XML extern, încărcat cu ajutorul unuiLayoutInflate
. După cum puteți vedea în următorul fragment, XMLlayout-ul este umflat cuOkCancelBar
ca părinte:
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(); }}
Cele două butoane sunt definite în următorul layout XML. După cum puteți vedea, folosim tagul <merge />
pentru a adăuga cele două butoane direct la OkCancelBar
. Fiecare buton este inclus din același fișier XMLlayout extern pentru a fi mai ușor de întreținut; pur și simplu le suprascriem id-ul:
<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>
Am creat o vizualizare personalizată flexibilă și ușor de întreținut care generează o ierarhie de vizualizare eficientă:
Eticheta <merge />
este extrem de utilă și poate face minuniîn codul dumneavoastră. Cu toate acestea, suferă de câteva limitări:
-
<merge />
poate fi folosită doar ca etichetă rădăcină a unui layout XML - Când umflați un layout care începe cu un
<merge />
, trebuie să specificați un părinteViewGroup
și trebuie să setațiattachToRoot
latrue
(consultați documentația pentru metodainflate(int, android.view.ViewGroup, boolean)
)
.
Leave a Reply