Du snurrer meg rundt: Lag en tilpasset 'spinner' i Android

Enhver erfaren ingeniør vil fortelle deg at hver plattform har sine styrker og sine svakheter. Å være den ledende Android-utvikleren på et team som også skriver programvare for iPhone og Windows Phone 7, blir jeg ofte påminnet om hvor "løs" Googles brukergrensesnitt er. Det er ikke å si at jeg ikke elsker Android's åpne arkitektur - det gjør jeg. Android er et kraftig operativsystem, og det er veldig lite det ikke kan gjøre. Men innsatsen som trengs for å utføre noen av de glatte overgangseffektene og opprettholde den konsistente presentasjonen som ganske enkelt "er" på Apple og Microsoft mobile plattformer, kan være litt skremmende for utviklere å få føttene våte i Googles digitale basseng.

Nylig måtte jeg implementere min egen tilpassede "spinner" i en listevisning. Du vet hva jeg mener - et av de sirkulære bildene som snurrer rett rundt (baby right round) for å indikere at noe laster. Selv om det er en ProgressBar-klasse i Android-rammen, introduserer dette kompleksiteten i en tilleggsvisning, og det virket som unødvendig overhead for en så triviell oppgave. Så jeg støttet litt på den nåværende tilstanden i animasjonsrammen, kastet opp en bildevisning og prøvde den.

Mens jeg var glad for å oppdage at Google UI-rammeteamet gjør fremskritt i riktig retning, løp jeg inn et par støt underveis med klasser som ikke oppførte seg som jeg hadde forventet, og i et tilfelle oppførte en klasse seg ikke folkene på Google forventet heller (eller i det minste ingeniøren som skrev dokumentasjonen for klassen, ikke hadde en solid forståelse av funksjonen). Etter noen dager med koding, flere omlesinger av dokumentasjonen, og et par innlegg i Google-kodeforumene, fikk jeg til slutt "spinneren" opp og snurret. Opplæringen som følger vil vise deg hvordan du kan gjøre det samme, og forhåpentligvis redde deg fra å oppdage de skumle gottene på den harde måten.

Hele kildekoden for demoen kan lastes ned som et komprimert arkiv her. Jeg har tatt med tre bilder i ressursmappen, som jeg fant på Google Bilder. (Stol på meg ... ingen vil at jeg skal tegne bilder fra bunnen av. Jeg er fremdeles hjemsøkt av minnet om tiden i skolekunstklassen vi måtte tegne kjæledyret vårt, og til tross for min beste innsats på en hund, ble jeg sendt til rektorens kontor for det læreren min trodde var sikkert en skikkelig prank.) Jeg så ingen opphavsrettsinformasjon om bildene jeg valgte, men hvis du er skaper / eier av et av bildene jeg brukte og vil at jeg skulle gjøre det bruk noe annet eller gi deg litt kreditt i kildefilene. Bare slipp meg en linje.

1. Lag et nytt Android-prosjekt i Eclipse ved hjelp av plug-in-modulen. Jeg prøver alltid å støtte det bredeste utvalg av telefoner, og som sådan kan du bygge dette prosjektet for alle versjoner av operativsystemet som er større enn eller lik Android 1.6 (Cupcake).

2. Legg til de uavhengige tegnene du planlegger å bruke i den aktuelle ressursmappen. I mitt tilfelle har jeg tre bilder med tittelen: flower_icon.png, frog_icon.png og gear_icon.png.

3. Opprett en / anim-mappe i / res-katalogen. Det er her du vil legge til XML-filene som definerer "tween" -animasjonene. Google tween-animasjonsmotoren er imponerende. Foruten rotasjoner, er den i stand til å utføre skalaoperasjoner, alpha-kanalanimasjoner og oversette manipulasjoner.

4. Legg til følgende definisjoner av XML-animasjon:

alpha.xml

"1.0" encoding = "utf-8" ?>

xmlns: android = "http://schemas.android.com/apk/res/android"

android: fromAlpha = "1.0"

android: toAlpha = "0.0"

android: varighet = "2000" />

rotate.xml "1.0" encoding = "UTF-8" ?>

xmlns: android = "http://schemas.android.com/apk/res/android"

android: fromDegrees = "0"

android: toDegrees = "360"

android: pivotX = "50%"

