Opprette sammensatte visninger på Android

Når du bygger komplekse applikasjoner, vil du ofte bruke den samme gruppen av visninger på forskjellige steder i applikasjonen. En måte å løse dette problemet på er å skape en visning som inkapsler logikken og utformingen av en gruppe visninger, slik at du kan gjenbruke dem uten å duplisere koden på ulike steder i prosjektet. I denne opplæringen lærer du hvordan du bruker sammensatte visninger for å lage egendefinerte visninger som er lett å gjenbrukbare.

1. Introduksjon

På Android kalles en visning som er sammensatt av en gruppe visninger, en sammensatt visning eller en sammensatt komponent. I denne veiledningen vil du bygge en kontroll for å velge en verdi fra en liste som ruller fra side til side. Vi kaller sammensatt en sidespinner siden standardvisningen til Android SDK for å velge en verdi fra en liste kalles en spinner. Følgende skjermbilde illustrerer hva vi skal skape i denne opplæringen.

2. Prosjektoppsett

For å komme i gang må du opprette et nytt Android-prosjekt med Android 4.0 som minimumskrav til SDK-nivå. Dette prosjektet bør bare inneholde en tom aktivitet som kalles Hoved aktivitet. De Aktivitet gjør ingenting mer enn å initialisere oppsettet som du kan se i følgende kodestykke.

offentlig klasse MainActivity utvider Aktivitet @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); 

Oppsettet for Hoved aktivitet ligger i /res/layout/activity_main.xml fil og den skal bare bare inneholde en tom RelativeLayout der sammensatt visningen vil bli vist senere.

 

3. Lag en sammensatt visning

For å opprette en sammensatt visning må du opprette en ny klasse som administrerer visningene i sammensatt visning. For sidespinneren trenger du to Knapp utsikt for pilene og a TextView vis for å vise den valgte verdien.

For å komme i gang, opprett /res/layout/sidespinner_view.xml layoutfil som vi skal bruke til sidespinnerklassen, sørg for å pakke inn de tre visningene i a  stikkord.

 

Deretter må vi opprette SideSpinner klassen som oppblåser dette oppsettet og setter pilene som bakgrunnsbilde for knappene. På dette tidspunktet gjør ikke sammensatt visningen noe siden det ikke er noe å vise ennå.

offentlig klasse SideSpinner utvider LinearLayout privat knapp mPreviousButton; privat knapp mNextButton; offentlig SideSpinner (kontekst kontekst) super (kontekst); initializeViews (sammenheng);  Offentlig SideSpinner (Kontekst Kontekst, AttributtSett Attrs) super (kontekst, attrs); initializeViews (sammenheng);  offentlig SideSpinner (Kontekst kontekst, AttributtSett attrs, int defStyle) super (kontekst, attrs, defStyle); initializeViews (sammenheng);  / ** * Blinker opp visningene i oppsettet. * * @param kontekst * Den aktuelle konteksten for visningen. * / Private void initializeViews (Kontekst kontekst) LayoutInflater inflater = (LayoutInflater) kontekst .getSystemService (Context.LAYOUT_INFLATER_SERVICE); inflater.inflate (R.layout.sidespinner_view, dette);  @Override protected void onFinishInflate () super.onFinishInflate (); // Setter bildene for de forrige og neste knappene. Bruker // innebygde bilder, slik at du ikke trenger å legge til bilder, men i // et ekte program bør bildene dine være i // programpakken, slik at de alltid er tilgjengelige. mPreviousButton = (Knapp) denne .findViewById (R.id.sidespinner_view_previous); mPreviousButton .setBackgroundResource (android.R.drawable.ic_media_previous); mNextButton = (Knapp) denne .findViewById (Rid.sidespinner_view_next); mNextButton .setBackgroundResource (android.R.drawable.ic_media_next); 

Du vil legge merke til at sammensatt visning utvider LinearLayout se gruppe. Dette betyr at ethvert layout ved hjelp av sammensatt visning har tilgang til attributter av den lineære oppsettet. Som et resultat er layoutet for sammensatt visningen litt annerledes enn vanlig, root-taggen er a  tag i stedet for taggen for en visningsgruppe som  eller .

