Schönheit aus Fragmenten. So verbessern Sie die Benutzeroberfläche in Android mithilfe der Fragment-Klasse. Android-Fragmente fragmentieren den Lebenszyklus

Abbildung 2. Fragmentlebenszyklus (während der Operationsausführung)

Um ein Fragment zu erstellen, müssen Sie eine Unterklasse der Klasse (oder einer vorhandenen Unterklasse davon) erstellen. Die Klasse hat einen Code, der dem ähnelt. Es enthält Callback-Methoden, die Operationsmethoden ähneln, z. B. , und . In der Praxis, wenn Sie konvertieren müssen bestehende Anwendung Um in Android Fragmente zu verwenden, verschieben Sie einfach den Code von den Operations-Callback-Methoden in die entsprechenden Fragment-Callback-Methoden.

Normalerweise müssen Sie es implementieren folgende Methoden Lebenszyklus:

Das System ruft diese Methode auf, wenn es ein Fragment erstellt. In seiner Implementierung muss der Designer die Schlüsselkomponenten des Fragments initialisieren, die erhalten bleiben müssen, wenn das Fragment angehalten oder nach dem Stoppen wieder aufgenommen wird.

Das System ruft diese Methode auf, wenn die Fragment-Benutzeroberfläche zum ersten Mal auf dem Display angezeigt wird. Um die Benutzeroberfläche des Fragments zu rendern, sollte diese Methode das Objekt zurückgeben, das den Stamm des Fragmentlayouts darstellt. Wenn das Fragment keine Benutzeroberfläche hat, können Sie null zurückgeben.

Zeigt ein verschiebbares Dialogfeld an. Die Verwendung dieser Klasse zum Erstellen eines Dialogfelds ist eine gute Alternative zu den Hilfsmethoden für Dialogfelder in der . Dies liegt daran, dass es die Möglichkeit bietet, einen Fragmentdialog in einen vorgangsgesteuerten Backstack für Fragmente einzufügen, sodass der Benutzer zu einem geschlossenen Fragment zurückkehren kann.

Die Anzeige einer Liste von vom Adapter verwalteten Elementen (z. B. ) ähnelt der . Diese Klasse stellt mehrere Methoden zum Verwalten der Liste der Ansichten bereit, beispielsweise eine Rückrufmethode für die Verarbeitung von Klicks.

Anzeige einer Hierarchie von Objekten in Form einer Liste, ähnlich der . Diese Klasse ist nützlich, wenn Sie einen Einstellungsvorgang in einer Anwendung erstellen.

Hinzufügen einer Benutzeroberfläche Ein Fragment wird normalerweise als Teil der Benutzeroberfläche einer Aktivität verwendet und fügt der Aktivität ein eigenes Layout hinzu. Um ein Layout für ein Fragment zu erstellen, muss der Entwickler eine Rückrufmethode implementieren

Android-System Wird aufgerufen, wenn das Fragment sein Layout rendern muss. Die Implementierung dieser Methode muss ein Objekt zurückgeben, das den Stamm des Fragmentlayouts darstellt.

Notiz.

Wenn das Fragment eine Unterklasse der Klasse ist, gibt die Standardimplementierung die Klasse von der Methode zurück, sodass keine Notwendigkeit besteht, sie zu implementieren.

Um ein Layout von einer Methode zurückzugeben, können Sie es über eine in der XML-Datei definierte Methode erweitern. Zu diesem Zweck stellt die Methode eine .

Der Code für eine Unterklasse der Klasse, die das Layout aus example_fragment.xml lädt, könnte beispielsweise so aussehen:

Die öffentliche statische Klasse „ExampleFragment“ erweitert Fragment ( @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savingInstanceState) ( // Das Layout für dieses Fragment vergrößern return inflater.inflate(R.layout.example_fragment, container, false); ) )

Erstellen eines Layouts Im folgenden Code ist das Konstrukt R.layout.example_fragment ein Verweis auf eine Layoutressource mit dem Namen example_fragment.xml, die in den Anwendungsressourcen gespeichert ist. Einzelheiten zum Erstellen eines Layouts in XML finden Sie in diesem Artikel.

Ein Beispiel für einen Vorgang, der ein Fragment als Hintergrundthread ohne Benutzeroberfläche verwendet, finden Sie im Codebeispiel FragmentRetainInstance.java, das in den SDK-Beispielen enthalten ist (und über den Android SDK-Manager zugänglich ist). Der Pfad dazu im System ist

Um Fragmente in einer Operation zu verwalten, benötigen Sie eine Klasse. Um es zu erhalten, müssen Sie die Methode über den Opcode aufrufen.

Im Folgenden sind die Aktionen aufgeführt, die Sie ausführen können:

  • Rufen Sie die in der Operation vorhandenen Fragmente mithilfe der Methode ab (für Fragmente, die Folgendes bereitstellen). Benutzeroberfläche im Operationslayout) oder (sowohl für Fragmente mit Benutzeroberfläche als auch für Fragmente ohne Benutzeroberfläche);
  • Entfernen Sie Fragmente aus dem Stapel von Übergängen mithilfe der Rückwärtsmethode (simulieren Sie das Drücken einer Taste). Zurück Benutzer);
  • Registrieren Sie den Change-Listener-Prozess im Backstack mithilfe der .

Weitere Informationen Diese und andere Methoden werden in der Klassendokumentation beschrieben.

Wie im vorherigen Abschnitt gezeigt, können Sie die Open-Klasse verwenden, mit der Sie Transaktionen für Fragmente ausführen können, z. B. Hinzufügen und Löschen.

Durchführen von Transaktionen mit Fragmenten

