androidfragment

Android SDK, Fragment

I Fragment sono oggetti molto simili alle Activity, solo che possono essere inseriti e rimossi dinamicamente, e possono esserne presenti più di uno nella stessa schermata.

Come inserire Fragment

Un modo per usare i Fragment è quello di creare un layout XML apposito: res/layout/news_article.xml e il suo elemento root sia <FrameLayout>:

<?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

    </FrameLayout>

questo elemento sarà il contenitore dei frammenti che saranno aggiunti programmaticamente.
C’è anche la possibilità di creare layout con frammenti per mezzo di XML, ma non sarà possibile poi modificarlo dinamicamente.

Per inserire questo layout nell’ Activity, usare il comando setContentView:

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_articles);
    ....

Per riempire il FrameLayout si opera in questo modo:

  • si prende il FragmentManager dell’ Activity in cui si trova il layout
  • si inizia una transazione
  • si eseguono le operazioni (add, replace, remove)
  • si fa il commit

ad esempio:

FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_container, headerFragment, "headerFragment").commit();

La funzione FragmentTransaction.add(int containerViewId, Fragment fragment, String tag) ha 3 parametri:

  1. un int per l’ id del container
  2. un Fragment da inserire: può anche essere una sottoclasse con metodi sovraccarichi
  3. una Stringa per identificare il frammento per recuperarlo in seguito con FragmentManager.findFragmentByTag(String)

Sostituire Fragment

Si opera come per aggiungere un Fragment, con l’ aggiunta di un nuovo comando: transaction.addToBackStack(null); che serve a salvare nel BackStack il frammento rimosso; il BackStack è gestito dall’ Activity e permette all’ utente di tornare al precedente stato premendo il tasto “back”.

Esempio:

// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

Comunicazione tra diversi Fragment

E’ possibile stabilire una comunicazione bidirezionale tra un’ attività contenitrice e i suoi frammenti.
Un modo per realizzarla è quello di definire una interfaccia di callback nel frammento, e costringere l’ attività ad implementarla.
Quando l’ attività riceve il callback attraverso l’ interfaccia, può convididere informazioni con altri frammenti del layout.

Esempio di comunicazione Fragment-Activity

public class HeadlinesFragment extends ListFragment {
    OnHeadlineSelectedListener mCallback;

    // Container Activity must implement this interface
    public interface OnHeadlineSelectedListener {
        public void onArticleSelected(int position);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        
        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnHeadlineSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }
    ...
}

Il precedente Fragment (è un ListFragment, una sua sottoclasse) ha una dichiarazione di interfaccia OnHeadlineSelectedListener.
Implementando questa interfaccia nell’ attività contenitrice e sovrascrivendo (overriding) il suo metodo onArticleSelected è possibile inviare l’ evento ad altri frammenti.
Il blocco try-catch serve a verificare che, quando il frammento viene inserito nell’ attività (evento onAttach() !), questa implementi l’ interfaccia: la verifica consiste nell’ istanziare una istanza dell’ interfaccia OnHeadlineSelectedListener tramite la classe dell’ attività, la quale implementa l’ interfaccia stessa.
In caso di errore, viene lanciata un’ eccezione.
In caso di successo, il membro mCallback tiene un riferimento all’ implementazione dell’ interfaccia da parte dell’ attività.

Il frammento usa l’ interfaccia di callback per inviare eventi all’ activity genitrice:

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
   // Send the event to the host activity
   mCallback.onArticleSelected(position);
}

Dal precedente snippet si vede che quando avviene l’ evento onListItemClick nel frammento, il suo listener chiama l’ interfaccia di callback che precedentemente abbiamo “agganciato” all’ attività; in altre parole, quando avviene un evento nel frammento, viene eseguito prima il listener nel frammento, e questo chiama la funzione implementata nell’ attività contenitrice: in questo modo si possono passare variabili dal frammento all’ attività.

Implementare l’ interfaccia

L’ attività che riceve i messaggi deve implementare le interfacce definite nei frammenti:

public static class MainActivity extends Activity
        implements HeadlinesFragment.OnHeadlineSelectedListener{
    ...
    
    public void onArticleSelected(Uri articleUri) {
        // The user selected the headline of an article from the HeadlinesFragment
        // Do something here to display that article
    }
}

Esempio di comunicazione Activity-Fragment

L’ attività puo inviare messaggi ai frammenti direttamente chiamando i metodi pubblici dei frammenti: può catturare l’ istanza del Fragment con findFragmentById().

Esempio:

public static class MainActivity extends Activity
        implements HeadlinesFragment.OnHeadlineSelectedListener{
    ...

    public void onArticleSelected(int position) {
        // The user selected the headline of an article from the HeadlinesFragment
        // Do something here to display that article

        ArticleFragment articleFrag = (ArticleFragment)
                getSupportFragmentManager().findFragmentById(R.id.article_fragment);

        if (articleFrag != null) {
            // If article frag is available, we're in two-pane layout...

            // Call a method in the ArticleFragment to update its content
            articleFrag.updateArticleView(position);
        } else {
            // Otherwise, we're in the one-pane layout and must swap frags...

            // Create fragment and give it an argument for the selected article
            ArticleFragment newFragment = new ArticleFragment();
            Bundle args = new Bundle();
            args.putInt(ArticleFragment.ARG_POSITION, position);
            newFragment.setArguments(args);
        
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

            // Replace whatever is in the fragment_container view with this fragment,
            // and add the transaction to the back stack so the user can navigate back
            transaction.replace(R.id.fragment_container, newFragment);
            transaction.addToBackStack(null);

            // Commit the transaction
            transaction.commit();
        }
    }
}

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...