Corso su Android – Lavorare con i Layout

titleImage

Abbiamo visto come creare  Activity e poter navigare tra queste, ma come fare a creare pagine  posizionando i componenti secondo le nostre esigenze?  Semplice, grazie ai vari tipi di Layout messi a disposizione dall'SDK. In questo articolo andremo a vedere i Layout più comunemente utilizzati utilizzando con essi solo i componenti visuali base. Nell'articolo successivo verranno approfonditi in dettaglio i vari componenti visuali.

Un layout definisce una struttura visuale per una interfaccia utente. Android separa la parte visuale dalla parte logica, utilizzando per la prima dei file xml. I componenti grafici possono essere definiti anche da codice, ma per un fatto di leggibilità e manutenzione è consigliato tenere separate le due parti.
Il file xml che rappresenta il nostro layout può essere creato manualmente o tramite strumenti grafici quali DroidDraw e il plugin di Eclipse, per esperienza preferisco scrivere a mano i vari componenti nel layout. Una volta presa la mano è abbastanza veloce.
Ogni layout contiene un solo elemento principale nel quale si possono aggiungere oggetti o widgets.

Riprendiamo il file activity_second.xml usato per la seconda Activity nel precedente tutorial ed andiamo ad analizzarne le varie parti:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
       android:text="@string/labelSecondActivity"
    />
    
    <Button
        android:id="@+id/idFinishButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/labelClose"
    />    
</LinearLayout>

Il primo elemento di un file xml deve sempre dichiarare il namespace di Android: xmlns:android=http://schemas.android.com/apk/res/android

così tutti gli altri elementi ereditano questo namespace.
Analizziamo gli attributi dei componenti utilizzati:

  • android:layout_width e android:layout_height rappresentano la larghezza e l'altezza del componente e possono assumere valori:
    • wrap_content: adatta alla dimensione del componente;
    • fill_parent: adatta il componente a tutto schermo;
    • match_parent: come fill_parent ma dalle versioni recenti di android;
  • android:orientation è un attributo che indica se i componenti all'interno del layout vengono aggiunti seguendo un allineamento orizzontale o verticale
  • android:id: indica l'id che viene utilizzato per legare la parte visuale con la parte di codice. La convenzione è di usare @+id/ che sta a significare che è un nuovo id e va aggiunto alla lista degli id nella classe R.
  • android:text: setta il testo del componente; come si vede, non è stato scritto il testo direttamente ma è stata definita una stringa ed è stata presa tramite "@string/labelClose", è consigliato mettere tutte le stringhe nel file string. In questo modo per aggiungere il supporto dell'applicazione alle altre lingue, basta aggiungere un altro file di stringhe nella lingua desiderata

Una volta definito un elemento nell'xml può essere instanziato nella classe che utilizza il layout. Per associare il componente si deve far riferimento all'id ed utilizzare il metodo findViewById(int) come mostrato di seguito:

Button btnGoToSecond = (Button)findViewById(R.id.idFinishButton);

Una volta associato il bottone, può essere utilizzato nel codice, come visto nell'esempio per intercettare l'evento del click da parte dell'utente.
Android mette a disposizione vari tipi di layout tra cui si può scegliere per realizzare l'interfaccia grafica della nostra applicazione. Andremo a vedere i seguenti layout:

  • LinearLayout;
  • RelativeLayout;
  • TableLayout;
  • ListView;
  • GridLayout.

LinearLayout

Allinea tutti i figli in una singola direzione orizzontale o verticale. Questo layout lo abbiamo utilizzato nel progetto delle Activity. Creiamo un nuovo progetto che chiameremo LayoutProject, il cui layout principale conterrà dei bottoni allineati in verticale ed alla pressione di questi andremo a visualizzare vari altri tipi di layout.

  • Dal Menu cliccare su File-->New-->Android Application Project
  • Sulla schermata inserire il nome del progetto e premere Finish.

