Progettazione dell'interfaccia utente Android lavorare con i frammenti

La nuova Fragment API per Android, introdotta in Android 3.0, consente un'interfaccia utente dinamica più semplice. In questo tutorial, scopri come convertire un flusso di lavoro di ListView a WebView a due schermi in un flusso di lavoro a schermo unico progettato per schermi di grandi dimensioni, come quelli che si trovano sui tablet.

Modifiche successive alle tecniche e al software

Alcuni aspetti delle applicazioni o delle tecniche utilizzate in questo tutorial sono cambiati da quando è stato originariamente pubblicato. Questo potrebbe rendere un po 'difficile da seguire. Ti consigliamo di guardare questi tutorial più recenti sullo stesso argomento:

  • Android SDK: utilizzo di frammenti

Il ritmo di questo tutorial sarà più veloce di alcuni dei nostri tutorial per principianti; potrebbe essere necessario rivedere alcune delle altre esercitazioni Android su questo sito o anche nel riferimento all'SDK di Android se non si ha familiarità con i concetti e le lezioni di base di Android trattati in questo tutorial. Il codice di esempio finale che accompagna questo tutorial è disponibile per il download come open-source dall'hosting del codice Google.

Presentazione dei frammenti

Prima di iniziare, definiamo cos'è un frammento, ad alto livello. Un frammento è, in genere, una parte dell'interfaccia utente con il proprio ciclo di vita. Se questo suona molto come un'attività, è perché è molto simile a un'attività. Tuttavia, un frammento è diverso da un'attività, in quanto deve esistere un frammento all'interno di un'attività. Un frammento non deve essere associato alla stessa attività ogni volta che viene istanziato, il che gli conferisce una certa flessibilità. Anche come un'attività, un frammento non deve contenere alcuna interfaccia utente.

Passaggio 0: Introduzione

Questo tutorial presume che inizierai da dove è stato interrotto il nostro tutorial su ListView. Puoi scaricare quel codice e compilare da lì, anche se avrai alcune attività che dovrai eseguire senza assistenza, oppure puoi scaricare il codice per questo tutorial e seguirlo.

Passaggio 1: riprogettazione degli schermi

La seguente figura illustra il flusso di lavoro esistente della nostra app per lettori di articoli Mobiletuts + (il tutorial di ListView) prima che un progetto di Frammento fosse considerato e applicato:

Questo flusso di lavoro funziona correttamente su uno schermo del telefono relativamente piccolo. Tuttavia, su un grande schermo, come lo schermo da 10 "del Motorola Xoom, e c'è molto spazio sprecato sullo schermo di ListView. Lo schermo WebView sembra buono, anche se un po 'noioso.

È qui che entrano in gioco i frammenti: su schermi più grandi, potremmo fornire un'interfaccia utente più efficace se potessimo visualizzare il ListView sullo stesso schermo di WebView. Quando l'utente fa clic su un elemento ListView specifico nel riquadro sinistro ?, la WebView sul lato destro viene aggiornata per visualizzare il contenuto appropriato. Questo tipo di flusso di lavoro viene spesso utilizzato nei lettori di e-mail o di feed di documenti. La seguente figura illustra proprio tale riprogettazione:

Passaggio 2: conversione in un progetto basato su frammenti

Ora che sappiamo come verrà progettato il nuovo flusso di lavoro dello schermo, sappiamo anche che le due attività correnti dovranno essere convertite in frammenti. Faremo la conversione in diversi passaggi. Il primo passo consiste nel lasciare visivamente inalterate le schermate, ma modificare ogni schermata per utilizzare un frammento. Un frammento conterrà il ListView corrente e un altro conterrà la WebView. Quindi passeremo a un'implementazione a schermo singolo, che comporta la modifica della messaggistica tra le attività ListView e WebView trasformate in frammenti.

