Wanneer u complexe applicaties bouwt, wilt u vaak dezelfde groep views op verschillende plaatsen van de applicatie opnieuw gebruiken. Een manier om dit probleem op te lossen is door een weergave te maken die de logica en lay-out van een groep weergaven bevat, zodat u deze opnieuw kunt gebruiken zonder code op verschillende plaatsen in het project te dupliceren. In deze zelfstudie leert u hoe u samengestelde views kunt gebruiken om aangepaste weergaven te maken die eenvoudig herbruikbaar zijn.
Op Android wordt een weergave die is samengesteld uit een groep weergaven een samengestelde weergave of een samengestelde component. In deze zelfstudie bouwt u een besturingselement om een waarde te selecteren in een lijst die van links naar rechts schuift. We noemen het samengestelde een zijspinner omdat de standaardweergave van de Android SDK om een waarde uit een lijst te kiezen, een spinner wordt genoemd. De volgende schermafbeelding illustreert wat we in deze zelfstudie gaan maken.
Om aan de slag te gaan, moet u een nieuw Android-project maken met Android 4.0 als het minimaal vereiste SDK-niveau. Dit project mag alleen een blanco activiteit bevatten met de naam Hoofdactiviteit. De Activiteit
doet niets meer dan het initialiseren van de lay-out zoals u kunt zien in het volgende codefragment.
public class MainActivity breidt activiteit uit @Override beschermde ongeldig onCreate (bundel savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main);
De lay-out voor Hoofdactiviteit
bevindt zich in de /res/layout/activity_main.xml bestand en het mag alleen een lege bevatten Relatieve layout
waarin de samengestelde weergave later wordt weergegeven.
Als u een samengestelde weergave wilt maken, moet u een nieuwe klasse maken die de weergaven in de samengestelde weergave beheert. Voor de side-spinner heb je er twee nodig Knop
weergaven voor de pijlen en a Tekstweergave
weergave om de geselecteerde waarde weer te geven.
Maak om te beginnen het /res/layout/sidespinner_view.xml lay-outbestand dat we zullen gebruiken voor de side spinner-klasse, en zorg ervoor dat de drie views in een
label.
Vervolgens moeten we het maken SideSpinner
klasse die deze lay-out opblaast en stelt de pijlen in als achtergrondafbeeldingen voor de knoppen. Op dit moment doet de samengestelde weergave niets, omdat er nog niets te zien is.
openbare klasse SideSpinner verlengt LinearLayout private Button mPreviousButton; private Button mNextButton; public SideSpinner (Context-context) super (context); initializeViews (context); public SideSpinner (Context-context, AttributeSet-attrs) super (context, attrs); initializeViews (context); public SideSpinner (Context-context, AttributeSet attrs, int defStyle) super (context, attrs, defStyle); initializeViews (context); / ** * Blaast de weergaven op in de lay-out. * * @param context * de huidige context voor de weergave. * / private void initializeViews (Context-context) LayoutInflater inflater = (LayoutInflater) context .getSystemService (Context.LAYOUT_INFLATER_SERVICE); inflater.inflate (R.layout.sidespinner_view, this); @Override beschermde leegte onFinishInflate () super.onFinishInflate (); // Stelt de afbeeldingen in voor de vorige en volgende knoppen. Gebruikt // ingebouwde afbeeldingen, zodat u geen afbeeldingen hoeft toe te voegen, maar // in een echte toepassing moeten uw afbeeldingen zich in het // -toepassingspakket bevinden, zodat ze altijd beschikbaar zijn. mPreviousButton = (Button) this .findViewById (R.id.sidespinner_view_previous); mPreviousButton .setBackgroundResource (android.R.drawable.ic_media_previous); mNextButton = (Button) this .findViewById (R.id.sidespinner_view_next); mNextButton .setBackgroundResource (android.R.drawable.ic_media_next);
Je zult merken dat de samengestelde weergave de LinearLayout
groep bekijken. Dit betekent dat elke lay-out met behulp van de samengestelde weergave toegang heeft tot de kenmerken van de lineaire lay-out. Als gevolg hiervan is de lay-out voor de samengestelde weergave een beetje anders dan gebruikelijk, de hoofdtag is een
tag in plaats van de tag voor een kijkgroep zoals
of
.
Wanneer u de samengestelde weergave toevoegt aan de lay-out van Hoofdactiviteit
, de tag voor de samengestelde weergave fungeert als een
label. Een samengestelde weergaverlasse kan afgeleid zijn van elke klasse afgeleid van ViewGroup
, maar in dit geval is de lineaire lay-out het meest geschikt, omdat de weergaven horizontaal zijn uitgezet.
Op dit punt wordt het project gecompileerd, maar niets is zichtbaar omdat de samengestelde weergave niet in de lay-out staat Hoofdactiviteit
. De zijwaartse spinnerweergave moet als een andere weergave aan de lay-out van de activiteit worden toegevoegd. De naam van de tag is de volledige naam van de SideSpinner
klasse, inclusief de naamruimte.
Om de side spinner aan toe te voegen Hoofdactiviteit
, voeg het volgende toe aan de relatieve lay-out in de /res/layout/activity_main.xml het dossier.
De attributen beschikbaar in de
tag zijn attributen van de lineaire lay-out sinds de SideSpinner
klasse die we hebben gemaakt, breidt het LinearLayout
klasse. Als u het project start, moet de side-spinner zichtbaar zijn, maar deze bevat nog geen waarden.
Er ontbreken nog een paar dingen als we de side-spinner daadwerkelijk willen gebruiken. We moeten nieuwe waarden aan de spinner kunnen toevoegen, een waarde kunnen selecteren en de geselecteerde waarde kunnen ophalen.
De eenvoudigste manier om nieuw gedrag aan een samengestelde weergave toe te voegen, is nieuwe openbare methoden aan de SideSpinner
klasse. Deze methoden kunnen door iedereen worden gebruikt Activiteit
die een verwijzing naar de weergave heeft.
private CharSequence [] mSpinnerValues = null; private int mSelectedIndex = -1; / ** * Hiermee stelt u de lijst met waarden in de draaifunctie in door standaard de eerste waarde * te selecteren. * * @param values * de waarden die in de spinner worden ingesteld. * / public void setValues (CharSequence [] waarden) mSpinnerValues = waarden; // Selecteer standaard het eerste item van de tekenreeksarray omdat // de lijst met waarden is gewijzigd. setSelectedIndex (0); / ** * Stelt de geselecteerde index van de spinner in. * * @param index * de index van de waarde die u wilt selecteren. * / public void setSelectedIndex (int index) // Als er geen waarden zijn ingesteld voor de spinner, doet u niets. if (mSpinnerValues == null || mSpinnerValues.length == 0) terug; // Als niets aan de indexwaarde is veranderd, doet u niets. if (index < 0 || index >= mSpinnerValues.length) rendement; // Stel de huidige index in en geef de waarde weer. mSelectedIndex = index; TextView currentValue; currentValue = (TextView) this .findViewById (R.id.sidespinner_view_current_value); currentValue.setText (mSpinnerValues [index]); // Als de eerste waarde wordt weergegeven, verbergt u de vorige knop. if (mSelectedIndex == 0) mPreviousButton.setVisibility (INVISIBLE); else mPreviousButton.setVisibility (ZICHTBAAR); // Als de laatste waarde wordt weergegeven, verbergt u de volgende knop. if (mSelectedIndex == mSpinnerValues.length - 1) mNextButton.setVisibility (INVISIBLE); else mNextButton.setVisibility (ZICHTBAAR); / ** * Hiermee wordt de geselecteerde waarde van de spinner opgehaald, of null als er nog geen geldige * geselecteerde index is ingesteld. * * @om de geselecteerde waarde van de spinner terug te draaien. * / openbare CharSequence getSelectedValue () // Als er geen waarden zijn ingesteld voor de spinner, retourneert u een lege reeks. if (mSpinnerValues == null || mSpinnerValues.length == 0) return ""; // Als de huidige index ongeldig is, retourneert u een lege tekenreeks. if (mSelectedIndex < 0 || mSelectedIndex >= mSpinnerValues.length) return ""; return mSpinnerValues [mSelectedIndex]; / ** * Hiermee wordt de geselecteerde index van de spinner opgehaald. * * @om de geselecteerde index van de spinner terug te draaien. * / public int getSelectedIndex () return mSelectedIndex;
De onFinishInflate
methode van de samengestelde weergave wordt aangeroepen wanneer alle weergaven in de lay-out opgeblazen en klaar voor gebruik zijn. Dit is de plaats om uw code toe te voegen als u in de samengestelde weergave weergaven moet wijzigen.
Met de methoden die u zojuist hebt toegevoegd aan de SideSpinner
klasse, gedrag voor de knoppen die de vorige en volgende waarde selecteren, kan nu worden toegevoegd. Vervang de bestaande code in de onFinishInflate
methode met de volgende:
@Override protected void onFinishInflate () // Wanneer de besturingselementen in de lay-out vol raken, stelt u // de terugbelfuncties voor de zijpijlen in. super.onFinishInflate (); // Als u op de vorige knop drukt, selecteert u de vorige waarde // in de lijst. mPreviousButton = (Button) this .findViewById (R.id.sidespinner_view_previous); mPreviousButton .setBackgroundResource (android.R.drawable.ic_media_previous); mPreviousButton.setOnClickListener (nieuwe OnClickListener () public void onClick (View view) if (mSelectedIndex> 0) int newSelectedIndex = mSelectedIndex - 1; setSelectedIndex (newSelectedIndex);); // Als de volgende knop wordt ingedrukt, selecteert u het volgende item in de // -lijst. mNextButton = (Button) this .findViewById (R.id.sidespinner_view_next); mNextButton .setBackgroundResource (android.R.drawable.ic_media_next); mNextButton.setOnClickListener (nieuwe OnClickListener () public void onClick (View view) if (mSpinnerValues! = null && GeselecteerdIndex < mSpinnerValues.length - 1) int newSelectedIndex = mSelectedIndex + 1; setSelectedIndex(newSelectedIndex); ); // Select the first value by default. setSelectedIndex(0);
Met de nieuw gecreëerde setValues
en setSelectedIndex
methoden, kunnen we nu de side-spinner initialiseren vanuit onze code. Zoals bij elke andere weergave, moet u de zijwaartse spinnerweergave in de lay-out vinden met de findViewById
methode. Vervolgens kunnen we elke openbare methode in de weergave van het geretourneerde object aanroepen, inclusief degene die we zojuist hebben gemaakt.
Het volgende codefragment laat zien hoe u de update kunt bijwerken onCreate
methode van de Hoofdactiviteit
klasse om een lijst met waarden weer te geven in de zijwaartse draaifunctie, met behulp van de setValues
methode. We kunnen ook standaard de tweede waarde in de lijst selecteren door de setSelectedIndex
methode.
public class MainActivity breidt activiteit uit @Override beschermde ongeldig onCreate (bundel savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); // Initialiseert de side-spinner uit de code. SideSpinner fruitsSpinner; fruitsSpinner = (SideSpinner) dit .findViewById (R.id.sidespinner_fruits); CharSequence fruitLijst [] = "Apple", "Orange", "Pear", "Grapes"; fruitsSpinner.setValues (fruitList); fruitsSpinner.setSelectedIndex (1);
Als u de toepassing start, zou de zijwielspinner moeten werken zoals verwacht. De lijst met waarden wordt weergegeven en de waarde Oranje is standaard geselecteerd.
De beschikbare weergaven in de Android SDK kunnen worden gewijzigd via code, maar sommige kenmerken kunnen ook rechtstreeks in de bijbehorende lay-out worden ingesteld. Laten we een kenmerk toevoegen aan de zijwaartse draaifunctie waarmee de waarden worden ingesteld die de zijwaartse rotatie-eenheid moet weergeven.
Als u een aangepast kenmerk voor de samengestelde weergave wilt maken, moeten we eerst het kenmerk in de /res/values/attr.xml het dossier. Elk attribuut van de samengestelde weergave moet worden gegroepeerd in een styleable met een
label. Voor de zijspinner wordt de naam van de klasse gebruikt zoals hieronder wordt getoond.
In de
tag, de naam
attribuut bevat de identifier die wordt gebruikt om te verwijzen naar het nieuwe attribuut in de lay-out en de formaat
attribuut bevat het type van het nieuwe attribuut.
Voor de lijst met waarden, de referentie
type wordt gebruikt omdat het kenmerk verwijst naar een lijst met strings die als een resource is gedefinieerd. De waardetypes die normaal worden gebruikt in lay-outs kunnen worden gebruikt voor uw aangepaste kenmerken, inclusief boolean
, kleur
, dimensie
, enum
, geheel getal
, vlotter
en draad
.
Hier leest u hoe u de resource definieert voor een lijst met strings die de waarden
attribuut van de side-spinner zal verwijzen naar. Het moet worden toegevoegd aan de /res/values/strings.xml bestand zoals hieronder getoond.
- Komkommer
- Aardappel
- Tomaat
- Ui
- Squash
Om het nieuwe te testen waarden
attribuut, maak een side spinner view in de Hoofdactiviteit
lay-out onder de bestaande side spinner. Het kenmerk moet worden voorafgegaan door een naamruimte die is toegevoegd aan de Relatieve layout
, zoals xmlns: sidespinner = "http://schemas.android.com/apk/res-auto"
. Dit is de uiteindelijke lay-out /res/layout/activity_main.xml zou eruit moeten zien.
eindelijk, de SideSpinner
klas moet worden aangepast om de. te lezen waarden
attribuut. De waarde van elk attribuut van de weergave is beschikbaar in de AttributeSet
object dat wordt doorgegeven als een parameter van de constructor van de view.
Om de waarde van uw gebruik te krijgen waarden
attribuut, we noemen het eerst het obtainStyledAttributes
methode van de AttributeSet
object met de naam van de styleable die het attribuut bevat. Dit retourneert de lijst met attributen voor die die kan worden gestyleerd als een TypedArray
voorwerp.
Vervolgens noemen we de gettermethode van de TypedArray
object met het juiste type voor het gewenste kenmerk, waarbij de ID van het kenmerk als een parameter wordt doorgegeven. Het volgende codeblok laat zien hoe de constructor van de side-spinner moet worden gewijzigd om de lijst met waarden te krijgen en deze in de zij-centrifuge in te stellen.
public SideSpinner (Context-context) super (context); initializeViews (context); public SideSpinner (Context-context, AttributeSet-attrs) super (context, attrs); TypedArray getyptArray; typedArray = context .obtainStyledAttributes (attrs, R.styleable.SideSpinner); mSpinnerValues = typedArray .getTextArray (R.styleable.SideSpinner_values); typedArray.recycle (); initializeViews (context); public SideSpinner (Context-context, AttributeSet attrs, int defStyle) super (context, attrs, defStyle); TypedArray getyptArray; typedArray = context .obtainStyledAttributes (attrs, R.styleable.SideSpinner); mSpinnerValues = typedArray .getTextArray (R.styleable.SideSpinner_values); typedArray.recycle (); initializeViews (context);
Als u de toepassing start, ziet u twee zijspinners die onafhankelijk van elkaar werken.
De laatste stap die we moeten voltooien, is het opslaan en herstellen van de status van de samengestelde weergave. Wanneer een activiteit wordt vernietigd en opnieuw wordt gemaakt, bijvoorbeeld wanneer het apparaat wordt geroteerd, worden de waarden van native views met een unieke ID automatisch opgeslagen en hersteld. Dit is momenteel niet het geval voor de side-spinner.
De status van de weergaven wordt niet opgeslagen. De identificatiegegevens van de weergaven in de SideSpinner
klasse zijn niet uniek omdat het vaak kan worden hergebruikt. Dit betekent dat we verantwoordelijk zijn voor het opslaan en herstellen van de waarden van de views in de samengestelde weergave. We doen dit door de onSaveInstanceState
, onRestoreInstanceState
, en dispatchSaveInstanceState
methoden. Het volgende codeblok laat zien hoe dit voor de zijwielspinner moet worden gedaan.
/ ** * Identifier voor de status om de geselecteerde index van * de zijcentrifuge op te slaan. * / private static String STATE_SELECTED_INDEX = "SelectedIndex"; / ** * Identifier voor de staat van de superklasse. * / private static String STATE_SUPER_CLASS = "SuperClass"; @Override beveiligd Pakket opSaveInstanceState () Bundelbundel = nieuwe bundel (); bundle.putParcelable (STATE_SUPER_CLASS, super.onSaveInstanceState ()); bundle.putInt (STATE_SELECTED_INDEX, mSelectedIndex); bundel retourneren; @Override beschermde ongeldig opRestoreInstanceState (Parcelable state) if (state instanceof Bundle) Bundelbundel = (bundel) staat; super.onRestoreInstanceState (bundle .getParcelable (STATE_SUPER_CLASS)); setSelectedIndex (bundle.getInt (STATE_SELECTED_INDEX)); else super.onRestoreInstanceState (state); @Override beschermde ongeldige verzendingSaveInstanceState (SparseArraycontainer) // Zorgt ervoor dat de status van de onderliggende weergaven in de side // spinner niet wordt opgeslagen omdat we de status in de // onSaveInstanceState verwerken. super.dispatchFreezeSelfOnly (container); @Override beschermde ongeldige verzendingRestoreInstanceState (SparseArray container) // Zorgt ervoor dat de status van de onderliggende weergaven in de side // spinner niet wordt hersteld, aangezien we de status in de // onSaveInstanceState verwerken. super.dispatchThawSelfOnly (container);
De side-spinner is nu voltooid. Beide zijspinners werken zoals verwacht en hun waarden worden hersteld als de activiteit wordt vernietigd en opnieuw wordt gemaakt. Je kunt nu toepassen wat je hebt geleerd om een groep views in een Android-applicatie opnieuw te gebruiken door samengestelde views te gebruiken.