In questo modo non verrà nè creata automaticamente un'Activity nè aggiornato il file AndroidManifest ma li andremo a definire noi. Infatti, se si espande il progetto sulla finestra Package Explorer si nota che le cartelle src e layout sono vuote.
Per prima cosa creiamo il package che deve coincidere con quello scelto al passo precedente:

  • Premere il tasto dx sulla cartella src
  • Selezionare New-->Package
  • Inserire il nome del packeage com.example.layoutproject
  • Premere Finish

Aggiungiamo ora la nuova Activity:

  • premere il tasto destro sul package appena creato
  • selezionare New-->Class
  • Immettere il nome della classe LinearLayoutActivity
  • Selezionare come superclasse android.app.Activity
  • Premere Finish

Ora dobbiamo inserire il metodo onCreate.

  • Posizioniamoci all'interno della classe e premiamo il tasto destro del mouse
  • Selesionare Source-->Override/Implements Methods…
  • Scegliere il medodo onCreate e premere Finish

Definiamo ora il file xml:

  • premere il tasto destro sulla cartella layout
  • selezionare New-->Android XML file
  • inserire il nome del file linear_layout_activity (Bisogna fare attenzione al nome del file che deve essere scritto in caratteri minuscoli)
  • selezionare come root element LinearLayout
  • premere Finish

Il file creato risulta essere:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android        = "http://schemas.android.com/apk/res/android"
    android:layout_width    = "match_parent"
    android:layout_height    = "match_parent"
    android:orientation        = "vertical" >
 </LinearLayout>

all'interno del quale, essendo il primo elemento, viene inserita la dichinarazione del namespace di Android.
Creiamo prima i file e le variabili che ci serviranno.
Nel file string.xml definiamo 5 label che verranno usate per i bottoni:

<string name="labelRelativeLayout">Relative Layout</string>
<string name="labelTableLayout">Table Layout</string>
<string name="labelListView">List view</string>
<string name="labelGridLayout">Grid Layout</string>

Creare poi il file color.xml:

  • premere il tasto destro del mouse sulla cartella values
  • selezionare New-->Android XML File
  • nella finestra che si apre nel campo Resource Type selezionare la voce Values
  • nel campo File scrivere il nome del file color.xml
  • tra i tag resouces definiamo il colore che useremo per il testo del bottone <color name="textButtonColor">#FF000000</color>
  • premere Finish

Creiamo il file dimens.xml:

  • premere il tasto destro sulla cartella values
  • selezionare New-->File
  • inserire il nome dimens.xml
  • premere Finish

Così viene creato un file vuoto, inserire il seguente codice:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="marginTopButton">5dp</dimen>
</resources>

Abbiamo così definito la dimensione che useremo per dare lo spazio ai bottoni.
Andiamo ora ad inserire 5 bottoni nel LinearLayout creato, ad ogni bottone verrà associata un'Activity con un layout diverso. L'xml risulta essere:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android        = "http://schemas.android.com/apk/res/android"
    android:layout_width    = "match_parent"
    android:layout_height    = "match_parent"
    android:orientation        = "vertical" >
    
    <Button
        android:id        = "@+id/idRelative"
        android:layout_width    = "match_parent"
       android:layout_height    = "wrap_content"
       android:gravity        = "center"
       android:text        = "@string/labelRelativeLayout"
       android:textColor    = "@color/textButtonColor"
       android:layout_marginTop = "@dimen/marginTopButton"
    />

    <Button
        android:id        = "@+id/idTable"
        android:layout_width    = "match_parent"
        android:layout_height    = "wrap_content"
        android:gravity        = "center"
        android:text        = "@string/labelTableLayout"
        android:textColor    = "@color/textButtonColor"
        android:layout_marginTop= "@dimen/marginTopButton"
    />
    
    <Button
        android:id        = "@+id/idList"
        android:layout_width    = "match_parent"
        android:layout_height    = "wrap_content"
        android:gravity        = "center"
        android:text        = "@string/labelListView"
        android:textColor    = "@color/textButtonColor"
        android:layout_marginTop= "@dimen/marginTopButton"
    />
    
    <Button
        android:id        = "@+id/idGrid"
        android:layout_width    = "match_parent"
        android:layout_height    = "wrap_content"
        android:gravity        = "center"
        android:text        = "@string/labelGridLayout"
        android:textColor    = "@color/textButtonColor"
        android:layout_marginTop= "@dimen/marginTopButton"
    />