Innanzitutto, però, modifica la Target di costruzione del progetto della tua applicazione su Android 3.0. Per eseguire questa operazione da Eclipse, fare clic con il tasto destro del mouse sul progetto e selezionare Proprietà. Vai alla sezione Android e seleziona la casella accanto ad Android 3.0. Non stiamo utilizzando alcuna API di Google, quindi la versione del progetto Open Source Android è sufficiente. Quindi fare clic sul pulsante OK.

Ora avrai accesso alle nuove API, inclusa l'API Fragments.

Nota: in un futuro tutorial, parleremo dell'utilizzo del nuovo livello di compatibilità per consentire a tecnologie come l'API Fragment di funzionare su versioni precedenti di Android. Per ora, però, richiederanno un dispositivo con Android 3.0, Honeycomb.

Passaggio 3: creazione delle classi frammento

Creare due nuove classi Java per rappresentare i due frammenti: le schermate ListView e WebView. Denominali TutListFragment e TutViewerFragment. TutListFragment estenderà la classe ListFragment e TutViewerFragment estenderà semplicemente la classe Fragment.

All'interno della classe TutListFragment, è necessario eseguire l'override di due metodi: onListItemClick () e onCreate (). Il contenuto di questi metodi dovrebbe apparire familiare; corrispondono a ciò che avevamo precedentemente nella classe TutListActivity. Questo cambierà a breve, ma non ancora. Ecco un elenco della classe TutListFragment, per ora:

 @Override public void onListItemClick (ListView l, Visualizza v, int position, long id) String [] links = getResources (). GetStringArray (R.array.tut_links); Contenuto di stringhe = collegamenti [posizione]; Inten showContent = new Intent (getActivity (). GetApplicationContext (), TutViewerActivity.class); showContent.setData (Uri.parse (contenuto)); startActivity (showContent);  @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setListAdapter (ArrayAdapter.createFromResource (getActivity () .getApplicationContext (), R.array.tut_titles, R.layout.list_item)); 

La classe TutViewerFragment è un po 'più semplice. Usiamo il fatto che sappiamo (per ora) che il frammento è in esecuzione con la stessa attività a cui era abituato e cattura i dati di intent direttamente dalla classe Fragment. Aggiungi un metodo di sovrascrittura per il metodo onCreateView (). Questo metodo dovrebbe ora assomigliare a questo:

 @Override public Visualizza onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) Intent launchInInent = getActivity (). GetIntent (); String content = launchingIntent.getData (). ToString (); WebView viewer = (WebView) inflater.inflate (R.layout.tut_view, container, false); viewer.loadUrl (contenuto); visore di ritorno; 

La possibilità di accedere direttamente all'istanza dell'attività è utile, ma in seguito creerà un problema. Cosa succede se questo frammento è sullo schermo con il frammento della lista? In tale scenario, non ci sarà alcun intento di lancio da cui ottenere l'URL. Allo stesso modo, in TutListFragment, lanciamo una nuova attività direttamente ogni volta che l'utente fa clic su un elemento nell'elenco. Cosa succede se il TutViewFragment esisteva all'interno della stessa attività? In tal caso, il lancio di una nuova attività non avrebbe alcun senso. Torneremo a risolvere questi problemi più avanti in questo tutorial.

Passaggio 4: aggiunta delle risorse del layout del frammento

Ora crea un nuovo file di layout chiamato tutlist_fragment.xml per rappresentare il frammento contenente l'elenco di articoli. Una risorsa di layout Fragment utilizza il tag e fa riferimento alla classe Fragment creata.

   

Quindi, crea un file di layout simile chiamato tutview_fragment.xml:

   

Passaggio 5: aggiornamento delle classi di attività

Le classi TutListActivity e TutViewerActivity devono ora essere aggiornate. La classe TutListActivity ha un singolo metodo, onCreate (), che dovrebbe ora essere aggiornato per caricare la risorsa di layout Fragment appropriata creata nel passaggio precedente, in questo modo:

 @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.tutlist_fragment); 

Inoltre, di nota, TutListActivity dovrebbe ereditare dalla classe Activity, non da ListActivity.

La classe TutViewerActivity richiede una modifica simile. Il suo metodo onCreate () dovrebbe ora assomigliare a questo:

 @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.tutview_fragment); 