android: pivotY = "50%"

android: interpolator = "@android: anim / linear_interpolator"

android: varighet = "2000" />

scale.xml

"1.0" encoding = "utf-8" ?>

xmlns: android = "http://schemas.android.com/apk/res/android"

android: fromXScale = "1"

android: toXScale = ".25"

android: fromYScale = "1"

android: toYScale = ".25"

android: pivotX = "50%"

android: pivotY = "50%"

android: varighet = "2000" />

Gotcha: Dokumentasjonen sier at du kan angi egenskapen for gjenta antall i XML-filen, men etter min erfaring fungerer den ikke alltid på denne måten, spesielt når du bruker animasjonssett for å lage kombinerte animasjonseffekter. Jeg anbefaler at du setter deg inn i vanen med å angi egenskapen for repetisjonstelling i Java-koden din, og jeg vil vise deg hvordan du gjør det i min tilpassede listevisningskort.

5. I mappen / layout legger du til en standard listevisning til hovedoppsettet.

main.xml

"1.0" encoding = "utf-8" ?>

"Http://schemas.android.com/apk/res/android"

android: orientering = "vertikal"

android: layout_width = "fill_parent"

android: layout_height = "fill_parent" >

android: layout_width = "fill_parent"

android: layout_height = "wrap_content"

android: text = "@ streng / hallo" />

android: id = "@ + id / android: list"

android: layout_width = "fill_parent"

android: layout_height = "fill_parent"

android: cacheColorHint = "# 0000"

android: bakgrunn = "@android: farge / gjennomsiktig"

android: dividerHeight = "1dip" />

6. Definer radvisningen. Jeg brukte en tabelloppsett med en tekst og ett bildevisning.

list_view_row.xml

"1.0" encoding = "utf-8" ?>

"Http://schemas.android.com/apk/res/android"

android: layout_width = "fill_parent"

android: layout_height = "? android: attr / listPreferredItemHeight"

android: padding = "6dip" >

"horisontal"

android: layout_width = "fill_parent"

android: layout_height = "wrap_content"

android: layout_marginBottom = "2dip"

android: stretchColumns = "*" >

android: id = "@ + id / label"

android: textSize = "18sp"

android: polstring = "2dip"

android: gravitasjon = "venstre | sentrum"

android: layout_gravity = "venstre | sentrum"

android: layout_width = "wrap_content"

android: layout_height = "wrap_content"

android: textColor = "#ffffff" />

android: id = "@ + id / gfx"

android: polstring = "2dip"

android: gravitasjon = "høyre | sentrum"

android: layout_gravity = "høyre | sentrum"

android: layout_width = "fill_parent"

android: layout_height = "wrap_content" />

7. Gå videre til kildekoden. Ved å bruke standardlistevisning / adapterhierarki, må elementene i listen følge med sin egen tilstand for tegning, og som sådan krever vi en enkel beholder for egen produksjon.

MyContainer.java

pakke authorwjf.com;

offentlig klasse MyContainer {

private String mText = "";

privat boolsk mAnimating = falsk ;

privat int mDrawable = -1;

public void setText (String someText) {mText = someText; }

public String getText () { return mText; }

public void setAnimating (Boolean isAnimating) {mAnimating = isAnimating; }

public Boolean isAnimating () { return mAnimating;}

public void setDrawableResourceId ( int id) {mDrawable = id; };

public int getDrawableResourceId () { return mDrawable; }

}

8. Hovedklassen gjør lite mer enn å laste i listevisningen og veksle tegningsflagget når et element i listen er valgt.

Main.java- pakken authorwjf.com;

importer java.util.ArrayList;

import android.app.ListActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.ListView;