</LinearLayout>

Il layout è formato da 5 bottoni, analizziamo gli attributi utilizzati:

  • android:id: id che useremo per associare il widget al codice java
  • android:layout_width=" match_parent": il bottone occuperà tutta larghezza dello schermo
  • android:layout_height="wrap_content": il bottone si adatta all'altezza
  • android:gravity = “center": il testo viene centrato rispetto al bottone
  • android:text="@string/labelRelativeLayout": assegna al testo del bottone quello definito nella stringa labelRelativeLayout
  • android:textColor= "@color/textButtonColor": assegna al testo il colore definito nella variabile textButtonColor
  • android:layout_marginTop="@dimen/marginTopButton":definisce il margine superiore che il bottone deve avere e il valore lo prende dalla dimensione definita nel file apposito.

Una volta definiti i file xml andiamo ad associare questi bottoni al codice java. Riprendendo la classe LinearLayoutActivity andiamo ad associare il layout creato con l’istruzione: setContentView(R.layout.linear_layout_activity);
Aggiungiamo ora le definizioni dei bottoni:

private Button btnGoToRelative = null;
private Button btnGoToTable    = null;
private Button btnGoToListView = null;
private Button btnGoToGrid     = null;

Recuperiamo i bottoni:

 btnGoToRelative    = (Button)findViewById(R.id.idRelative);

ed associamo un listener per intercettare la pressione del bottone:

btnGoToRelative.setOnClickListener(this);

Sul listener viene passato come riferimento this, questo perché vogliamo implementare il listener nella stessa Activity, quindi modifichiamo la definizione della classe come:

public class LinearLayoutActivity extends Activity implements OnClickListener

ed implementiamo il metodo onClick:

@Override
public void onClick(View v) {
    if (v == btnGoToRelative){
        Log.d(TAG,"Button RelativeLayout pressed");
    }else if (v == btnGoToTable){
        Log.d(TAG,"Button TableLayout pressed");
    }else if (v == btnGoToListView){
        Log.d(TAG,"Button ListView pressed");
    }else if (v == btnGoToGrid){
        Log.d(TAG,"Button GridLayout pressed");
    }
}

Da notare che nel metodo viene effettuato il controllo sulla view, cioè sul bottone premuto. Per ora limitiamoci ad effettuare delle "loggate", in seguito invocheremo le Activity.
Come ultima cosa, aggiungiamo l'Activity nel manifest. Di seguito vediamo come è possibile inserire un'Activity utilizzando gli strumenti messi a disposizione dall'IDE, ma si può anche tranquillamente inserire un'Activity manualmente.

  • fare doppio clic sul file AndroidManifest.xml
  • premere sul tab Application
  • premere sul bottone Add nella sezione Application Nodes
  • Selezionare Activity e premere Ok
  • Inserire il nome dell’Activity
  • Selezionare l'Activity e premere il bottone Add
  • Selezionare Intent-Filter e premere Ok

Sotto il nome dell'Activity viene inserito un Intent-Filter (come visto nel secondo articolo), quindi:

  • selezionare Intent-Filter
  • premere il bottone Add
  • Selezionare Action e premere Ok
  • Selezionare come action android.intent.action.MAIN
  • Selzionare di nuovo Intent-Filter e premere Add
  • Selezionare Category
  • Selezionare come categoria android.intent.category.LAUNCHER

Salvare il manifest ed effettuare il run del progetto; verrà visualizzata la schermata seguente con il nostro LinearLayout:

RelativeLayout