Når du legger til sammensatt visningen til layouten av Hoved aktivitet, taggen for sammensatt visning vil fungere som en  stikkord. En sammensatt visningsklasse kan utlede fra hvilken som helst klasse som kommer fra ViewGroup, men i dette tilfellet er den lineære utformingen den mest hensiktsmessige siden visningene er lagt ut horisontalt.

4. Legg til sammensatt visning til en layout

På dette tidspunktet samles prosjektet, men ingenting er synlig siden sammensatt visningen ikke er i utformingen av Hoved aktivitet. Sidespinnevisningen må legges til oppsettet av aktiviteten som enhver annen visning. Navnet på taggen er navnet på SideSpinner klasse, inkludert navneområde.

For å legge til sidespinneren til Hoved aktivitet, legg til følgende i forhold til det relative oppsettet i /res/layout/activity_main.xml fil.

Attributtene som er tilgjengelige i tag er attributter av den lineære oppsettet siden SideSpinner klasse vi opprettet strekker seg ut LinearLayout klasse. Hvis du starter prosjektet, bør sidespinneren være synlig, men det inneholder ingen verdier ennå.

5. Legg til metoder i sammensatt visning

Det mangler fortsatt noen ting hvis vi egentlig vil bruke sidespinneren. Vi bør kunne legge til nye verdier i spinneren, velge en verdi og få den valgte verdien.

Den enkleste måten å legge til ny oppførsel på i en sammensatt visning, er å legge til nye offentlige metoder i SideSpinner klasse. Disse metodene kan brukes av noen Aktivitet som har en referanse til visningen.

privat CharSequence [] mSpinnerValues ​​= null; privat int mSelectedIndex = -1; / ** * Angir listen over verdier i spinneren, velg den første verdien * som standard. * * @param verdier * verdiene som skal settes i spinneren. * / public void setValues ​​(CharSequence [] verdier) mSpinnerValues ​​= values; // Velg det første elementet i strengen array som standard siden // listen over verdi har endret seg. setSelectedIndex (0);  / ** * Angir den valgte indeksen for spinneren. * * @param index * indeksen for verdien å velge. * / public void setSelectedIndex (int index) // Hvis ingen verdier er angitt for spinneren, gjør ingenting. hvis (mSpinnerValues ​​== null || mSpinnerValues.length == 0) tilbake; // Hvis indeksverdien er ugyldig, gjør ingenting. hvis (indeks < 0 || index >= mSpinnerValues.length) returnere; // Sett gjeldende indeks og vis verdien. mSelectedIndex = index; TextView currentValue; currentValue = (TextView) denne .findViewById (R.id.sidespinner_view_current_value); currentValue.setText (mSpinnerValues ​​[index]); // Hvis den første verdien vises, skjul den forrige knappen. hvis (mSelectedIndex == 0) mPreviousButton.setVisibility (INVISIBLE); ellers mPreviousButton.setVisibility (VISIBLE); // Hvis den siste verdien vises, skjul den neste knappen. hvis (mSelectedIndex == mSpinnerValues.length - 1) mNextButton.setVisibility (INVISIBLE); ellers mNextButton.setVisibility (VISIBLE);  / ** * Får den valgte verdien av spinneren, eller null hvis ingen gyldig * valgt indeks er angitt ennå. * * @ returner den valgte verdien av spinneren. * / offentlig CharSequence getSelectedValue () // Hvis ingen verdier er angitt for spinneren, returner du en tom streng. hvis (mSpinnerValues ​​== null || mSpinnerValues.length == 0) returnere ""; // Hvis gjeldende indeks er ugyldig, returner du en tom streng. hvis (mSelectedIndex < 0 || mSelectedIndex >= mSpinnerValues.length) returnere ""; returner mSpinnerValues ​​[mSelectedIndex];  / ** * Får den valgte indeksen til spinneren. * * @return den valgte indeksen til spinneren. * / public int getSelectedIndex () return mSelectedIndex; 

De onFinishInflate Metoden for sammensatt visning kalles når alle visningene i oppsettet er oppblåst og klar til bruk. Dette er stedet å legge til koden din hvis du må endre visninger i sammensatt visning.

Med metodene du nettopp har lagt til i SideSpinner klasse, oppførsel for knappene som velger forrige og neste verdi kan nå legges til. Erstatt den eksisterende koden i onFinishInflate metode med følgende:

