Android Tutorial: ViewPager mit Fragments und der CursorLoader

Devs und Geeks

Hallo liebe mobiFlip.de-Leser. Letztes mal habe ich euch versucht näher zu bringen, wie Android mit verschiedenen Auflösungen umgeht und habe mich sehr über das Positive Feedback gefreut. Da der Wunsch aufkam und ich Spaß daran habe, folgt nun heute ein kleines Programmiertutorial, welches den ein oder anderen eventuell etwas näher an die Materie heranführt. In diesem Tutorial geht es darum, wie man mit Bordmitteln in Android einige einfache Funktionen realisiert. Also nach links und rechts wischen und verschiedene Daten bzw. Layouts anzeigen lassen.

Da ich Programmierung nur nebenbei mache und mir das auch selber angeeignet habe, würde ich mich über Anmerkungen oder Tipps freuen. Ein gewisses Vorwissen kann in diesem Beitrag nicht schaden, sollte dies nicht vorhanden sein und Interesse bestehen, beim absoluten Grundschleim nochmal anzufangen, dann hinterlasst doch bitte eure Wünsche in den Kommentaren. Viel Spaß beim Lesen, Ausprobieren und Verwenden. Source und APK sind dem Artikel beigefügt.

Voraussetzungen

  • Grundlegende Kenntnisse im Umgang mit Java
  • Überschreiben von Methoden
  • Grundsätzlicher Umgang mit Fragments (nicht zwingend)

Ziel

  • Eine Activity indem man 5 Fragments nach links und rechts „wischen“ kann.
  • Davon zwei Fragments aus XML Res.
  • Drei ListFragments von denen eines aus einem statischen Array gefüllt wird und zwei mit Inhalt aus dem ContentProvider. In diesem Fall die Namen der Audio Künstler und die Namen der Audio Alben welche sich auf dem Gerät befinden.
  • Dazu kommt das Einblenden des Titels des aktuell eingeblendeten Fragments über diesem.

Vorbereitung

Als erstes wird ein Android Projekt erstellt. Die min. Api kann API 4 bzw. Android 1.6 sein, da wird die Android support.v4.lib benutzen werden, welche wie der Name schon sagt, bis API 4 kompatibel ist. Die Main Activity kann direkt miterzeugt werden. Wenn das Projekt erstellt wurde und Eclipse damit fertig ist den „gen“ Ordner zu füllen, klickt man mit der rechten Maustaste auf das Projekt.

Android Tools –> Add Suppot Library…

Nun sollte Eclipse sich daten von Google holen und das Package „Android Support, revision 7“ zur Intstallation anbieten. Dies wird mit Accept und Intstall bestätigt. Nun erscheinen im Projekt die Punkte „Android Dependencies“ und „Referenced Libraries“ in denen sich das JAR android-support-v4.jar befinden sollte.

Komponenten aus der Support lib müssen im XML mit vollem Namen geschrieben werden. In unserem Fall müssen wird also schreiben android.support.v4.view.ViewPager schreiben. Dann wird eine id vergeben und wie immer die Höhe und Breite dieses Widgets. Das würde im Grunde schon reichen um einen ViewPager zu benutzen, aber das wir auch den Titel der einzelnen Fragments anzeigen wollen kommt auch der PagerTitleStrip zum Einsatz. Dieses wird auch wieder in der Höhe und Breite festgelegt und GANZ  WICHTIG mit android:layout:gravity auf „top“ oder „bottom“ gesetzt, je nach dem ob der Titel oben oder unten stehen soll.

Dabei ist noch wichtig zu wissen, dass der PagerTitleStrip ein Kind des ViewPager Elements sein muss.

Die PageAdapter Klasse

Wenn der ViewPager benutzt wird, muss die PagerAdapter Klasse von „PagerAdapter“ abgeleitet werden und in diesem Fall auch anders benannt werden. Da wir in diesem Fall jedoch mit Fragments arbeiten werden, muss unser PagerAdapter von FragmentPagerAdapter abgeleitet werden.

public class PageAdapter extends FragmentPagerAdapter {

Dabei müssen diese Methoden mindestens implementiert werden:

public PageAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}

@Override

public Fragment getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}

@Override

public int getCount() {
// TODO Auto-generated method stub
return 0;
}