Il RelativeLayout visualizza le view in posizioni relative. Le view vengono posizionate a destra di, sotto di etc. Per capire come funziona facciamo un esempio. Vogliamo arrivare ad avere un layout come quello mostrato in figura:

Iniziamo aggiungendo il file relative_layout_activity.xml:

  • premere il tasto destro del mouse sulla cartella layout
  • selezionare New-->Android XML File
  • inserire il nome relative_layout_activity.xml
  • selezionare RelativeLayout nella sezione Root Element
  • Premere Finish

Aggiungiamo al file XML una label (TextView), due campi di testo(EditText) ed un bottone(Button):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
<TextView
        android:id              = "@+id/idDescription"
        android:layout_width    = "fill_parent"
        android:layout_height   = "wrap_content"
        android:text            = "@string/labelDescription"
    />
    <EditText
        android:id                      = "@+id/idEdName"
        android:layout_width            = "0dp"
        android:layout_height           = "wrap_content"
        android:layout_below            = "@id/idDescription"
        android:layout_alignParentLeft  = "true"
        android:layout_toLeftOf         = "@+id/idSurname"
        android:hint                    = "@string/hintName"/>
    <EditText
        android:id                      = "@id/idSurname"
        android:layout_width            = "150dp"
        android:layout_height           = "wrap_content"
        android:layout_below            = "@id/idDescription"
        android:layout_alignParentRight = "true"
        android:hint                    = "@string/hintSurname"/>
    <Button
        android:layout_width            = "96dp"
        android:layout_height           = "wrap_content"
        android:layout_below            = "@id/Surname"
        android:layout_alignParentRight = "true"
        android:text                    = "@string/labelBtnOk" />
</RelativeLayout>

Come funziona: prima di tutto, notiamo che ogni componente ha un id, questo ci serve per mettere in relazione i vari elementi. Andiamo a posizionare come prima la TextView che risulterà in testa al nostro layout.
Posizioniamo l’EditText con id "idEdName" sotto la TextView con id "idDescription android:layout_below= "@id/idDescription", posizioniamolo alla sinistra dell'EditText con id "idSurneame" definito subito dopo il nome usando l'attributo android:layout_toLeftOf= "@+id/idSurname".
Ora, andiamo ad aggiungere nel file string.xml le stringhe utilizzate nel layout:

<string name="labelDescription">Inserire Nome e Cognome</string>
<string name="hintName">Nome</string>
<string name="hintSurname">Cognome</string>
<string name="labelBtnOk">Ok</string>

Creiamo la nuova Activity come visto in precedenza dandole il nome RelativeLayoutActivity ed aggiungiamo il RelativeLayaut creato

public class RelativeLayoutActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.relative_layout_activity);
    }
}

Andiamo ad aggiungere nel manifest l'Activity appena create. Questo può essere fatto manualmente od utilizzando il plugin di Eclipse come già visto precedentemente. In entrambi i casi il risultato è di aggiungere una riga nel manifest:

<activity android:name="RelativeLayoutActivity"></activity>

Aggiorniamo ora il metodo onClick della classe LinearLayout per richiamare la seconda Activity. Come abbiamo già visto, definiamo un intent e chiamiamo il metodo startActivity(intent). Il metodo onClick risulterà essere:

@Override
    public void onClick(View v) {
        Intent intent = null;
        if (v == btnGoToRelative){
            Log.d(TAG,"Button RelativeLayout pressed");
            intent = new Intent(LinearLayoutActivity.this, RelativeLayoutActivity.class);
            startActivity(intent);
        }else if (v == btnGoToTable){
            Log.d(TAG,"Button TableLayout pressed");
        }else if (v == btnGoToListView){
            Log.d(TAG,"Button ListView pressed");
        }else if (v == btnGoToGrid){
            Log.d(TAG,"Button GridLayout pressed");
        }
    }

Effettuamio il run del progetto e premendo sul bottone con label RelativeLayout visualizzeremo all'Activity appena creata.

TableLayout