Passaggio 6: verifica dei progressi

Prova a eseguire l'applicazione ora. Noterai che fa esattamente quello che era solito fare. Non è ancora molto eccitante, vero? Tuttavia, l'intera interfaccia utente viene ora eseguita utilizzando i frammenti. Ciò consentirà le prossime modifiche che è necessario apportare per passare agevolmente mentre aggiungiamo un nuovo layout per combinare i due frammenti per i display più grandi da mostrare all'utente su un'unica schermata. Tuttavia, come avrete notato, la comunicazione tra i frammenti viene gestita in modo identico a come comunichiamo tra le attività. Infatti, abbiamo usato la consapevolezza che l'attività con cui ciascun frammento è stato abbinato è rimasto invariato. Questo non sarà il caso quando abbiamo una singola attività che contiene e gestisce entrambi i frammenti. Risolviamo questo prima.

Passaggio 7: Modifica della comunicazione per TutListFragment

Come hai appreso nel passaggio 3, l'avvio di un'attività direttamente dall'oggetto TutListFragment non ha più senso. L'interfaccia utente WebView può, infatti, essere parte della stessa attività dell'elenco, che è il nostro piano comunque per gli schermi più grandi. In tal caso, vogliamo solo aggiornare l'URL di WebView nel secondo frammento.

Per fare questo cambiamento, dobbiamo fare diverse cose. Per prima cosa, rendiamo i frammenti indipendenti dall'attività in cui risiedono. Per fare ciò, aggiungi un'interfaccia listener alla classe TutListFragment, in quanto tale:

 interfaccia pubblica OnTutSelectedListener public void onTutSelected (Uri tutUri); 

E quindi attivarlo aggiornando il metodo onListItemClickListener () come segue:

 @Override public void onListItemClick (ListView l, Visualizza v, int position, long id) String [] links = getResources (). GetStringArray (R.array.tut_links); Contenuto di stringhe = collegamenti [posizione]; tutSelectedListener.onTutSelected (Uri.parse (contenuto)); 

Quindi, fare in modo che la classe TutListActivity implementa l'interfaccia OnTutSelectedListener, in questo modo:

 public class TutListActivity estende Activity implementa TutListFragment.OnTutSelectedListener ? @Override public void onTutSelected (Uri tutUri) Intent showContent = new Intent (getApplicationContext (), TutViewerActivity.class); showContent.setData (tutUri); startActivity (showContent); 

Così ora abbiamo la funzionalità divisa tra il frammento, che gestisce le azioni dell'interfaccia utente e l'attività, che può essere un controller, passando i dati all'attività successiva. Modificheremo in seguito il metodo onTutSelected () per decidere se avviare o meno una nuova istanza di attività o aggiornare l'istanza del frammento esistente.

Passaggio 8: modifica della comunicazione per TutViewerFragment

Ora spostiamo la nostra attenzione sulla classe TutViewerFragment, che deve essere aggiornata. Invece di interrogare l'intento del lancio per scoprire quale URL caricare, il frammento attenderà che gli venga detto quale URL caricare. In questo modo, possiamo aggiornare direttamente la WebView e non ricreare il frammento con ogni carico.

Innanzitutto, modifica la classe TutViewerFragment per contenere un nuovo metodo chiamato updateUrl ():

 public void updateUrl (String newUrl) if (viewer! = null) viewer.loadUrl (newUrl); 

Quindi, rimuovere tutte le funzionalità dal metodo onCreateView (), ad eccezione della chiamata inflate (). Oltre nella classe TutViewerActivity, aggiungere di nuovo la funzionalità per recuperare l'Intent e quindi chiamare il metodo updateUrl (), in questo modo:

 @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.tutview_fragment); Intent launchingIntent = getIntent (); String content = launchingIntent.getData (). ToString (); TutViewerFragment viewer = (TutViewerFragment) getFragmentManager () .findFragmentById (R.id.tutview_fragment); viewer.updateUrl (contenuto); 