Der große Vorteil der Verwendung von Fragmenten in einem Vorgang besteht in der Möglichkeit, sie als Reaktion auf Benutzereingaben hinzuzufügen, zu entfernen, zu ersetzen und andere Dinge damit zu tun. Alle an einer Operation vorgenommenen Änderungen werden als Transaktion bezeichnet. Dies kann mithilfe der APIs in erfolgen. Jede Transaktion kann in einem Backstack gespeichert werden, der von der Operation verwaltet wird. Dadurch kann der Benutzer rückwärts durch Änderungen in Fragmenten navigieren (ähnlich wie rückwärts durch Aktivitäten gehen).

Interaktion mit der Operation

öffentliche statische Klasse FragmentA erweitert ListFragment ( OnArticleSelectedListener mListener; ... @Override public void onAttach(Activityactivity) ( super.onAttach(activity); try ( mListener = (OnArticleSelectedListener)activity; ) Catch (ClassCastException e) ( throw new ClassCastException( Activity.toString() + „muss OnArticleSelectedListener implementieren“) ) ... )

Wenn die Operation die Schnittstelle nicht implementiert hat, löst das Fragment eine Ausnahme aus. Bei Erfolg enthält das mListener-Element einen Verweis auf die Implementierung der OnArticleSelectedListener-Schnittstelle durch die Operation, sodass Fragment A Ereignisse mit der Operation teilen kann, indem es Methoden aufruft, die von der OnArticleSelectedListener-Schnittstelle definiert werden. Wenn beispielsweise Fragment A eine Erweiterung der Klasse ist, ruft das System das Fragment auf, wenn der Benutzer auf ein Listenelement klickt. Diese Methode ruft wiederum die Methode onArticleSelected() auf, um das Ereignis in Verbindung mit der Operation zu verwenden:

Die öffentliche statische Klasse FragmentA erweitert ListFragment ( OnArticleSelectedListener mListener; ... @Override public void onListItemClick(ListView l, View v, int position, long id) ( // Zeilen-ID des angeklickten Elements mit dem Inhaltsanbieter Uri Uri noteUri = anhängen ContentUris. (ArticleColumns.CONTENT_URI, id); // Senden Sie das Ereignis und den Uri an die Hostaktivität mListener.onArticleSelected(noteUri) ... )

Der an die Methode übergebene ID-Parameter ist die ID der Zeile, die das ausgewählte Listenelement enthält, das die Operation (oder ein anderes Fragment) verwendet, um den Artikel aus dem Anwendungsobjekt abzurufen.

Weitere Informationen zur Zusammenarbeit mit einem Inhaltsanbieter finden Sie im Dokument.

Elemente zur Aktionsleiste hinzufügen

Fragmente können Menüelemente zu Aktivitäten (und damit zu) hinzufügen, indem sie implementieren. Damit diese Methode jedoch Aufrufe akzeptiert, muss sie zur Laufzeit aufgerufen werden, um anzuzeigen, dass das Fragment beabsichtigt, Elemente zum Optionsmenü hinzuzufügen (andernfalls akzeptiert das Fragment den Methodenaufruf nicht).

Alle vom Fragment zum Optionsmenü hinzugefügten Elemente werden zu den vorhandenen hinzugefügt. Darüber hinaus empfängt das Fragment Methodenrückrufe, wenn der Benutzer einen Menüpunkt auswählt.

Der Entwickler kann zur Bereitstellung auch eine Ansicht im Layout seines Fragments registrieren Kontextmenü. Rufen Sie dazu die Methode auf. Wenn der Benutzer das Kontextmenü öffnet, akzeptiert das Fragment einen Methodenaufruf. Wenn der Benutzer einen Menüpunkt auswählt, erhält das Fragment einen Methodenaufruf.

Android-System Obwohl das Fragment für jedes hinzugefügte Element einen Rückruf für das Ereignis „Menüelement ausgewählt“ erhält, erhält die Aktivität zunächst den entsprechenden Rückruf, wenn der Benutzer ein Menüelement auswählt. Wenn die vorhandene Callback-Implementierung der Aktivität für das im Menüelement ausgewählte Ereignis das ausgewählte Element nicht verarbeitet, wird das Ereignis an die Callback-Methode im Fragment übergeben. Dies gilt für Optionsmenüs und Kontextmenüs.

Detaillierte Menüinformationen finden Sie in den Entwicklerhandbüchern und

Fragment-Lebenszyklusmanagement

Abbildung 3. Die Auswirkungen des Betriebslebenszyklus auf Lebenszyklus Fragment

Die Verwaltung des Lebenszyklus eines Fragments ähnelt in vielerlei Hinsicht der Verwaltung des Lebenszyklus eines Vorgangs. Wie eine Operation kann ein Fragment in einem von drei Zuständen existieren:

Wieder aufgenommen Das Fragment ist während der Operation sichtbar. Ausgesetzt Eine andere Aktivität wird ausgeführt und hat den Fokus im Vordergrund, aber die Aktivität, die das Fragment enthält, ist immer noch sichtbar (die Vordergrundaktivität ist teilweise transparent oder füllt nicht den gesamten Bildschirm aus). Angehalten Das Fragment ist nicht sichtbar. Entweder wurde der Containervorgang gestoppt oder das Fragment wurde daraus entfernt, aber dem Backstack hinzugefügt. Das gestoppte Fragment ist noch aktiv (alle Informationen über den Zustand und die Elemente werden im System gespeichert). Es ist jedoch für den Benutzer nicht mehr sichtbar und wird zerstört, wenn der Vorgang zerstört wird.

Auch hier ist die Analogie zu einer Operation sichtbar: Der Entwickler kann den Zustand des Fragments mit Hilfe speichern, falls der Operationsprozess zerstört wird, und der Entwickler muss den Zustand des Fragments wiederherstellen, wenn die Operation neu erstellt wird. Der Status kann während der Ausführung einer Callback-Methode in einem Fragment gespeichert und während der Ausführung von , oder wiederhergestellt werden. Weitere Informationen zur Persistenz finden Sie im Dokument.

Der bedeutendste Lebenszyklusunterschied zwischen einer Operation und einem Fragment besteht darin, wie sie in ihren jeweiligen Backstacks gespeichert werden. Standardmäßig wird eine Operation beim Stoppen auf dem vom System verwalteten Backstack für Operationen abgelegt (damit der Benutzer über die Schaltfläche dorthin zurückkehren kann). Zurück, wie im Artikel beschrieben). Gleichzeitig wird das Fragment nur dann auf dem betriebsgesteuerten Backstack platziert, wenn der Entwickler explizit anfordert, dass eine bestimmte Instanz gespeichert wird, indem er während der Transaktion eine Methode aufruft, die das Fragment löscht.

Ansonsten ist die Verwaltung des Lebenszyklus eines Fragments der Verwaltung des Lebenszyklus einer Operation sehr ähnlich. Deshalb praktische Empfehlungen gelten auch für Fragmente. Gleichzeitig muss der Entwickler verstehen, wie sich der Lebenszyklus einer Operation auf den Lebenszyklus eines Fragments auswirkt.

Aufmerksamkeit! Wenn Sie ein Objekt innerhalb eines Klassenobjekts benötigen, können Sie das aufrufen. Allerdings muss der Entwickler darauf achten, die Methode nur dann aufzurufen, wenn das Fragment an eine Operation angehängt ist. Wenn das Fragment noch nicht angehängt ist oder am Ende seines Lebenszyklus abgedockt wurde, gibt die Methode null zurück.

Ausrichtung am Aktivitätslebenszyklus

Der Lebenszyklus der Aktivität, die das Fragment enthält, wirkt sich direkt auf den Lebenszyklus des Fragments aus, sodass jeder Aktivitätslebenszyklus-Rückruf zu einem ähnlichen Rückruf für jedes Fragment führt. Wenn beispielsweise eine Operation einen Aufruf annimmt, akzeptiert jedes ihrer Fragmente .

Allerdings verfügen Fragmente über mehrere zusätzliche Lebenszyklus-Rückrufmethoden, die eine einzigartige Interaktion mit einem Vorgang ermöglichen, um Aktionen wie das Erstellen und Zerstören der Fragment-Benutzeroberfläche auszuführen. Dies sind die Methoden:

OnCreate() , das Fragment innerhalb dieser Operation benötigt lediglich eine Rückrufmethode.

Wenn ein Vorgang in den Status „wieder aufgenommen“ übergeht, können Sie ihm nach Belieben Fragmente hinzufügen und entfernen. Daher kann der Lebenszyklus des Fragments nur dann unabhängig geändert werden, wenn der Vorgang im Status „wieder aufgenommen“ verbleibt.

Wenn die Operation jedoch diesen Zustand verlässt, wird der Fortschritt des Fragments durch seinen Lebenszyklus erneut von der Operation ausgeführt.

Beispiel:

Um alles zusammenzufassen, was in diesem Dokument behandelt wird, schauen wir uns einen Beispielvorgang an, bei dem zwei Fragmente verwendet werden, um ein Layout mit zwei Bedienfeldern zu erstellen. Die folgende Operation umfasst ein Fragment zum Anzeigen einer Liste von Shakespeare-Stücken und ein weiteres zum Anzeigen einer Zusammenfassung des aus der Liste ausgewählten Stücks. Das Beispiel zeigt, wie unterschiedliche Fragmentkonfigurationen je nach Bildschirmkonfiguration organisiert werden sollten.

Android-System Der vollständige Quellcode für diesen Vorgang befindet sich im Abschnitt.

Die Hauptoperation wendet das Layout auf die übliche Weise an, und zwar in der folgenden Methode:

@Override protected void onCreate(Bundle savingInstanceState) ( super.onCreate(savedInstanceState); setContentView(R.layout.fragment_layout); )

Hier wird das fragment_layout.xml-Layout verwendet:

Mithilfe dieses Layouts erstellt das System eine Instanz der TitlesFragment-Klasse (Liste der Wiedergaben), sobald die Operation das Layout lädt. In diesem Fall nimmt das Objekt (das ein Fragment mit einer Zusammenfassung enthalten wird) Platz auf der rechten Seite des Bildschirms ein, bleibt aber zunächst leer. Wie weiter unten gezeigt wird, wird das Fragment erst eingefügt, wenn der Benutzer ein Element in der Liste auswählt.

Allerdings sind nicht alle Bildschirme breit genug, um neben der Playlist eine Zusammenfassung anzuzeigen. Daher wird das oben beschriebene Layout nur im Querformat verwendet und in der Datei res/layout-land/fragment_layout.xml gespeichert.

Wenn das Gerät drin ist Hochformat, wendet das System das folgende Layout an, das in der Datei res/layout/fragment_layout.xml gespeichert ist:

In diesem Layout ist nur das TitlesFragment-Objekt vorhanden. Das bedeutet, dass im Hochformat des Geräts nur die Liste der Spiele sichtbar ist. Wenn der Benutzer in dieser Konfiguration auf ein Listenelement klickt, startet die Anwendung eine neue Aktivität, um die Zusammenfassung anzuzeigen, anstatt ein zweites Fragment zu laden.

Als nächstes können Sie sehen, wie dies in den Fragmentklassen implementiert wird. Zuerst kommt der Code für die TitlesFragment-Klasse, die eine Liste von Shakespeares Stücken anzeigt. Dieses Snippet erweitert die Klasse und nutzt ihre Funktionen, um die grundlegende Arbeit mit der Liste zu erledigen.

Beachten Sie beim Untersuchen des Codes, dass es zwei mögliche Verhaltensweisen gibt, wenn ein Benutzer auf ein Listenelement klickt. Je nachdem, welches der beiden Layouts aktiv ist, erstellt und zeigt entweder eine einzelne Aktivität ein neues Zusammenfassungsfragment an (durch Hinzufügen des Fragments zu einem Objekt) oder es wird eine neue Aktivität (Anzeige des Fragments) gestartet.

Das zweite Fragment, DetailsFragment, zeigt eine Zusammenfassung des in der TitlesFragment-Liste ausgewählten Stücks an:

Erinnern wir uns an den Code der TitlesFragment-Klasse: Wenn der Benutzer auf ein Listenelement klickt, und an das aktuelle Layout Nicht Enthält die R.id.details-Ansicht (die das DetailsFragment besitzt), dann führt die Anwendung eine DetailsActivity aus, um den Inhalt des Elements anzuzeigen.

Öffentliche statische Klasse DetailsActivity erweitert Aktivität ( @Override protected void onCreate(Bundle savingInstanceState) ( super.onCreate(savedInstanceState); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) ( // Wenn der Bildschirm jetzt in ist Im Querformat können wir den Dialog // inline mit der Liste anzeigen, sodass wir diese Aktivität nicht benötigen. finish(); return; ) if (savedInstanceState == null) ( // Geben Sie bei der Ersteinrichtung die Details ein fragment. DetailsFragment details = new DetailsFragment(); details.setArguments(getIntent().getExtras()); getFragmentManager().beginTransaction().add(android.R.id.content, details).commit( )

Beachten Sie, dass sich diese Aktivität in der Landschaftskonfiguration selbst vervollständigt, sodass die Hauptaktivität die Kontrolle übernehmen und das DetailsFragment neben dem TitlesFragment anzeigen kann. Dies kann passieren, wenn der Benutzer eine DetailsActivity im Hochformat startet und das Gerät dann ins Querformat umdreht (was dazu führt, dass die aktuelle Aktivität neu gestartet wird).

Zusätzliche Codebeispiele mit Snippets (und vollständigen Dateien) Quellcode Dieses Beispiel) sind in der Beispielanwendung Demos API verfügbar (die von heruntergeladen werden kann).

Eine gute Benutzeroberfläche zu erstellen ist schwierig, insbesondere wenn Sie noch nicht viel Erfahrung in diesem Bereich haben. Daher hier ein kurzer Test Ihres Wissens zu diesem Thema: Wenn Sie es gewohnt sind, dass ein neues Fenster unbedingt eine Aktivität benötigt oder es in einem frisch geschriebenen Programm aus irgendeinem Grund zu Krämpfen kommt, anstatt einer reibungslosen Animation, ist dieser Artikel genau das Richtige für Sie für dich :)

Rake-Aktivität

Die meisten Tutorials, die die Tricks der Android-Entwicklung demonstrieren, beginnen auf die gleiche Weise: Unerfahrene Entwickler werden gebeten, alle visuellen Elemente direkt in das XML-Markup der Hauptaktivität einzufügen. Es sieht ungefähr so ​​aus:

Die öffentliche Klasse MainActivity erweitert AppCompatActivity ( @Override protected void onCreate(Bundle savingInstanceState) ( super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ...

Diese Art von Design wird zur Gewohnheit und das Projekt wird mit neuen Aktivitäten mit immer komplexeren Markups gefüllt. Im Ergebnis – sogar minimal nützliche Anwendung wird mit einem Aktivitätsstapel überwuchert und verschlingt alles RAM, und bei Google Play fliegen dem Entwickler Steine ​​und Zweien entgegen.

Und das alles, weil das Android-Betriebssystem nicht verspricht, Ihre Aktivitäten am Leben zu halten. Wie Sie sich erinnern, existieren diese Komponenten unabhängig voneinander und haben einen besonderen Lebenszyklus. Wenn die Aktivität in den OnPause-Zustand wechselt, was recht häufig vorkommt, wird sie zu Schrödingers Katze: Sie können nicht im Voraus wissen, ob sie am Leben sein wird oder nicht.

Durch die Verwendung zusätzlicher Aktivitäten zur Anzeige von Menüs und anderen Kleinigkeiten gefährden Sie alle logischen Verbindungen innerhalb der Anwendung. Aktivitäten werden auf einem Stapel gesammelt und das Betriebssystem kann einzeln oder in einer Gruppe mit dem Entladen beginnen. Wenn der Benutzer zum vorherigen Fenster zurückkehren möchte, ist die Aktivität möglicherweise bereits zerstört und der Benutzer verlässt die Anwendung.

Zusätzlich zu den Problemen bei der Erhaltung der Logik gibt es auch die Routine, OOP-Code zu unterstützen: Schnittstellen, die eng an die Aktivität gebunden sind, lassen sich kaum weiterentwickeln. Skalierung, schneller Austausch einige Elemente zu anderen, Animationen – all dies wird in neuen Versionen der Anwendung nur sehr schwer umzusetzen sein.

Dank der Mode für ein einziges Ökosystem, alles mobile Anwendungen waren im Allgemeinen sehr ähnlich. Man muss nur den Weg finden und ein wenig üben, dann beginnt die Qualität schnell zu wachsen. Nach dem Prinzip „Kritisieren – Vorschlagen“ schreiben wir nun eine Anwendung, die eine universelle Benutzeroberfläche implementiert. Das wird nicht nur aus akademischer Sicht interessant sein – ich bin sicher, dass Sie den heute geschriebenen Code problemlos in Ihre Projekte integrieren können. Also fangen wir an!

Fragmente

Um die Arbeit mit der Benutzeroberfläche einfacher und schneller zu machen, hat Google ein Fragment – ​​eine Klasse – eine Ebene zwischen der Aktivität und den visuellen Komponenten des Programms erstellt. Einerseits ist es ein Container für beliebige View-Objekte, die dem Benutzer angezeigt werden können. Andererseits gibt es eine Fortsetzung der Aktivität, von der Fragment alle Informationen über Änderungen im Lebenszyklus erhält.

Fragmente haben wie Aktivitäten ihren eigenen (wenn auch originelleren) Lebenszyklus. Beispielsweise ist es nicht möglich, direkt nach dem Erstellen eines Fragments mit der Benutzeroberfläche zu arbeiten. Sie müssen warten, bis alle Elemente geladen sind. Nach der onCreate-Methode wird die onCreateView-Methode ausgeführt, in der die Elemente geladen werden können.

Öffentliche Klasse FragmentOne erweitert Fragment ( ... public View onCreateView(...) ( Ansicht anzeigen=inflater.inflate(R.layout.fragment_one, container,false);

TextView textView = (TextView)view.findViewById(R.id.fo_text);

textView.setText("Hallo, ich bin das erste Fragment!"); Rückkehr zur Ansicht; ...

In einem Fragment können Sie auch alle Methoden überschreiben, die den Status des Fensters überwachen. Wenn die Anwendung also in den Hintergrund geht, wird onPause in der Aktivität ausgeführt und dann wird hier die Methode mit genau demselben Namen ausgeführt. Dies kann nützlich sein – praktisch, um die Verbindung zu Objekten Dritter, wie z. B. gebundenen Diensten, zu trennen.

FragmentTransaction

Da Google wusste, dass die Arbeit mit Fragmenten aufwändig sein würde, hat Google im Vorfeld spezielle Tools dafür entwickelt. Die Klassen FragmentManager und FragmentTransaction akkumulieren alle Prozesse: Erstellen und Löschen neuer Fragmente, Übertragen von Daten usw.

Ich möchte darauf hinweisen, dass Klassen, die mit Fragmenten arbeiten, in zwei Versionen verfügbar sind. Ich empfehle die Verwendung einer neueren Version – das sind solche, die im Importpfad die Zeile android.support.v4 haben. Dies ist eine große Bibliothek, die aus Gründen der Abwärtskompatibilität erstellt wurde. Google-Unternehmen behandelt Geräte auf allen Betriebssystemversionen sorgfältig und Bibliotheken ermöglichen die Nutzung von Entwicklungsinnovationen auch bei der Arbeit mit der alten API.

Android.support.v4.app.FragmentTransaction importieren; Android.support.v4.app.Fragment importieren;...

FrameLayout

Oft kommen Daten in der Benutzeroberfläche dynamisch, abhängig von laufenden Ereignissen. Um ein Bild oder einen Text irgendwo platzieren zu können, gibt es einen speziellen Container – FrameLayout. Dies ist seine Hauptaufgabe – Platz auf dem Bildschirm für jedes Objekt der View-Klasse zu reservieren, das später geladen werden kann. In solchen Behältern leben auch Fragmente.

Sie können FrameLayout auf unterschiedliche Weise ein neues Fragment hinzufügen: FragmentTransaction verfügt über ähnliche Funktionen zum Ersetzen und Hinzufügen von Methoden.

Transaction.replace(R.id.frame_container, fragmentObject);

Trotz der äußerlichen Ähnlichkeit müssen Sie ein gutes Verständnis dafür haben, welche Ergebnisse Sie erzielen können. Die Ersetzungsmethode funktioniert sehr einfach: Sie fügt ein Fragment hinzu und löscht die alten Fragmente, wenn sich zuvor etwas im Container befand.

Transaction.add(R.id.frame_container, fragment);

Die Add-Methode erstellt einen Stapel von Fragmenten und jedes neue Herausforderung schiebt eine neue Instanz an die Spitze des Stapels. Es ist wichtig, dass alte Objekte auf dem Stapel beim Erscheinen eines neuen Fragments keine Benachrichtigungen erhalten und so tun, als wäre nichts passiert. Dies bedeutet, dass die onPause-Methode für sie nicht ausgeführt wird und sie weiterhin Geräteressourcen verbrauchen, obwohl der Benutzer sie nicht mehr sieht.

Eine solche Verschwendung von zugewiesenem Speicher kann beispielsweise gerechtfertigt sein, wenn Sie die Datenvorverarbeitung organisieren möchten: Ein Fragment kann etwas laden, während es unsichtbar ist, und dann das fertige Ergebnis anzeigen.

Es kann mehrere Aktionen mit Fragmenten geben; sie werden akkumuliert, bis die Commit-Methode ausgeführt wird.

Transaction.commit();

Die Fortsetzung steht nur Mitgliedern zur Verfügung

Option 1: Treten Sie der „Site“-Community bei, um alle Materialien auf der Site zu lesen

Durch die Mitgliedschaft in der Community innerhalb des angegebenen Zeitraums erhalten Sie Zugriff auf ALLE Hacker-Materialien, erhöhen Ihren persönlichen kumulativen Rabatt und können eine professionelle Xakep-Score-Bewertung erwerben!

Zum allgemeinen Verständnis habe ich mich auch dazu entschlossen, den Lebenszyklus eines Fragments in Verbindung mit dem Lebenszyklus einer Aktivität zu untersuchen, der auftritt, wenn eine Aktivität mit einem Fragment gestartet und zerstört wird. Das Ergebnis ist folgendes:


Liste der abgefangenen Fragmentmethoden

Drei Hauptmethoden, die in fast jeder Anwendung verwendet werden:

onCreate— Initialisierung der internen Komponenten des Fragments mit den gespeicherten Daten.

onCreateView— Generierung einer Komponente zur Anzeige.

onPause— Umgang mit der Situation, wenn ein Fragment den Fokus verliert.

Beschreibung aller Methoden in der Reihenfolge ihres Aufrufs:

onAttach— die erste Verbindung eines Fragments mit einer Aktivität. Hier wird die Aktivität übermittelt, zu der die Verbindung hergestellt wird.

onCreate— Fragmentinitialisierung. Hier werden Daten aus der Bundle-Klasse über den letzten Status des Fragments in seinem vorherigen Leben (falls vorhanden), die zuvor beispielsweise in der Methode onSaveInstanceState gespeichert wurden, übergeben, um diesen Status wiederherzustellen. Zu diesem Zeitpunkt befindet sich die Aktivität noch im Erstellungsprozess.

onCreateSicht — Bildung der Ansicht zur Anzeige. Gibt die Ansicht des Fragments zurück. Kann zurückkehren null für nicht-visuelle Komponenten. Hier werden Daten aus der Bundle-Klasse über den letzten Status des Fragments sowie der Aktivitätscontainer übergeben, in dem das Fragment und der Markup-„Inflator“ verbunden werden.

AnSichtErstellenD – Wird aufgerufen, wenn die Ansicht erstellt wird. Hier werden die generierten Ansichts- und Bundle-Klassendaten zum letzten Status des Fragments übergeben. Wird verwendet, um die Ansicht fertigzustellen, bevor der gespeicherte Zustand wiederhergestellt wird. Zu diesem Zeitpunkt ist die Ansicht noch nicht mit dem Fragment verknüpft.

onActivityCreateD - Endgültige Initialisierung. Wird aufgerufen, wenn die onCreate()-Methode der Aktivität zurückgegeben wurde. Die Aktivität wird erstellt, das Fragment wird darin eingefügt. Wird beispielsweise verwendet, um den Zustand eines Fragments wiederherzustellen. Hier werden Daten aus der Bundle-Klasse über den letzten Zustand des Fragments übergeben.

onViewStateRestored — Initialisierung der Ansicht basierend auf dem gespeicherten Zustand. Wird aufgerufen, wenn der gespeicherte Zustand der Ansicht wiederhergestellt wird.

onSaveInstanceState— Speichern des Status des Fragments. Es funktioniert nur, wenn das Fragment stoppt und vom System getötet werden kann, aber tatsächlich noch benötigt wird. Dies geschieht beispielsweise beim Aufruf der nächsten Aktivität, beim Betätigen des Home-Buttons, aber auch im Falle einer vollständigen Zerstörung der Aktivität und deren Neuanlage infolge einer Änderung der Gerätekonfiguration (Sprachwechsel). , Eingabegerät, Bildschirmausrichtung usw.). Ein Objekt der Bundle-Klasse, das den Status der Aktivität speichert, wird an die Methoden onCreate, onPostCreate und onRestoreInstanceState übergeben. Aufmerksamkeit! Die Methode kann jederzeit vorher aufgerufen werden onDestroy!

onDestroyView– Wird aufgerufen, wenn eine Ansicht von einem Fragment getrennt wird. Wenn das Fragment das nächste Mal angezeigt wird, wird eine neue Ansicht generiert.

onDetach– Wird aufgerufen, bevor das Fragment von der Aktivität getrennt wird.

Letzte Aktualisierung: 30.10.2015

Jede Fragmentklasse erbt von der Basisfragmentklasse und hat ihren eigenen Lebenszyklus, der aus mehreren Phasen besteht:

    onAttach(): Wenn diese Methode ausgeführt wird, wird das Fragment einer bestimmten Aktivität zugeordnet. Zu diesem Zeitpunkt sind das Fragment und die Aktivität noch nicht vollständig initialisiert.

    onCreate(): Das Fragment wird erstellt. Diese Methode wird aufgerufen, nachdem die entsprechende onCreate()-Methode der Aktivität aufgerufen wurde.

    onCreateView() : Das Fragment erstellt die visuelle Schnittstelle

    onActivityCreated(): Wird aufgerufen, nachdem die Aktivität erstellt wurde. Ab sofort kann über die Methode findViewById() auf Schnittstellenkomponenten zugegriffen werden

    onStart(): Wird aufgerufen, wenn das Fragment sichtbar wird

    onResume(): Das Fragment wird aktiv

    onPause() : Das Fragment bleibt sichtbar, ist aber nicht mehr aktiv

    onStop(): Das Fragment ist nicht mehr sichtbar

    onDestroyView(): Die Schnittstelle, die das Fragment darstellt, wird zerstört

    onDestroy(): dauerhafte Zerstörung des Fragments

Im Fragmentklassencode können wir alle oder einige dieser Methoden überschreiben.

Da Fragmente häufig für bestimmte Zwecke verwendet werden, beispielsweise um eine Liste einiger Objekte anzuzeigen, haben wir standardmäßig Zugriff auf von Fragment abgeleitete Klassen, die bereits über bestimmte Fähigkeiten verfügen:

    ListFragment: verwaltet eine Liste von Elementen mithilfe eines der Adapter

    DialogFragment: wird zum Erstellen von Dialogfeldern verwendet

    PreferenceFragment: Wird zum Verwalten von Anwendungseinstellungen verwendet

Sie können reguläre Klassen verwenden, um ein neues Fragment zu erstellen. Allerdings die Umwelt Android Studio bietet bereits eine Reihe integrierter Vorlagen:

Beim Erstellen werden Sie aufgefordert, den Projektnamen, den Namen der Schnittstellen-Markup-Datei und eine Reihe weiterer Optionen festzulegen:

Die von Android Studio generierte Fragmentklasse ähnelt weitgehend den zuvor verwendeten:

Paket com.example.eugene.testapp; Android.app.Activity importieren; android.net.Uri importieren; android.os.Bundle importieren; android.app.Fragment importieren; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; öffentliche Klasse BlankFragment erweitert Fragment ( private static final String ARG_PARAM1 = "param1"; private static final String ARG_PARAM2 = "param2"; private String mParam1; private String mParam2; private OnFragmentInteractionListener mListener; // Factory zum Erstellen des Fragments public static BlankFragment newInstance( String param1, String param2) ( BlankFragment fragment = new BlankFragment(); Bundle args = new Bundle(); args.putString(ARG_PARAM1, param1); args.putString(ARG_PARAM2, param2); fragment.setArguments(args); return fragment ; ) public BlankFragment() ( // Constructor ) @Override public void onCreate(Bundle savingInstanceState) ( super.onCreate(savedInstanceState); if (getArguments() != null) ( mParam1 = getArguments().getString(ARG_PARAM1); mParam2 = getArguments().getString(ARG_PARAM2); ) ) @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savingInstanceState) ( return inflater.inflate(R.layout.fragment_blank, container, false);

) public void onButtonPressed(Uri uri) ( if (mListener != null) ( mListener.onFragmentInteraction(uri); ) ) @Override public void onAttach(Activityactivity) ( super.onAttach(activity); try ( mListener = (OnFragmentInteractionListener) Aktivität; ) Catch (ClassCastException e) ( throw new ClassCastException(activity.toString() + " muss OnFragmentInteractionListener implementieren); ) ) @Override public void onDetach() ( super.onDetach(); mListener = null; ) public interface OnFragmentInteractionListener ( public void onFragmentInteraction(Uri uri); ) )

Daher können wir Fragmente manuell erstellen oder eine der von Android Studio bereitgestellten Vorlagen verwenden. Wenn man über die Entwicklung für Android spricht, ist es unmöglich, es nicht zu erwähnen.

Fragmente

Was ist Fragment?

Fragment ist ein spezielles Schnittstellenelement, das die Erstellung reaktionsfähiger Anwendungen erleichtern soll, die sowohl auf Smartphones als auch auf Tablets funktionieren.

  • Ein Fragment enthält wie eine Aktivität selbst Schnittstellenelemente. Allerdings gibt es einige wesentliche Unterschiede zwischen den beiden Konzepten: Fragment darin enthalten.
  • Aktivität darin enthalten es können mehrere sein Fragmente, das heißt, es können mehrere Fragmente gleichzeitig auf dem Bildschirm sein, wohingegen darin enthalten immer allein zu jeder Zeit.

Implementierung einer Anwendung ohne Fragmente

Werfen wir einen Blick darauf konkretes Beispiel um besser zu verstehen, wie es funktioniert.

Stellen wir uns vor, wir haben eine Anwendung mit zwei Bildschirmen:

  • Bildschirm mit Newsfeed.
  • Durch Klicken auf ein Listenelement in der vorherigen Aktivität wird ein Bildschirm mit Details zu den Neuigkeiten geöffnet.

So sieht es am Telefon aus:


Es stellt sich heraus, dass wir zwei Aktivitäten haben, von denen jede bestimmte Schnittstellenelemente enthält. Dies seien FeedActivity für den ersten Bildschirm und DetailActivity für den zweiten Bildschirm.

Stellen Sie sich nun vor, dass wir auch einen Antrag für das Tablet stellen müssen:


In diesem Fall zeigen wir Inhalte von beiden Bildschirmen auf einem Bildschirm an und verwenden dabei die gleichen Elemente. Es stellt sich heraus, dass wir eine dritte Aktivität benötigen, zum Beispiel TabletFeedActivity.

Wird dieser Ansatz funktionieren? Ja. Ist es richtig? Absolut nicht.

Wenn wir diesen Ansatz verwenden, erstellen wir nicht nur zusätzliche unnötige Aktivitäten, sondern verlieren auch die Möglichkeit, den Code wiederzuverwenden – fast der gesamte Code in TabletFeedActivity wird einfach von FeedActivity und DetailActivity kopiert!

Und hier kommen uns Fragmente zu Hilfe!

Implementieren einer Anwendung mit Fragmenten

Wir verlassen FeedActivity und DetailActivity , führen aber zwei zusätzliche Klassen ein – FeedFragment ( Fragment Nr. 1 im Bild unten) und DetailFragment ( Fragment Nr. 2 im Bild unten).

Bei Verwendung eines Telefons befindet sich FeedFragment in FeedActivity und DetailFragment in DetailActivity:

Wenn die Anwendung auf einem Tablet ausgeführt wird, fügen wir beide Fragmente zu FeedActivity hinzu, DetailActivity wird überhaupt nicht verwendet. Alle!


Auf diese Weise schreiben wir keinen unnötigen Code und unsere Anwendung wird vollständig anpassungsfähig.

Das Gleiche wie bei darin enthalten, ja Fragment Es gibt einen Lebenszyklus.

Ein Fragment kann drei Zustände haben:

  • Angehalten- Fragment ist auf dem Bildschirm nicht sichtbar. Es existiert, steht aber nicht für Benutzerinteraktionen zur Verfügung und kann zerstört werden, wenn die damit verbundene Aktivität zerstört wird.
  • Ausgesetzt- Das Fragment ist auf dem Bildschirm sichtbar, kann aber von anderen Oberflächenelementen verdeckt werden (z. B. wenn sich eine andere Aktivität im Vordergrund befindet).
  • Wieder aufgenommen- Fragment ist auf dem Bildschirm sichtbar und für den Benutzer zugänglich.

Schauen Sie sich die Tabelle der Fragment-Rückrufe an, die entsprechend aufgerufen werden, wenn sich der Aktivitätsstatus ändert:

Schauen wir uns einige davon an.

  • onAttach() - Fragment„angehängt“ an darin enthalten.
  • onCreate() - Fragment entsteht.
  • onCreateView() – wird aufgerufen, um Schnittstellenelemente zu erstellen (z. B. eine Inflate-Funktion aus XML).
  • onActivityCreated() – wird aufgerufen, nachdem die onCreate()-Methode verarbeitet wurde darin enthalten.
  • onDestroyView() – wird aufgerufen, wenn die in onCreateView erstellte Ansicht vom Fragment „getrennt“ wird.
  • onDetach() - Fragment„löst“ sich von darin enthalten.

Im Allgemeinen ist alles der Aktivität sehr ähnlich, mit Ausnahme einiger neuer Rückrufe.

Versuchen wir es in der Praxis

Fragmente hinzufügen

Lassen Sie uns eine Anwendung erstellen, die zwei Fragmente enthält:

  • Ein Fragment mit Schaltern, mit denen wir eine Farbe auswählen.
  • Ein Fragment, das einfach mit der ausgewählten Farbe gefüllt wird.

Auf dem Telefon gibt es zwei Bildschirme – auf dem ersten wählen wir eine Farbe aus, woraufhin die Aktivität mit einem Fragment gestartet wird, das die Farbe anzeigt.

Das Tablet verfügt nur über einen Bildschirm mit einer Benutzeroberfläche mit zwei Bedienfeldern, genau wie in dem Beispiel, das ich oben gegeben habe.

Lassen Sie uns zunächst herausfinden, wie wir ein Fragment erstellen und es einer Aktivität hinzufügen können.

Erstellen Sie ein neues Projekt und darin ein neues Fragment:

Die öffentliche Klasse SelectionFragment erweitert Fragment ( public SelectionFragment() ( ) @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savingInstanceState) ( return super.onCreateView(inflater, container, savingInstanceState); ) )

Bitte beachten Sie: Das Fragment muss einen Konstruktor ohne Parameter haben und es dürfen keine anderen Konstruktoren vorhanden sein, da diese bei der Neuerstellung des Fragments nicht aufgerufen werden.

Wir werden auch eine Datei mit dem Layout für das Fragment erstellen – fragment_selection.xml:

Füllen wir nun das Layout innerhalb der onCreateView()-Methode aus:

@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savingInstanceState) ( View view = inflater.inflate(R.layout.fragment_selection, container, false); view.setBackgroundColor(Color.RED); return view; )

Ich habe die Farbe auf Rot gesetzt, um deutlich zu machen, wo sich das Fragment befindet.

Es gibt zwei Möglichkeiten, ein Fragment zu einer Aktivität hinzuzufügen:

  • Über XML. In diesem Fall ist es nicht möglich, das Fragment zur Laufzeit zu löschen.
  • Zur Laufzeit.

Hinzufügen eines Fragments zu XML

Versuchen wir, ein Fragment zu „activity_main.xml“ hinzuzufügen:

Starten Sie die Anwendung:

Hinzufügen eines Fragments zur Laufzeit

Ersetzen wir zunächst das MainActivity-Layout-Markup durch Folgendes:

FrameLayout dient in diesem Fall als Container für das Fragment.

Fügen Sie nun am Ende der onCreate()-Methode in MainActivity den folgenden Code hinzu:

SelectionFragment SelectionFragment = new SelectionFragment(); FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction() .add(R.id.container, SelectionFragment) .commit();

Wir erstellen ein Fragment, besorgen uns einen Fragmentmanager und fügen das Fragment dem Container hinzu.

FragmentManager ist eine spezielle Klasse, über die die Interaktion mit Fragmenten erfolgt.

Bitte beachten Sie: Es gibt zwei Implementierungen von Fragmenten im Android SDK: regulär und von Unterstützt Bibliotheken v4. Obwohl die meisten Beispiele im Internet die Support Library-Implementierung verwenden, ist es heutzutage eigentlich nicht notwendig, sie zu verwenden, da sie so konzipiert ist, dass Fragmente mehr funktionieren frühere Versionen Android als 3.0.

Seit 3.0 können Sie die reguläre Implementierung verwenden.

Wenn Sie die Anwendung starten, werden Sie feststellen, dass das Ergebnis dasselbe bleibt:

Erstellen eines Zwei-Panel-Layouts

Wir benötigen also zwei Layouts für MainActivity: eines für Telefone, Sekunde für Tabletten.

Lassen Sie uns ein Layout erstellen für Tablette. Dies geschieht auf die gleiche Weise wie gewohnt mit einem Unterschied:


Wie Sie sehen, habe ich das Qualifikationsmerkmal ausgewählt Kleinste Bildschirmbreite und gab den Wert 600 ein. Daher wird dieses Layout nur auf Geräten verwendet, deren Bildschirmbreite mindestens 600 dp beträgt. Dies entspricht in etwa einem Tablet mit 7 Zoll Bildschirmdiagonale.

Standardlayout (z Telefone) wird so aussehen:

Da Android beim Erstellen von Schnittstellen eine möglichst deklarative Vorgehensweise empfiehlt und wir SelectionFragment nicht entfernen oder ersetzen müssen, deklarieren wir es direkt im XML.

Das Layout ist für Tabletten wird so sein:

Hier verwenden wir SelectionFragment auf die gleiche Weise, allerdings belegt es nicht den gesamten Bildschirm, sondern nur ein Drittel und zusätzlich haben wir einen Container für das zweite Fragment hinzugefügt – wir werden es zur Laufzeit ersetzen, also zu XML hinzufügen wird nicht funktionieren.

Da wir das SelectionFragment nicht mehr dynamisch hinzufügen, entfernen Sie den gesamten zugehörigen Code aus onCreate() in MainActivity .

Erstellen Sie außerdem einen neuen Emulator für das Tablet, beispielsweise so:


Starten Sie die Anwendung darauf:


Wie Sie sehen können, nimmt SelectionFragment auf einem Tablet die linken 30 % des Bildschirms ein. Der restliche Platz ist für das zweite Fragment reserviert, das noch nicht verfügbar ist.

Fahren wir fort, indem wir Optionsfelder hinzufügen, um Farben auszuwählen.

RadioButton und RadioGroup

RadioButton – eine Komponente zum Erstellen von Optionsfeldern. Da RadioButton nicht alleine verwendet werden sollte, gibt es auch ein Layout dafür – RadioGroup.

RadioGroup ist von LinearLayout geerbt und enthält mehrere RadioButtons. Es steuert die Exklusivität der Auswahl (schließlich kann pro Zeiteinheit nur ein Optionsfeld ausgewählt werden). Dank der Vererbung von LinearLayout kann es entweder vertikal oder horizontal sein.


Die Fortsetzung ist bei kostenpflichtigen Plänen möglich

Und dazu noch die Hausaufgabenkontrolle durch unsere Mentoren.

Es ist sehr günstig – nur ab 0 ₽ pro Monat!