Come dice il nome, TableLayout, permette di disporre i componenti in modo tabellare.
Iniziamo con il creare un nuovo file XML, premiamo con il tasto destro sulla cartella layout-->New-->Android XM File

  • Inserire come nome table_layout_activity
  • Selezionare TableLayout
  • Premere Finish

Verrà creato il file con tag principale TableLayout.
Prima di aggiungere elementi dobbiamo precisare che ogni riga di questo layout viene indicata utilizzando il tag <TableRow>, quindi per una tabella con più righe avremo più tag.
Modifichiamo il codice nel seguente modo:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stretchColumns="*">
    
    <TableRow >
        <TextView
            android:layout_width     = "fill_parent"
            android:layout_height    = "wrap_content"
            android:text             = "@string/cell_1_1"
            android:gravity          = "center"
        />
        <TextView
            android:layout_width     = "wrap_content"
            android:layout_height    = "wrap_content"
            android:text             = "@string/cell_1_2"
            android:gravity          = "center"
        />
    </TableRow>
    
    <TableRow >
        <TextView
            android:layout_width   = "wrap_content"
            android:layout_height  = "wrap_content"
            android:text           = "@string/cell_2_2"
            android:gravity        = "center"
            android:layout_column  = "1"
        />
    </TableRow>
    
    <TableRow >
        <TextView
            android:layout_width     = "wrap_content"
            android:layout_height    = "wrap_content"
            android:text             = "@string/cell_3"
            android:gravity          = "center"
            android:layout_span      = "2"
        />
    </TableRow>
</TableLayout>

La tabella è composta da 3 righe delimitate dal tag <TableRow> e 2 colonne. Nella prima riga vengono assegnati i valori ad entrambe le celle della tabella. Nella seconda riga viene popolata solo la cella con coordinata 2,1 grazie all'attributo

android:layout_column    = "1"

Mentre con la terza riga abbiamo utilizzato l'attributo android:layout_span= "2" che permette di posizionare il componente nelle 2 celle.
Da notare l'attributo android:stretchColumns="*", questo fa in modo da effettuare lo stretch orizzontale di tutte le celle della tabella, così da fargli occupare tutto lo spazio a disposizione. Può essere fatto lo stretch anche di una singola cella mettendo al posto dell' "*" il numero della cella da espandere (ricordate che la numerazione parte da 0).
Definiamo nel file string.xml le costanti utilizzate:

<string name="cell_1_1">Cell 1_1</string>
<string name="cell_1_2">Cell 1_2</string>
<string name="cell_2_2">Cell 2_2</string>
<string name="cell_3">Cell 3 span</string>

Creiamo l'Activity TableLayoutActivity ed associamo il layout appena creato:

public class TableLayoutActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.table_layout_activity);
    }
}

Aggiungere la chiamata all'Acrivity nel metodo onClick della classe LinearLayoutActivity

@Override
public void onClick(View v) {
    Intent intent = null;
    if (v == btnGoToRelative){
        Log.d(TAG,"Button RelativeLayout pressed");
        intent = new Intent(LinearLayoutActivity.this, RelativeLayoutActivity.class);
        startActivity(intent);
    }else if (v == btnGoToTable){
        Log.d(TAG,"Button TableLayout pressed");
        intent = new Intent(LinearLayoutActivity.this, TableLayoutActivity.class);
        startActivity(intent);
    }else if (v == btnGoToListView){
        Log.d(TAG,"Button ListView pressed");
    }else if (v == btnGoToGrid){
        Log.d(TAG,"Button GridLayout pressed");
    }
}

Non ci resta che aggiungere al manifest l'Activity:

<activity android:name="TableLayoutActivity"></activity>

e lanciare l'applicazione. Il risultato sarà come in figura:

ListView

