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.
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.
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.
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.
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å.
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.
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.
I
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 boolean
, farge
, dimensjon
, enum
, heltall
, flyte
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.
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 (SparseArraycontainer) // 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);
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.