Autore Topic: [facile] Creare un menu con le ViewStub  (Letto 4132 volte)

Offline teskio

  • Moderatore globale
  • Utente normale
  • *****
  • Post: 387
  • Respect: +118
    • Github
    • Google+
    • Mostra profilo
    • Skullab
  • Dispositivo Android:
    Cubot GT99 / SurfTab Ventos 10.1
  • Play Store ID:
    Skullab Software
  • Sistema operativo:
    windows 7 / ubuntu 12.04
[facile] Creare un menu con le ViewStub
« il: 20 Marzo 2011, 11:02:54 CET »
+7
Livello di difficoltà: facile
Target SDK: 4
Min SDK: 3
Link al file compresso del progetto eclipse:
direct - ViewStub_tutorial.rar
mirror 1 - ViewStub_tutorial.rar
mirror 2 - ViewStub_tutorial.rar



Ciao a tutti, ho deciso che volevo ricreare un piccolo menu custom prendendo ispirazione da un quesito apparso in questo post : menu tipo quello di maps - Android Developers Italia
E quello che ne è uscito è questo menu con sfondo trasparente :



Dato che sono riuscito nell’intento utilizzando come prefissatomi una ViewStub invece che una ulteriore Activity sovrapposta, ho deciso di scrivere questo tutorial per condividere questa metodologia, magari può tornare utile a qualcuno !

Pronti ? Si Parte !

Ok, prima di tutto creiamo un nuovo progetto con Eclipse.
Il Manifest non subirà cambiamenti particolari quindi tralasciamo la sua visualizzazione e analizziamo invece il layout dell’Activity principale.

Sorgenti:
stubs.xml
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

        <LinearLayout android:layout_width="fill_parent"
                android:layout_height="fill_parent" android:orientation="vertical"
                android:gravity="center">
                <EditText android:layout_width="fill_parent"
                        android:layout_height="wrap_content" />
                <Button android:layout_width="wrap_content"
                        android:layout_height="wrap_content" android:text="Click...but do nothing" />
        </LinearLayout>

        <ViewStub android:id="@+id/stub_menu" android:inflatedId="@+id/panel_menu"
                android:layout="@layout/menu" android:layout_width="fill_parent"
                android:layout_height="fill_parent" android:layout_gravity="top" />

</merge>

La prima cosa che salta all’occhio direi è l’utilizzo del tag <merge>
Cos’è ? A cosa serve ? Il tag <merge> è stato creato per ridurre il numero di livelli nella gerarchia delle Views, sembra un po’ ostica da capire come cosa, ma vedendolo in azione si intuisce meglio il suo scopo. In altre parole, basta pensare che ogni View, e quindi ogni Layout, è figlio di un’altra View (o Layout) e difatti quando si crea un XML layout bisogna specifare un root Layout, che verrà istanziato poi al momento di generare il codice Java corrispondente dalla classe LayoutInflater. In questo caso però, quando il LayoutInflater incontrerà il tag <merge> non creerà una nuova istanza di un Layout ma non farà altro che unire la nostra View alla top-level View, cioè alla View di alto livello già istanziata. Comunque per altri chiarimenti vi rimando alla bibliografia in fondo al tutorial. Un altro motivo per cui ho utilizzato il tag <merge> è per poter sovrapporre le due View del layout, che sono il LinearLayout e, per l’appunto, la nostra ViewStub !
Il LinearLayout comprende una EditText e un Button, che ho messo a puro scopo indicativo, mentre vorrei soffermarmi un po’ sulla ViewStub, anche perché è il motivo di questo tutorial !

Analizzando la ViewStub

La ViewStub è una View che non ha dimensioni, non viene disegnata e che quindi non viene considerata in nessun modo all’interno del nostro layout. In pratica l’unica cosa che facciamo è dichiarare la sua esistenza per poterla poi usare in seguito quando ne avremo bisogno ! Il beneficio di usare una ViewStub è quello di non appesantire il sistema nella creazione di nuovi elementi a runtime, un po’ come la tecnica del lazy loading delle immagini,che spopola nel progettazione Web 2.0

Gli attributi della ViewStub

Quello che ci serve per dichiarare una ViewStub è un android:id, cioè l’identificativo della ViewStub stessa, e un android:layout, che non è altro che il riferimento al file XML contenente il layout che andrà a “popolare” la ViewStub. Un terzo attributo è l’android:inflateId, cioè l’identificativo del file XML contenente il layout (quello specificato prima). Per il resto, larghezza e altezza ecc.. sono i classici attributi che ritroviamo nella creazione dei layout. Nel caso specifico, ho settato come android:layout_gravity il valore top, in modo da posizionare la ViewStub in alto nello schermo.
Ok direi che per ora può bastare, vedremo successivamente come gestire la ViewStub all’interno dell’Activity. Per ulteriori informazioni vi rimando alla bibliografia in fondo a questo tutorial.