Visualizza una lista di items scrollabili. Gli items sono inseriti automaticamente utilizzando un adapter che prende i dati da un array o da un database e trasformano ogni risultato in una view da inserire nella lista. Faremo due esempi uno con un adaper standard ed uno con un adapter custom.
Come per gli altri layout posizioniamoci sulla cartella layout e premiamo il tast destro del mouse -->New-->Android XML File. Nella finestra aperta

  • inseriamo come nome listview_layout_activity
  • selezioniamo ListView nella sezione  RootElement
  • premere Finish

Al file appena creato aggiungiamo come attributo l'id: android:id= "@+id/idList"
Definiamo nel file string.xml un array che definisce i giorni della settimana che verranno passati all'adapter:

<string-array name="listOfDays">
        <item>Lunedi</item>
        <item>Martedi</item>
        <item>Mercoledi</item>
        <item>Giovedi</item>
        <item>Venerdi</item>
        <item>Sabato</item>
        <item>Domenica</item>    
    </string-array>

creiamo una nuova activity (ListViewArrayAdapterActivity);

recuperiamo il layout da utilizzare setContentView(R.layout.listview_layout_activity);

recuperiamo l'oggetto ListView ed assegnamogli l'adapter passandogli l'array definito nel file string.xml.

public class ListViewArrayAdapterActivity extends Activity {
    private ListView list    = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.listview_layout_activity);
        
        String[] days = getResources().getStringArray(R.array.listOfDays);
        
        list = (ListView)findViewById(R.id.idList);
        list.setAdapter(new ArrayAdapter<String>(this, R.layout.text_item_list, days));    }
}

Nel manifest aggiungere l'Activity creata:

<activity android:name="ListViewArrayAdapterActivity"></activity>

Ora bisogna creare il file text_item_list.xml che dovrà contenere la TextView da visualizzare sugli items della lista:

  • Premere il tasto destro sulla cartella layout
  • Selezionare New-->File (crea un file vuoto)
  • Inserire il nome del file text_item_list.xml
  • Premere Finish

Inserire il seguente codice:

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android             = "http://schemas.android.com/apk/res/android"
    android:layout_width         = "match_parent"
       android:layout_height    = "match_parent"
       android:paddingTop    = "5dp"
       android:paddingBottom    = "5dp"
/>

Aggiungere l'invocazione alla classe nel metodo onClick della classe LinearLayoutActivity:

@Override
public void onClick(View v) {
    Intent intent = null;
    if (v == btnGoToRelative){
        Log.d(TAG,"Button RelativeLayout pressed");
        intent = new Intent(LinearLayoutActivity.this, RelativeLayoutActivity.class);
        startActivity(intent);
    }else if (v == btnGoToTable){
        Log.d(TAG,"Button TableLayout pressed");
        intent = new Intent(LinearLayoutActivity.this, TableLayoutActivity.class);
        startActivity(intent);
    }else if (v == btnGoToListView){
        Log.d(TAG,"Button ListView pressed");
        intent = new Intent(LinearLayoutActivity.this, ListViewArrayAdapterActivity.class);
        startActivity(intent);
    }else if (v == btnGoToGrid){
        Log.d(TAG,"Button GridLayout pressed");
    }
}

Effettuare il run del progetto, sulla lista premendo sul bottone listView  va sulla schermata con la lista appena creata:

Ora che abbiamo visto come creare una semplice lista passandogli un ArrayAdapter vediamo come recuperare la scelta effettuata dall'utente (per esempio viene selezionato il giorno x) e come associare creare una ListView passandogli un adapter custom. Realizzeremo questo creando una nuova activity che verrà visualizzata premendo sul primo elemento della lista (lunedi).
Partiamo con il creare il layout che utilizzeremo per visualizzare le righe della lista. Come fatto in precedenza, creiamo il file text_item_list_custom.xml

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android             = "http://schemas.android.com/apk/res/android"
        android:layout_width      = "match_parent"
        android:layout_height     = "wrap_content"
        android:orientation       = "horizontal"
        android:layout_marginTop  = "10dp"
        android:paddingBottom     = "10dp"
        android:paddingTop        = "10dp"
        android:paddingLeft       = "5dp"
        android:layout_gravity    = "center"
    >
        <ImageView
              android:id             = "@+id/idImage"
              android:layout_width   = "wrap_content"
              android:src            = "@drawable/ic_launcher"
              android:layout_height  = "wrap_content"
              android:layout_gravity = "center"
        />
          <TextView
              android:id             = "@+id/idText"
              android:layout_width   = "match_parent"
              android:layout_height  = "wrap_content"
          />
 </LinearLayout>