Im Constructor wird der FragmentManager übergeben, dazu aber später bei der Main Activity mehr. Bei der Methode „getItem(int arg0)“ wird die Position des abgerufenen Fragments übergeben und erwartet ein Fragment als Rückgabewert. Die Methode getCound() erwartet als Rückgabewert die Anzahl der Fragmente die im ViewPager untergebracht werden sollen. Da Bei unserem Beispiel 5 Fragment dargestellt werden sollen legen wir uns eine

private final int NUM_PAGES = 5;

Variable an. Man kann diesen Wert natürlich auch über eine Methode aus einer anderen Klasse holen und so die Anzahl an Fragments „dynamisch“ regeln. Für den PagerTitleStrip müssen wir nun noch die Methode

public CharSequence getPageTitle(int position) {

überschreiben (Strg + 3 -> Enter). In diesem Fall legen wir eine Array mit den Titeln der Fragments an

private final String[] titles = { „Page1“, „Page2“, „Früchte“,“Artists“,“Albums“};

und geben

return titles[position];

zurück.

Die Erzeugung der Fragments

In diesem Beispiel habe ich zwei Arten von Fragments hergenommen. Zum einen das normale Fragment und zum anderen das ListFragment.

Fragment erzeugen:

Es wird eine Klasse erstellt welche von Fragment abgeleitet wird. Diese bekommt eine Variable

private int fragmentNR;

welche im Constructor mit einem Wert belegt wird.

public PageFragment(int nr) {
this.fragmentNR = nr;

Nun muss nur noch die Methode onCreateView überschrieben werden. Diese gibt einen View zurück. Man könnte entweder ein View per Code erzeugen oder wie in diesem Beispiel per XML. Dafür wird per if bzw. else if Abfrage überprüft welches Layout gefordert wird und „aufgeblasen“ werden muss.

View v = new View(getActivity());
if (fragmentNR == 0)
v = inflater.inflate(R.layout.page_one, container, false);
else if (fragmentNR == 1)
v = inflater.inflate(R.layout.page_two, container, false);
return v;

Damit ist das Fragment fertig zum erzeugen. Dies geschieht in der getItem(int pos) Methode in der PageAdapter Klasse. Die ersten zwei Fragments werden von dem erklärten Typ sein.

public Fragment getItem(int pos) {
if (pos < 2) {
PageFragment f = new PageFragment(pos);
return f;}

ListFragment erzeugen:

Das ListFragment wird von der Gleichnamigen Klasse abgeleitet

public class PageListFragment extends ListFragment implements
LoaderCallbacks

und das Interface LoaderCallback angehängt. Dieses Interface implementiert 3 Methoden:

@Override
public Loader onCreateLoader(int arg0, Bundle arg1) {
return loader;
}

@Override
public void onLoadFinished(Loader arg0, Cursor cursor) {
}

@Override
public void onLoaderReset(Loader arg0) {
}

Die Methoden werden auch in dieser Folge aufgerufen. Dazu später mehr. Wie schon im normalen Fragment belegen wir auch in dem ListFragment im Constructor eine Variable mit einem Zahlenwert, welcher vom FragmentPagerAdapter übergeben wird.

public PageListFragment(int nr) {
this.listNr = nr;
}

Nun überschreiben wir die onCreate(Bundle) Methode, diese ist nicht bei ListFragment zu finden sondern bei Fragment. In der onCreate(Bundle) Methode erzeugen wir nun je nach angeforderten ListFragment den richtigen ListAdapter.

if (listNr == 0) {ArrayAdapter-String- mAdapter = new ArrayAdapter-String-(
getActivity(),android.R.layout.simple_list_item_1, fruit);
setListAdapter(mAdapter);

Wenn im Constructor die „0“ übergeben wird benutzten wir einen einfach ArrayAdapter um das Array

private final String[] fruit = { „Bananen“, „Apfle“, „Erdbeere“,
„Kirschen“, „Mangos“ };

in einer Liste darzustellen. Der ArrayAdapter braucht als Übergabewert:

  • Context: getActivity()
  • ein Layout für ein ListItem: Hier ein Android Standardlayout
  • ein Array des Types String da festgelegt wurde ArrayAdapter-String-
  • Jetzt muss nur noch der ListAdapter des ListFragments gesetzt werden mit „setListAdapter(mAdapter)“.

Wenn im Constructor jedoch 1 oder 2 angefordert werden, dann sieht alles ein wenig anders aus. Als erstes muss eine Klassenvariable erstellt werden.

private SimpleCursorAdapter mCursorAdapter;

Der SimpleCursorAdapter braucht folgende Übergabewerte:

  • Context: getActivity()
  • ein Layout für ein ListItem: Hier ein Android Standardlayout
  • einen Cursor, da aber noch keiner vorhanden ist, wird hier „null“ übergeben. Später wird er ausgetauscht.
  • ein String Array mit den Strings aus dem Cursor welche dargestellt werden sollen.
  • ein int Array mit der id des TextViews auf den die Strings geschrieben werden sollen
  • als letztes noch „int flags“: Das wird nicht gebraucht und mit 0 belegt.

Jetzt wird wieder mit setListAdapter(mCursorAdapter); der Adapter für das ListFragment gesetzt und der Loader Aufgerufen. Man holt sich zuerste den LoaderManager mit getLoaderManager() und ruft die Methode initLoader(0, null, this) auf.  Der LoaderManager ruft jetzt die Methode

public Loader onCreateLoader(int arg0, Bundle arg1)

auf und übergibt in unserem Beispeil die int „0“ und das Bundle „null“. Zurückgegeben wird ein Loader des Typs Cursor. Nun erstellen wir also diesen Loader:

Loader loader = new CursorLoader(getActivity(), mMediaSource[listNr],
null, null, null, null);

Der CursorLoader braucht folgende Übergabewerte:

  • Context
  • Uri der Quelle
    private Uri[] mMediaSource = {null, MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI};
  • Ein String Array welches Festlegt welche Strings aus dem ContentProvider benötigt werden. Bei null werden Alle im Cursor vorhanden sein. Dies kann bei viel Content zu schlechter Performance führen.
  • Die nächsten zwei Werte dienen zum Filtern der Ergebnisse. Werd ich hier nicht näher erläutern.
  • Der letzte Wert entscheidet über die Sortierung. Es kann z.B.

String sortOrder = MediaStore.Audio.Media.ARTIST + “ COLLATE LOCALIZED ASC“;

Wenn der LoaderManager fertig ist und der Loader erstellt wurde, wird die Methode onLoadFinished(Loader loader, Cursor cursor) aufgerufen. Nun muss man nur noch den Cursor des SimpleCursorAdapter mit .swapCursor(cursor) austauschen gegen den neuen und schon wird die Liste angezeigt.

Abschließend muss man noch in der Methode onLoaderReset(..) den Cursor im SimpleCursorAdapter gegen den Wert „null“ austauschen um den Cursor wieder löschen zu können.

Jetzt muss nur noch im PageAdapter eine Instanz dieses Fragments erstellt werden

else if (pos == 2) {
PageListFragment lf = new PageListFragment(0);
return lf;
} else if (pos == 3) {
PageListFragment lf = new PageListFragment(1);
return lf;
} else if (pos == 4) {
PageListFragment lf = new PageListFragment(2);
return lf;
} else {
PageFragment f = new PageFragment(pos);
return f;
}

Die Main Activity:

Da wir hier mit einem FragmentPageAdapter arbeiten, brauchen wir eine Activity welche einen FragmentManager hat. Dies ist in der Klasse Activity nicht der Fall sondern in der Klasse FragmentActivity. Dem entsprechend müssen wir die Main Klasse von FragmentActivity ableiten und nicht von Activity wie sonst.

public class Main extends FragmentActivity {

Anschließend muss wie gewohnt per setContentView() das entsprechende Layout geladen werden. Jetzt folgt noch die Instanziierung unserer PageAdapter Klasse per

PageAdapter mPageAdapter = new PageAdapter(getSupportFragmentManager());

wie man sehen kann wird der FragmentManager an unseren Adapter übergeben.

Info

Wenn mit der support.v4.lib gearbeitet wird, wird der FragmentManager per getSupportFragmentManager() aufgerufen. Falls jedoch die FragmentActivity ab API11 verwendet wird, wird der FragmentManager per getFragmentManager() aufgerufen.

Nun noch der ViewPager. Dieser wird erstmal per id gefunden

ViewPager mViewPager = (ViewPager) findViewById(R.id.viewpager);

und dann wird unser Adapter zugewiesen

mViewPager.setAdapter(mPageAdapter);

Jetzt sind wir fertig und es sollte alles wie gewünscht funktionieren.


Fehler melden4 Kommentare

  1. Das DISQUS-Kommentarsystem verarbeitet personenbezogene Daten. Das System wird aus diesem Grund erst nach ausdrücklicher Einwilligung über nachfolgende Schaltfläche geladen. Es gilt die Datenschutzerklärung.

Du bist hier:
mobiFlip.de / Anleitungen / Devs und Geeks / ...