A questo punto, il comportamento dell'applicazione rimane invariato. I frammenti, tuttavia, possono ora esistere all'interno della stessa attività o in quelli separati senza ulteriori modifiche al codice.

Passaggio 9: aggiunta di un layout a doppio frammento

Ora creiamo un layout con entrambi i frammenti, da utilizzare in determinate situazioni. Nella cartella layout-land (che potrebbe essere necessario creare), aggiungi una copia di tutlist_fragment.xml. Questo mostrerà un layout diverso per l'orientamento orizzontale su qualsiasi schermo orizzontale. La modalità verticale rimarrà invariata. Modifica il file in modo che assomigli al seguente layout con entrambi i frammenti:

       

Questo dividerà lo schermo orizzontalmente tra i due frammenti.

Passaggio 10: aggiunta di una scelta dinamica

Ora è possibile aggiungere all'applicazione una logica semplice per scegliere tra l'avvio di una nuova attività (il flusso di lavoro di due schermate) e l'aggiornamento di un frammento esistente (il flusso di lavoro di una schermata).

Per fare ciò, aggiornare il metodo onTutSelected () della classe TutListActivity come segue:

 @Override public void onTutSelected (String tutUrl) TutViewerFragment viewer = (TutViewerFragment) getFragmentManager () .findFragmentById (R.id.tutview_fragment); if (viewer == null ||! viewer.isInLayout ()) Intent showContent = new Intent (getApplicationContext (), TutViewerActivity.class); showContent.setData (Uri.parse (tutUrl)); startActivity (showContent);  else viewer.updateUrl (tutUrl); 

Tutto ciò è catturare il frammento e verificare se fa parte del layout esistente per l'attività. Altrimenti, viene avviata l'attività del visualizzatore, altrimenti viene aggiornato il frammento esistente.

Passaggio 11: esecuzione dell'app Recentemente frammentata

A questo punto, l'applicazione funzionerà ora in due modalità diverse: portrait non è cambiato, mentre landscape visualizza ListView a sinistra di WebView. Ci sono diversi miglioramenti che potrebbero essere apportati a questo punto, ma sono del perfezionamento, ottimizzazione e selezione nit-picking e soprattutto per lo smalto. Ad esempio, se si è in modalità ritratto WebView e si ruota lo schermo, il risultato è ancora solo lo schermo WebView. Devi premere indietro per arrivare alla doppia visualizzazione. La lucidatura va oltre lo scopo di questo tutorial, ma puoi vedere come, con l'uso critico dei layout e un po 'di logica di attività, puoi ottenere flussi di lavoro dello schermo potenti ma flessibili per una varietà di schermi e dispositivi.

Conclusione

L'API Fragment aiuta a organizzare i componenti dell'interfaccia utente in modo che possano essere riutilizzati attraverso le attività. In questo modo, un'applicazione può regolare dinamicamente il flusso di lavoro e le interfacce utente con un sovraccarico di programmazione relativamente ridotto. Hai anche visto che un'applicazione che si basa sui frammenti è più facile da riorganizzare. Ancora meglio, quasi tutte le applicazioni possono sfruttare i frammenti ora che sono disponibili tramite una libreria di compatibilità fornita da Google compatibile fino a Android 1.6.
Ora vai fuori e frammenta l'interfaccia utente delle tue app e crea interfacce utente fantastiche per ogni dimensione e forma dello schermo!

Riguardo agli Autori

Gli sviluppatori mobili Lauren Darcey e Shane Conder hanno coautore diversi libri sullo sviluppo di Android: un libro di programmazione approfondito intitolato Sviluppo di applicazioni wireless Android e Sams ti insegna a sviluppare applicazioni Android in 24 ore. Quando non scrivono, passano il loro tempo a sviluppare software mobile presso la loro azienda ea fornire servizi di consulenza. Possono essere contattati via email a [email protected], tramite il loro blog su androidbook.blogspot.com e su Twitter @androidwireless.

Hai bisogno di più aiuto nella scrittura di app per Android? Consulta i nostri ultimi libri e risorse!

я я