@Override protected void onFinishInflate () // Når kontrollene i oppsettet gjør oppblåsing, sett // tilbakekallingen til sidepilene. super.onFinishInflate (); // Når forrige knapp trykkes, velg forrige verdi // i listen. mPreviousButton = (Knapp) denne .findViewById (R.id.sidespinner_view_previous); mPreviousButton .setBackgroundResource (android.R.drawable.ic_media_previous); mPreviousButton.setOnClickListener (ny OnClickListener () public void onClick (Vis visning) hvis (mSelectedIndex> 0) int newSelectedIndex = mSelectedIndex - 1; setSelectedIndex (newSelectedIndex);); // Når neste knapp trykkes, velger du det neste elementet i // -listen. mNextButton = (Knapp) denne .findViewById (Rid.sidespinner_view_next); mNextButton .setBackgroundResource (android.R.drawable.ic_media_next); mNextButton.setOnClickListener (ny OnClickListener () public void onClick (Vis visning) if (mSpinnerValues! = null && mSelectedIndex < mSpinnerValues.length - 1)  int newSelectedIndex = mSelectedIndex + 1; setSelectedIndex(newSelectedIndex);   ); // Select the first value by default. setSelectedIndex(0); 

Med den nyopprettede setValues og setSelectedIndex metoder, kan vi nå initialisere sidespinneren fra vår kode. Som med alle andre visninger, må du finne sidespinneren i layoutet med findViewById metode. Vi kan deretter ringe noen offentlig metode på visningen fra gjenstanden som returneres, inkludert de vi nettopp har opprettet.

Følgende kodestykke viser hvordan du oppdaterer onCreate metode av Hoved aktivitet klasse for å vise en liste over verdier i sidespinneren, ved hjelp av setValues metode. Vi kan også velge den andre verdien i listen som standard ved å påkalle setSelectedIndex metode.

offentlig klasse MainActivity utvider Aktivitet @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); // Initialiserer sidespinneren fra kode. SideSpinner fruitsSpinner; fruitsSpinner = (SideSpinner) this .findViewById (R.id.sidespinner_fruits); CharSequence FruitList [] = "Apple", "Orange", "Pear", "Druer"; fruitsSpinner.setValues ​​(fruitList); fruitsSpinner.setSelectedIndex (1); 

Hvis du starter programmet, skal sidespinneren virke som forventet. Listen over verdier vises og verdien oransje er valgt som standard.

6. Legg til layoutegenskaper til sammensatte visning

Synspunktene som er tilgjengelige i Android SDK kan endres via kode, men noen attributter kan også settes direkte i det tilsvarende layoutet. La oss legge til et attributt til sidespinneren som angir verdiene som sidespinneren må vise.

For å opprette et egendefinert attributt for sammensatt visning, må vi først definere attributtet i /res/values/attr.xml fil. Hver egenskap av sammensatt visning bør grupperes i en stilig med a stikkord. For sidespinneren brukes klassens navn som vist nedenfor.

    

tag, den Navn Attributt inneholder identifikatoren som brukes til å referere til det nye attributtet i layoutet og i format Attributtet inneholder typen av det nye attributtet.

For listen over verdier, er henvisning type brukes siden attributtet vil henvise til en liste over strenger definert som en ressurs. Verditypene som vanligvis brukes i layouter, kan brukes til dine egendefinerte attributter, inkludert booleanfargedimensjonenumheltallflyte og string.

Slik definerer du ressursen for en liste over strenger som verdier attributten til sidespinneren vil referere til. Det må legges til i /res/values/strings.xml filen som vist nedenfor.

  Agurk Potet Tomat Løk squash  

For å teste den nye verdier attributt, opprett en sidespinnervisning i Hoved aktivitet layout under den eksisterende sidespinneren. Attributtet må være prefiks med et navneområde lagt til RelativeLayout, som for eksempel xmlns: sidespinner = "http://schemas.android.com/apk/res-auto". Dette er hva den endelige layoutet i /res/layout/activity_main.xml skal se ut.

   

Endelig, den SideSpinner klassen må endres for å lese verdier Egenskap. Verdien av alle attributtene til visningen er tilgjengelig i AttributeSet objekt som sendes inn som en parameter av visningskonstruktøren.