public class Main utvider ListActivity {

private ArrayList mItems = null ;

privat tilpasset adapter mAdapter;

/ ** Ringes når aktiviteten først opprettes. * /

@Overstyring

public void onCreate (Bundle savedInstanceState) {

super .onCreate (savedInstanceState);

setContentView (R.layout. main );

mItems = new ArrayList ();

MyContainer item1 = new MyContainer ();

item1.setAnimating ( falsk );

item1.setText ("Rotatation Tween Effect");

item1.setDrawableResourceId (R.drawable. gear_icon );

mItems.add (item1);

MyContainer item2 = new MyContainer ();

item2.setAnimating ( falsk );

item2.setText ("Alpha Tween Effect");

item2.setDrawableResourceId (R.drawable. frog_icon );

mItems.add (ITEM2);

MyContainer item3 = new MyContainer ();

item3.setAnimating ( falsk );

item3.setText ("Scale Tween Effect");

item3.setDrawableResourceId (R.drawable. flower_icon );

mItems.add (ITEM3);

mAdapter = ny CustomAdapter ( dette, R.layout. list_view_row, mItems);

setListAdapter (mAdapter);

}

/ **

* Listevisning på klikkbehandler.

* /

@Overstyring

public void onListItemClick (ListView-overordnet, Vis v, int- posisjon, lang id) {

mItems.get (stilling) .setAnimating (mItems.get (stilling) .isAnimating ()!);

mAdapter.notifyDataSetChanged ();

}

}

9. Sist, men absolutt ikke minst, er vår tilpassede adapter ansvarlig for å slå av og på animasjonene. Det er her jeg setter inn animasjonsrepetanseegenskapen (anim.setRepeatCount (Animasjon. INFINITE )) i stedet for i XML-filene, slik Google-dokumentasjonen ofte antyder.

CustomAdapter.java

pakke authorwjf.com;

importer java.util.ArrayList;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.view.animation.Animation;

import android.view.animation.AnimationUtils;

import android.widget.ArrayAdapter;

import android.widget.ImageView;

import android.widget.TextView;

Custom class CustomAdapter utvider ArrayAdapter {

private ArrayList-varer;

privat kontekst c = null ;

public CustomAdapter (Kontekstkontekst, int textViewResourceId, ArrayList-elementer) {

super (kontekst, textViewResourceId, elementer);

dette .items = elementer;

dette .c = kontekst;

}

@Overstyring

public View getView ( int- posisjon, View convertView, ViewGroup-overordnede) {

Vis v = convertView;

if (v == null ) {

LayoutInflater vi = (LayoutInflater) c.getSystemService (Kontekst. LAYOUT_INFLATER_SERVICE );

v = vi.inflate (R.layout. list_view_row, null );

}

TextView label = (TextView) v.findViewById (R.id. Label );

ImageView gfx = (ImageView) v.findViewById (R.id. Gfx);

MyContainer item = (MyContainer) items.get (posisjon);

Animasjon anim = null ;

switch (item.getDrawableResourceId ()) {

sak R. trekkbar. flower_icon :

anim = AnimationUtils. loadAnimation (getContext (), R.anim. skala );

pause ;

sak R. trekkbar. frog_icon :

anim = AnimationUtils. loadAnimation (getContext (), R.anim. alpha );

pause ;

sak R. trekkbar. gir_icon :

anim = AnimationUtils. loadAnimation (getContext (), R.anim. rotate );

pause ;

}

label.setText (item.getText ());

gfx.setImageResource (item.getDrawableResourceId ());

gfx.clearAnimation ();

gfx.setVisibility (visning. SYNLIG );

if (item.isAnimating ()) {

anim.setRepeatCount (Animasjon. INFINITE );

anim.setRepeatMode (Animasjon. REVERSE );

gfx.startAnimation (Anim);

}

retur v;

}

}

Gotcha: Av grunner til at jeg ikke fullt ut forstår, må du ringe .clearAnimation hver gang adapteren blir påkalt. Atferden du får ellers er wonky og antyder at brukergrensesnittet for brukeren bruker utsikter på en mindre enn ideell måte. Hvis du vil se hva jeg snakker om, kan du kommentere linjen gfx.clearAnimation (); og last deretter applikasjonen på enheten din og trykk på et par forskjellige rader. Du vil se rader som er påvirket av at du ikke trykket på, og på en måte som ikke er tilsynelatende logisk. Jeg fikk dette emnet med en rammeingeniør fra Google UI og fikk aldri et tilfredsstillende svar.

Der har du det, litt UI-kjærlighet til Googles favorittrobot. Til mine andre Android-utviklere sier jeg: "Se! Apples iPhone er ikke den eneste enheten der ute som kan ha en glatt UI. Det er til tider litt mer arbeid å komme dit herfra."

Skjermbilde av animasjonene våre som kjører på emulatoren.

© Copyright 2021 | pepebotifarra.com