Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

ViewPager e le Tab

Implementare un'app seguendo una struttura di interfaccia tipicamente utilizzata su Android: una navigazione laterale basata su ViewPage e Tab.
Implementare un'app seguendo una struttura di interfaccia tipicamente utilizzata su Android: una navigazione laterale basata su ViewPage e Tab.
Link copiato negli appunti

In questa lezione inizieremo a costruire un piccolo news reader, che utilizzeremo come esempio pratico per mostrare i più comuni elementi utilizzati oggigiorno nelle interfacce Android. Affronteremo per prima cosa l'architettura della UI su cui si basa l'applicazione, e ne vedremo una tipologia molto diffusa e particolarmente adatta al nostro scopo: Tabs sfogliabili mediante ViewPager.

Contenuti dell'applicazione

Prima di introdurre la struttura dell'applicazione, faremo una premessa sui contenuti che essa gestirà. Per fare in modo che il lettore possa concentrarsi sugli aspetti visuali ed interattivi della UI, i contenuti non verranno reperiti realmente in rete, ma saranno forniti da una classe di nome DataProvider. Quella che segue è la sua struttura:

public class DataProvider
{
	public static final String CATEGORY="CATEGORY";
	public static final String COOKING_CATEGORY="CUCINA";
	public static final String TECH_CATEGORY="TECH";
	public static final String GREEN_CATEGORY="GREEN";
	private static final String[] CATEGORY_ORDER=new String[]{COOKING_CATEGORY,GREEN_CATEGORY,TECH_CATEGORY};
	public static class Content
	{
		private String title;
		private String description;
		// OMISSIS: getter e setter dei metodi privati
	}
	private static HashMap<String,ArrayList<Content>> contents;
	static
	{
		// OMISSIS: inizializzazione statica di contents
	}
	public static List<Content> getContentsByCategory(String category)
	{
		return contents.get(category);
	}
	public static String getCategoryByIndex(int index)
	{
		return CATEGORY_ORDER[index];
	}
	public static int getCatoriesCount()
	{
		return contents.entrySet().size();
	}
}

La classe contiene e distribuisce oggetti di tipo Content che rappresentano singole notizie. Content, a sua volta, è annidata in DataProvider ed al suo interno ha solo due membri privati: title che rappresenta il titolo della notizia, e description che contiene un breve testo che la descrive.

La struttura dati è una HashMap che abbiamo chiamato contents: essa utilizza il nome di una categoria di notizie (in forma di stringa) come chiave, mentre i valori sono ArrayList di notizie.

Gli altri metodi servono di conseguenza, per l'estrazione degli oggetti Content.

Struttura dell'applicazione

In base ai concetti illustrati in precedenza riguardo alla navigazione interna all'applicazione, consideriamo la nostra app suddivisa su tre livelli:

  • a livello globale, ci sono le categorie delle notizie che verranno navigate lateralmente. Ogni categoria corrisponderà ad una Tab e, contemporaneamente, ad una pagina del ViewPager;
  • ogni categoria mostra le notizie che la riguardano. Tale flusso sarà un altro caso di navigazione laterale con Adapter e lo implementeremo con il ListFragment che vedremo tra poco;
  • ogni notizia elencata all'interno della categoria potrà essere selezionata, e la sua descrizione verrà mostrata in un'Activity a parte. Ciò significa che implementeremo una navigazione discendente, che approfondiremo nelle prossime lezioni.

I Fragment

Un Fragment può essere considerato come una "piccola Activity". È un modulo all'interno del quale possiamo specificare un layout e le funzionalità di gestione principali. Ha un suo ciclo di vita ma non è una componente di sistema indipendente, tanto che ha bisogno sempre di essere inserito in un'Activity.

Utilizzeremo i Fragment per rappresentare ogni scheda che vogliamo incorporare nell'interfaccia utente. Visto che la scheda dovrà contenere tutti gli articoli di una categoria, ci farebbe comodo assegnarle un layout dotato di ListView. Tuttavia ciò non sarà necessario poichè sfrutteremo una tipologia speciale di Fragment, il ListFragment, che nasce già dotato di una ListView al suo interno. Si consideri - come spunto di riflessione - che, al posto della ListView, si potrebbe usare una RecyclerView, che abbiamo conosciuto nelle scorse lezioni. Nell'esempio tuttavia si è preferito il widget più tradizionale, data la sua ampia diffusione di utilizzo.

public class ContentFragment extends ListFragment
{  
	@Override
	public void onListItemClick(ListView lv, View view, int position, long id)
	{
		/*
		 * azione collegata al click sulla singola voce mostrata.
		 * Per il momento la lasciamo vuota
		 */
	}
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
	{
		Bundle b = getArguments();
		String category = (String) b.get(DataProvider.CATEGORY);
		ArrayAdapter<Content> adapter = new ArrayAdapter<Content>(
			inflater.getContext(), android.R.layout.simple_list_item_1,
			DataProvider.getContentsByCategory(category));
		setListAdapter(adapter);
		return super.onCreateView(inflater, container, savedInstanceState);
	}
}

ViewPager e le Tab

ll ViewPager viene fissato direttamente nel layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
<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.TabLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tablayout"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
</LinearLayout>

La logica di gestione dei Fragment in questo esempio si basa sempre sul concetto di Adapter. Creeremo infatti una classe PageAdapter, estensione di FragmentPagerAdapter:

public class PagerAdapter extends FragmentPagerAdapter { 
    public PagerAdapter(FragmentManager manager)
    {
        super(manager);
    } 
    @Override
    public Fragment getItem(int index) {
    	Bundle b=new Bundle();
    	ContentFragment fragment=null;
    	String category=DataProvider.getCategoryByIndex(index);
    	b.putString(DataProvider.CATEGORY,category);
    	fragment=new ContentFragment();
    	fragment.setArguments(b); 
        return fragment;
    } 
    @Override
    public int getCount()
    {
        return DataProvider.getCatoriesCount();
    } 
    @Override
    public CharSequence getPageTitle(int position) {
        return DataProvider.getCategoryByIndex(position);
    }
}

Nel metodo onCreate dell'Activity verrà prima istanziato un PageAdapter, che subito verrà assegnato al ViewPager con il metodo setAdapter:

mAdapter = new PagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mAdapter);

Affinchè il ViewPager e le Tab possano convivere nella stessa Activity e condividere gli stessi Fragment, è necessario che si scambino a vicenda le informazioni sul proprio stato. Il widget TabLayout, appartenente alla Android Design Support Library, tramite il metodo setupWithViewPager, viene agganciato alla ViewPager. In questa maniera, potremo consultare le Tab cliccandone il titolo o sfogliandole con lo swipe.

public class MainActivity extends AppCompatActivity
{ 
    private ViewPager mViewPager;
	private PagerAdapter mAdapter; 
	@Override
    protected void onCreate(Bundle savedInstanceState)
    {
		super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main); 
        final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        toolbar.setSubtitle("Creazione di un NewsReader"); 
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mAdapter = new PagerAdapter(getSupportFragmentManager()); 
        mViewPager.setAdapter(mAdapter);
        getSupportActionBar().setDisplayHomeAsUpEnabled(false); 
        TabLayout tabLayout = (TabLayout) findViewById(R.id.tablayout);
        tabLayout.setupWithViewPager(mViewPager); 
    }
}

Il codice d'esempio visto fin qui è allegato a questa lezione, e liberamente scaricabile.

Ti consigliamo anche