Il layout del menu

Quello di seguito altro non è che il layout XML del menu vero e proprio, quello che sarà dichiarato nell’attributo android:layout della ViewStub

Sorgenti:
menu.xml
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent" android:layout_height="fill_parent"
        android:background="#99000000">
        <LinearLayout android:layout_width="fill_parent"
                android:layout_height="wrap_content" android:padding="20dp"
                android:orientation="horizontal" android:gravity="center"
                android:background="#888">
                <Button android:id="@+id/button_1"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" android:text="Button 1" />
                <Button android:id="@+id/button_2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" android:text="Button 2" />
                <Button android:id="@+id/button_3"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" android:text="Button 3" />
        </LinearLayout>
</LinearLayout>

Molto semplice, due LinearLayout, uno dentro l’altro. Il secondo è quello che contiene i 3 pulsanti di esempio, mentre il primo è il nostro root Layout !
Ed ecco il trick  :-P. Nel primo LinearLayout ho settato come attributo android:background il valore “#99000000” , il quale darà il nostro tocco di stile al menu, rendendo lo sfondo trasparente (o traslucente). Ma cosa sono quei numeri ? Non è altro che il riferimento ad un colore del tipo rgb con una componente alpha-transparency, in pratica i primi due numeri -99- definiscono la alpha-transparency (a), i seguenti 2 numeri -00- la componente red (r), i successivi -00- il green (g) e infine gli ultimi due -00- il blue (b). Tradotto, ho settato lo sfondo del LinearLayout con il colore nero e un grado di trasparenza pari a 99. Provate a variare i primi due numeri (da 00 a 99) per vedere le varie differenze di trasparenza.

L’Activity principale

Ed eccoci finalmente al codice dell’Activity principale (nonché l’unica del tutorial).

Sorgenti:
StubActivity.java
Codice (Java): [Seleziona]
public class StubActivity extends Activity {
        /** Called when the activity is first created. */
        private View menu;

        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.stubs);
                menuInit();
        }

        private void menuInit() {
                menu = ((ViewStub) findViewById(R.id.stub_menu)).inflate();
                menu.setVisibility(View.GONE);
                Button b1 = (Button) menu.findViewById(R.id.button_1);
                b1.setOnClickListener(new OnClickListener() {

                        @Override
                        public void onClick(View arg0) {
                                Toast.makeText(getApplicationContext(),
                                                "Click on Button 1",
                                                Toast.LENGTH_SHORT).show();
                        }

                });
                Button b2 = (Button) menu.findViewById(R.id.button_2);
                b2.setOnClickListener(new OnClickListener() {

                        @Override
                        public void onClick(View arg0) {
                                Toast.makeText(getApplicationContext(),
                                                "Click on Button 2",
                                                Toast.LENGTH_SHORT).show();
                        }

                });
                Button b3 = (Button) menu.findViewById(R.id.button_3);
                b3.setOnClickListener(new OnClickListener() {

                        @Override
                        public void onClick(View arg0) {
                                Toast.makeText(getApplicationContext(),
                                                "Click on Button 3",
                                                Toast.LENGTH_SHORT).show();
                        }

                });
        }

        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
                switch (keyCode) {
                case KeyEvent.KEYCODE_MENU:
                        int visibility = menu.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE;
                        menu.setVisibility(visibility);
                        break;
                case KeyEvent.KEYCODE_BACK:
                        if (menu.getVisibility() == View.VISIBLE) {
                                menu.setVisibility(View.GONE);
                        } else
                                this.finish();
                        break;
                default:
                        break;
                }
                return false;
        }

}

Come sempre, creiamo una classe che estende Activity e settiamo la View principale con il file stubs.xml, dopodiché inizializziamo il menu.
Ho creato il metodo menuInit() proprio per fare questo, vediamo cosa fa.

Codice (Java): [Seleziona]
menu = ((ViewStub) findViewById(R.id.stub_menu)).inflate();
Ecco il tassello mancante per l’utilizzo delle ViewStub. Il metodo inflate() inserisce di fatto la ViewStub all’interno del nostro layout, restituendo il riferimento alla View che contiene il layout del menu. Da questo momento la View diventa visibile a tutti gli effetti, ecco perché con la successiva riga di codice

