In un capitolo precedente abbiamo spiegato come la navigazione discendente tra i contenuti di un'applicazione permetta di passare da un elenco di elementi ad una schermata di dettaglio di uno di questi. La pagina di dettaglio viene spesso implementata con una nuova Activity, la cui chiusura riporterà l'utente alla pagina precedente (solitamente definita parent Activity).
Questa parte di navigazione “all'indietro” (che riporta l'utente alla parent Activity) può assumere due forme, comunemente chiamate UP e BACK.
La figura seguente come queste due possibilità si presentano in un'interfaccia:
La navigazione BACK (lato sinistro dell'immagine precedente) consiste nella pressione del pulsante “back” presente sia in forma hardware (praticamente in tutti i dispositivi) che in forma software, come quello in figura. Il senso della navigazione BACK è strettamente cronologico: essa mostra l'ultima pagina visualizzata prima dell'attuale, indipendentemente da quale sia il legame logico tra i contenuti in essa mostrati.
La navigazione UP è un'idea più recente, e l'inizio della sua diffusione coincide con l'introduzione dell'ActionBar. Il lato destro della figura precedente mostra un indicatore di esempio che può attivare la navigazione UP (la freccia alla sinistra del titolo).
Questo tipo di navigazione all'indietro non ha un carattere “storico” bensì logico: rappresenta il passaggio da un livello di contenuti più dettagliato ad uno di livello più generico, di più alto livello.
Quindi, mentre la navigazione UP è deliberatamente attivata dal programmatore, la navigazione BACK è innescata dall'esistenza di un pulsante “Indietro” del dispositivo. Mentre una corretta implementazione della prima è di fondamentale importanza per una buona navigazione nell'app, la seconda può dare adito ad effetti inaspettati e pertanto va sempre considerata in fase di progettazione dell'interfaccia.
Definire la navigazione
Per potere implementare la navigazione UP sarà necessario che ad ogni Activity ne corrisponda un'altra che svolga il ruolo di parent. In questo modo sarà possibile far sì che, navigando UP, l'applicazione tornerà dall'Activity corrente alla sua parent Activity.
Sarà quindi necessario seguire i seguenti passaggi:
-
per ogni Activity, ne definiamo una di livello parent. Per farlo dobbiamo apportare una modifica al nodo
<activity>
nel file manifest. Se si sta programmando per Android 4.1 o superiore (API di livello minimo: 16) è sufficiente indicare la classe della parent Activity nell'attributoparentActivityName
. Per le versioni 4.0 o inferiori, si dovrà aggiungere un nodo<meta-data>
come il seguente:
<meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.example.myfirstapp.MainActivity" />
-
la navigazione UP deve essere abilitata invocando il metodo
setDisplayHomeAsUpEnabled
.
L'esempio
Nel capitolo precedente abbiamo iniziato a definire l'architettura di un semplice news reader, basata su Tabs dell'ActionBar e ViewPager. Ogni pagina di queste strutture mostra un elenco di titoli di articoli.
In questa lezione, ne modificheremo il codice in modo tale che:
- selezionando il titolo di un articolo si apra una nuova Activity che ne mostri i contenuti;
- tale Activity è configurata affinchè si possa richiederle la navigazione UP, che riporterà l'utente a visualizzare l'Activity principale.
La prima modifica da apportare riguarda la creazione della nuova Activity, chiamata DetailActivity
:
public class DetailActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
getActionBar().setDisplayHomeAsUpEnabled(true);
Intent i = getIntent();
String title = i.getStringExtra("TITLE");
String text = i.getStringExtra("TEXT");
TextView txt = (TextView) findViewById(R.id.title);
txt.setText(title);
txt = (TextView) findViewById(R.id.text);
txt.setText(text);
}
}
Il codice dell'Activity è piuttosto semplice. Incorpora un layout (/res/layout/activity_detail.xml) così fatto:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"/>
</android.support.design.widget.AppBarLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/title"
android:background="?attr/colorPrimaryDark"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:textSize="15sp"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="3dp"
android:id="@+id/text"
/>
</LinearLayout>
Nel metodo onCreate
dell'Activity notiamo la riga seguente:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Eseguendo il metodo setDisplayHomeAsUpEnabled
, l'Activity sarà dotata di navigabilità UP. Per specificare la destinazione del passo a ritroso, è necessario impostare il parametro android:parentActivity
nella dichiarazione della DetailActivity nel file manifest:
<activity android:name=".DetailActivity"
android:parentActivityName=".MainActivity"/>
Infine, l'invocazione dell'Activity verrà effettuata tramite l'override del metodo onListItemClick
del ListFragment
usato come classe base per le pagine del ViewPager:
public class ContentFragment extends ListFragment
{
private ArrayAdapter adapter=null;
@Override
public void onListItemClick(ListView lv, View view, int position, long id)
{
Content c=adapter.getItem(position);
Intent i=new Intent(getActivity(),DetailActivity.class);
i.putExtra("TITLE", c.getTitle());
i.putExtra("TEXT", c.getDescription());
getActivity().startActivity(i);
}
// ...
}