For å få verdien av din egendefinerte verdier attributt, vi ringer først på obtainStyledAttributes metode av AttributeSet objekt med navnet på den stilige som inneholder attributtet. Dette returnerer listen over attributter for den stilige som en TypedArray gjenstand.

Vi kaller så gettermetoden til TypedArray objekt som har riktig type for attributtet du vil ha, og sender identifikatoren for attributtet som en parameter. Følgende kodeblokk viser hvordan du kan endre konstruktøren til sidespinneren for å få listen over verdier og sette dem i sidespinneren.

offentlig SideSpinner (kontekst kontekst) super (kontekst); initializeViews (sammenheng);  Offentlig SideSpinner (Kontekst Kontekst, AttributtSett Attrs) super (kontekst, attrs); TypedArray typedArray; typedArray = kontekst .obtainStyledAttributes (attrs, R.styleable.SideSpinner); mSpinnerValues ​​= typedArray .getTextArray (R.styleable.SideSpinner_values); typedArray.recycle (); initializeViews (sammenheng);  offentlig SideSpinner (Kontekst kontekst, AttributtSett attrs, int defStyle) super (kontekst, attrs, defStyle); TypedArray typedArray; typedArray = kontekst .obtainStyledAttributes (attrs, R.styleable.SideSpinner); mSpinnerValues ​​= typedArray .getTextArray (R.styleable.SideSpinner_values); typedArray.recycle (); initializeViews (sammenheng); 

Hvis du starter programmet, bør du se to sidespinnere som arbeider uavhengig av hverandre.

7. Lagre og gjenopprett stat

Det siste trinnet vi må fullføre, er å lagre og gjenopprette tilstanden til sammensatt visningen. Når en aktivitet ødelegges og gjenopprettes, for eksempel når enheten roteres, lagres og gjenopprettes verdiene av innfødte visninger med en unik identifikator automatisk. Dette er for øyeblikket ikke sant for sidespinneren.

Statens visninger lagres ikke. Identifikatorene til visningene i SideSpinner klassen er ikke unik siden den kan gjenbrukes mange ganger. Dette betyr at vi er ansvarlige for å lagre og gjenopprette verdiene av visningene i sammensatt visning. Vi gjør dette ved å implementere onSaveInstanceState, onRestoreInstanceState, og dispatchSaveInstanceState metoder. Følgende kodeblokk viser hvordan du gjør dette for sidespinneren.

/ ** * Identifikator for staten for å lagre den valgte indeksen for * sidespinneren. * / privat statisk streng STATE_SELECTED_INDEX = "SelectedIndex"; / ** * Identifikator for tilstanden til superklassen. * / privat statisk streng STATE_SUPER_CLASS = "SuperClass"; @Override protected Parcelable onSaveInstanceState () Bundle bundle = ny Bundle (); bundle.putParcelable (STATE_SUPER_CLASS, super.onSaveInstanceState ()); bundle.putInt (STATE_SELECTED_INDEX, mSelectedIndex); returbunt;  @Override protected void onRestoreInstanceState (omsettelig tilstand) if (state instanceof Bundle) Bundle bundle = (Bundle) state; super.onRestoreInstanceState (bundle .getParcelable (STATE_SUPER_CLASS)); setSelectedIndex (bundle.getInt (STATE_SELECTED_INDEX));  annet super.onRestoreInstanceState (state);  @Override protected void dispatchSaveInstanceState (SparseArray container) // Passer på at statusen til barnets visninger i side // spinneren ikke lagres siden vi håndterer tilstanden i // onSaveInstanceState. super.dispatchFreezeSelfOnly (container);  @Override protected void dispatchRestoreInstanceState (SparseArray container) // Passer på at statusen til barnets visninger i side // spinneren ikke gjenopprettes siden vi håndterer tilstanden i // onSaveInstanceState. super.dispatchThawSelfOnly (container); 

Konklusjon

Sidespinneren er nå ferdig. Begge sidespinnere virker som forventet og deres verdier gjenopprettes hvis aktiviteten blir ødelagt og gjenopprettet. Du kan nå bruke det du har lært å gjenbruke en hvilken som helst gruppe visninger i et Android-program ved å bruke sammensatte visninger.