Creiamo un nuovo package dove andremo a creare l'adapter:

  • premere con il tasto destro sulla cartella src
  • selezionare New-->Package
  • inserire il nome: com.example.layoutproject.adapter
  • premere il tasto destro del mouse sul package
  • selezionare New-->Class
  • inserire come nome CustomAdapter
  • inserire come superclasse android.widget.BaseAdapter
  • premere Finish

Viene creata la struttura della classe con i metodi obbligatori che devono essere implementati. Vediamo come modificare la classe per i nostri scopi.
Creiamo un costruttore a cui viene passato il context ed inizializziamo un LayoutInflater che permette di instanziare un layout all'interno di una determinata View:

public CustomAdapter(Context context){
    inflater = LayoutInflater.from(context);
}

Definiamo nello stesso file la classe ViewValues che conterrà un solo valore che assoceremo con la TextView contenuta nel file text_item_list_custom.xml

static class ViewValues {
        TextView value;
    }

Implementiamo il costruttore

public CustomAdapter(Context context){
        inflater     = LayoutInflater.from(context);
        items        = new String[]{"Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno",
                                "Luglio","Agosto","Settembre", "Ottobre", "Novembre", "Dicembre"};
    }

Ora andiamo a modificare i metodi implementati dal plug-in:
il metodo getCount restituisce il numero di elementi della lista quindi andiamo a ritornare la lunghetta degli elementi nell'array items.

@Override
public int getCount() {
    return items.length;
}

Il metodo getItem restituisce l'elemento in una determinata posizione

@Override
public Object getItem(int position) {
    return items[position];
}

Il metodo getItemId ritorna il "row id" associato ad una specifica posizione nella lista. Per ora non lo utilizziamo lasciamo che ritorna a zero.

@Override
public long getItemId(int position) {
    return 0;
}

Il metodo getView costruisce la view da visualizzare all'interno di una riga. Grazie all'inflater viene inserito il layout, poi viene recuperato il componente TextView e gli viene assegnato il testo preso dall'array items. Questi metodi vengono chiamati in automatico da Android per popolare una lista, noi dobbiamo solo implementarli.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewValues values = null;
        
    if (convertView == null) {
        values = new ViewValues();
        convertView = inflater.inflate(R.layout.text_item_list_custom, null);
        values.value         = (TextView)convertView.findViewById(R.id.idText);
            
        convertView.setTag(values);
    }
    else {
        values = (ViewValues) convertView.getTag();
    }
        
    values.value.setText( (String)items[position]);
    return convertView;
}

Creiamo l'Activity ListViewCustomAdapterActivity utilizzando lo stesso layout listview_layout_activity per la lista e instanziando il CustomAdapter

public class ListViewCustomAdapterActivity extends Activity {
    private ListView list    = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.listview_layout_activity);
        
        list = (ListView)findViewById(R.id.idList);
        list.setAdapter(new CustomAdapter(this));
    }
}

Inseriamo nel manifest l'Activity create.
Torniamo alla classe ListViewArrayAdapterActivity, perché vogliamo passare alla nuova Activity dopo aver premuto il primo valore della lista, quindi andiamo ad implementare il metodo per intercettare quale elemento della lista è stato premuto:

protected void onCreate(Bundle savedInstanceState) {
        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.listview_layout_activity);
        
        String[] days = getResources().getStringArray(R.array.listOfDays);
        
        list = (ListView)findViewById(R.id.idList);
        list.setAdapter(new ArrayAdapter<String>(this, R.layout.text_item_list, days));
        list.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int position,
                    long arg3) {
                if ( position == 0){
                    Intent intent = new Intent(ListViewArrayAdapterActivity.this, ListViewCustomAdapterActivity.class);
                    startActivity(intent);
                }
                
            }
        });
    }

GridLayout

Visualizza gli elementi in una griglia in due dimensioni. Faremo visualizzare delle immagini e alla pressione di queste verrà visualizzata la posizione con un Toast.
Come prima cosa creiamo il file grid_layout_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/gridview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:columnWidth="90dp"
    android:numColumns="auto_fit"
    android:verticalSpacing="10dp"
    android:horizontalSpacing="10dp"
    android:stretchMode="columnWidth"
    android:gravity="center"
    >
</GridView>

Creiamo la classe CustomGridAdapter nello stesso package di CustomAdapter estendendo sempre BaseAdapter e, come in precedenza, verranno creati i metodi obbligatori da implementare.

La classe risulta essere:

public class CustomGridAdapter extends BaseAdapter {

    private Context context    = null;
    
    private Integer[] imgIds = {
            R.drawable.img0, R.drawable.img1,
            R.drawable.img2, R.drawable.img3,
            R.drawable.img4, R.drawable.img5,
            R.drawable.img6, R.drawable.img7,
            R.drawable.img8, R.drawable.img9
    };

    public CustomGridAdapter(Context context){
        this.context = context;
    }
    
    @Override
    public int getCount() {
        return imgIds.length;
    }

    @Override
    public Object getItem(int position) {
        return imgIds[position];
    }

    @Override
    public long getItemId(int position) {
    
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {  // if it's not recycled, initialize some attributes
            imageView = new ImageView(context);
            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8, 8, 8, 8);
        } else {
            imageView = (ImageView) convertView;
        }

        imageView.setImageResource(imgIds[position]);
        return imageView;
}

Dove imgIds è un array contenente gli id delle immagini che andremo ad utilizzare, il metoto getCount ritorna il numero di elementi nella griglia e il metodo getItem ritorna l'elemento in posizione "position" della lista.
Aggiungiamo ora le immagini sotto la cartella drawable.
Andiamo a creare l'activity GridViewActivity come visto precedentemente, da cui andremo a richiamare l'adapeter per popolare la grid

public class GridViewActivity extends Activity {
    private GridView gridview    = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.grid_layout_activity);
        
        gridview = (GridView) findViewById(R.id.gridview);

        gridview.setAdapter(new CustomGridAdapter(this));
        gridview.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                Toast.makeText(GridViewActivity.this, "" + position, Toast.LENGTH_SHORT).show();
            }
        });

    }
}

Nel metodo onClick della classe LinearLayoutActivity inserire l'intent per il passaggio alla nuova activity

intent = new Intent(LinearLayoutActivity.this, GridViewActivity.class);
startActivity(intent);

Non dimentichiamoci di definire l'Activity nel manifest e poi effettuare il run del progetto.

<activity android:name="GridViewActivity"></activity>

Alla prossima.

Per ogni dubbio o domanda, resto a vostra disposizione nei commenti.

Allegati

LayoutProject

imgsgridlayout

 

Quello che hai appena letto è un Articolo Premium reso disponibile affinché potessi valutare la qualità dei nostri contenuti!

 

Gli Articoli Tecnici Premium sono infatti riservati agli abbonati e vengono raccolti mensilmente nella nostra rivista digitale EOS-Book in PDF, ePub e mobi.
volantino eos-book1
Vorresti accedere a tutti gli altri Articoli Premium e fare il download degli EOS-Book? Allora valuta la possibilità di sottoscrivere un abbonamento a partire da € 2,95!
Scopri di più

Leave a Reply

Raspberry Pi 3 GRATIS! (Win10 compatibile)

Fai un abbonamento Platinum (EOS-Book + Firmware), ricevi in OMAGGIO la RASPBERRY 3, inviaci il tuo progetto e OTTIENI IL RIMBORSO