Codice (Java): [Seleziona]
menu.setVisibility(View.GONE);
Rimuovo la View da flusso delle View visibili a schermo, perché per il momento il menu non deve essere visibile.
Ora che abbiamo il riferimento alla View del menu, possiamo interagire con i componenti che la popolano. Nello specifico, è stato assegnato un OnClickListener ai 3 pulsanti del menu, i quali al loro click faranno apparire a video un messaggio.

Gestire il menu sull’onKeyDown

Ora che il menu è inizializzato possiamo mostrarlo e renderlo fruibile. In questo tutorial ho deciso di farlo apparire alla pressione del tasto menu del device (ma guarda il caso… :-)) ma nulla vieta di gestirlo diversamente. Il codice non è ottimizzato al massimo, ma d’altronde è solo un esempio.
Con queste righe di codice

Codice (Java): [Seleziona]
int visibility = menu.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE;
menu.setVisibility(visibility);

Rendo visibile o meno il menu alla pressione del tasto menu.
Dato che stiamo facendo l’override del metodo onKeyDown dell’Activity, il tasto “indietro” del device sarà ora inutilizzabile, quindi andiamo a gestire anche questo, per poter permettere l’uscita dall’applicazione nel modo tradizionale, e già che ci siamo aggiungiamo un altro tocco di stile al nostro menu, nascondendolo anche alla pressione del suddetto tasto

Codice (Java): [Seleziona]
if (menu.getVisibility() == View.VISIBLE) {
menu.setVisibility(View.GONE);
} else this.finish();

E con questo è tutto, abbiamo realizzato un menu con sfondo trasparente con il solo ausilio delle ViewStub. In questo modo l’app risulta notevolmente meno appesantita, il nostro codice è modulare e la nostra ViewStub è riusabile per altri progetti.
Ovviamente si possono usare le ViewStub per aggiungere altri elementi, non solo per creare dei menu, ma ad esempio per mostrare una progress bar quando si effettua un download, rimuovendola quando il downlaod è terminato, insomma il limite è la vostra inventiva :-P
Spero che il tutorial sia stato chiaro e utile a qualcuno, alla prossima !

Bibliografia:
« Ultima modifica: 20 Marzo 2011, 20:14:56 CET da teskio »

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3489
  • Respect: +507
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:[facile] Creare un menu con le ViewStub
« Risposta #1 il: 20 Marzo 2011, 13:06:44 CET »
0
Grazie, tutorial molto interessante :)

Offline JD

  • Amministratore
  • Utente storico
  • *****
  • Post: 1600
  • Respect: +232
    • leinardi
    • Mostra profilo
  • Dispositivo Android:
    LG Nexus 5
  • Sistema operativo:
    L'ultima Ubuntu
Re:[facile] Creare un menu con le ViewStub
« Risposta #2 il: 20 Marzo 2011, 13:12:26 CET »
0
Ciao teskio, complimenti per il tutorial, serviva proprio qualcosa su ViewStubs e Merge :)

Ho solo un piccolo problema: stranamente non riesco a scaricare il file dei sorgenti ne con Chrome ne con Firefox, è solo un problema mio/temporaneo?
È stata trovata una soluzione al tuo problema?
Evidenzia il post più utile premendo . È un ottimo modo per ringraziare chi ti ha aiutato ;).
E se hai aperto tu il thread marcalo come risolto cliccando !

Offline teskio

  • Moderatore globale
  • Utente normale
  • *****
  • Post: 387
  • Respect: +118
    • Github
    • Google+
    • Mostra profilo
    • Skullab
  • Dispositivo Android:
    Cubot GT99 / SurfTab Ventos 10.1
  • Play Store ID:
    Skullab Software
  • Sistema operativo:
    windows 7 / ubuntu 12.04
Re:[facile] Creare un menu con le ViewStub
« Risposta #3 il: 20 Marzo 2011, 20:17:36 CET »
0
@JD
Grazie della segnalazione. Il link a me funziona, però non faccio testo dato che devono scaricarlo gli altri :-P, quindi ho aggiunto dei mirror da dove poter scaricare il progetto eclipse. Spero che almeno quelli funzionino.  :-)

Offline Nicola_D

  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:[facile] Creare un menu con le ViewStub
« Risposta #4 il: 20 Marzo 2011, 23:26:40 CET »
0
mmm stavo pensando di usare questa tecnica come "popup" per il login via facebook nella mia app.. al momento uso un'activity con tema dialog, ma non mi piace molto...
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia