Flexible UI kombiniert mit Swipe

  • Hey folks,


    ich habe eine Vorlage für den Aufbau einer flexiblen grafischen Oberfläche in mein Projekt übernommen und würde nun gerne diese um eine Swipe funktion erweitern.


    °°°Vorlage °°°


    Damit ihr wisst wovon ich rede... Das Fragment B soll swipebar sein. In Fragment A gibt es eine Liste von Elementen die ausgewählt werden können. Nach dem auswählen eines Elements auf Fragment A erscheint auf Fragment B die swipebare Oberfläche.


    hier sieht man es ganz gut. Links die Liste und rechts kann man zischen Eingang und Ausgang swipen[Blockierte Grafik: http://preview.slick.pics/FTl6EN4cX.png
    Ist es also möglich auch eine Activity anstelle eine Fragments am Platz von Fragment B anzeigen zu lassen? Ich weiss nämlich nur wie ich diese Swipe Funktion auf einer Activity baue.
    Diese ganze Gescichte mit der flexiblen UI scheint ausschließlich auf Fragmenten zu basieren, stimmt das so?


    lg proto

  • Zitat

    Ist es also möglich auch eine Activity anstelle eine Fragments am Platz von Fragment B anzeigen zu lassen?


    Nein, ist es nicht.


    Du kannst Fragmente im Code schachteln.
    Via XML klappt das nicht so gut, aber im Code geht das.


    Sprich: links hast Du Dein ListFragment, rechts ein Fragment mit einem ViewPager.


    Zitat

    Diese ganze Geschichte mit der flexiblen UI scheint ausschließlich auf Fragmenten zu basieren, stimmt das so?


    Ja, das stimmt so.


    Da Fragmente vom prinzipiellen Aufbau den Activities ähnlich sind, dürfte sich Dein Wissen mit den Activities auch auf Fragmente ummünzen lassen.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • ok das klingt ja schon mal super, Danke.


    Wie du auf meinem Screenshot von oben siehst ist es mir auch schon gelungen die Swipe-View auf das Fragment B zu legen, nur habe ich das Problem das keine neue Swipe-Area für jedes Element in der Liste von Fragment A generiert wird.


    ein Beispiel: auf meinen Swipe Seiten (Eingang, Ausgang,...) sind viele Checkboxen zu sehen. Wähle ich nun aus der Liste "PBM One" und hake die ersten vier checkboxen auf der Swipe-Area an, bleiben diese ebenfalls aktiviert wenn ich auf "PBM Two" (oder ein anderes) wechsle .


    Ich weiss etwas viel Quelltext aber hier mal meine MainActivity, in der ganz unten die Umschaltung der Swipe-Areas geregelt werden sollte. Vielleicht fällt jemandem ein Fehler auf.


  • Also für mich sieht das so aus, als wären die Fragmente, die Du anlegst, ziemlich allgemein gehaltene Fragmente.
    Ich sehe nirgendwo, wie diese auf ihre Daten zugreifen.


    Vermutlich nutzen sie alle dieselbe Datenquelle, welche von dem Wechsel der BPM nichts mit bekommt.
    Hier hilft bestimmt der Einsatz des Debuggers. :)

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Den Datenzugriff der einzelnen Fragmente hab ich noch nicht geregelt.


    Es ist mir nur unverständlich da jedes mal wenn ich ein PBM aus der Liste wähle in Zeile 66 die Funktion makeSectionsPagerAdapter(position); aufgerufen wird.


    Diese macht einen neuen SectionsPagerAdapter ( mit den genannten Fragmenten ) in ein vorhandenes Array an die Position <position> ( Zeile 193 ), und der mViewPager setzt den neu generierten SectionsPagerAdapter als Adapter.


    Somit sollte zumindest bei jedem PBM in der Liste ein neu generierter SectionsPagerAdapter angezeigt werden, aber nicht mal das ist der Fall. :-/


    Wenn ich meinen Code durchschaue finde ich keinen Fehler weil für mich alles einen Sinn ergibt.

  • +hm+
    Ich weiß nicht, ob Du einfach so den PagerAdapter hinter dem View austauschen kannst.
    Auch bin ich mir nicht sicher, ob Du in dem Fall nicht noch irgendwie dem UI erklären musst sich neu zu zeichnen.


    Ganz davon abgesehen bin ich mir aber sicher, dass der Ansatz so der falsche Ansatz ist.
    Du verknüpfst die Werte eines Datenmodells direkt mit einer bestimmten UI Darstellung, nämlich einem eigenen PagerAdapter.
    Damit verstößt Du einerseits gehörig gegen das MVC Pattern und andererseits erhöht sich dann mit jedem Klick der Speicherverbrauch Deiner App.
    UI Elemente sind 'teuer' (in Bezug auf die zur Generierung notwendige Systemleistung) und Du erstellst halt fröhlich mit jedem Klick einen neuen ViewPager, der von support.v4.view abgeleitet ist und damit ein UI Element darstellt. Klar, GC räumt das irgendwann weg, hoffentlich. Du weißt halt nur nicht, wann dieses 'irgendwann' ist.
    (Selbst wenn Du bereits existierende ViewPagerAdapter wiederverwendetest, hättest Du immer noch 5x 4 unterschiedliche, also 5 identische Views statt insgesamt 4 unterschiedliche Vies – und es werden immer nur maximal die 4 angezeigt.)


    Ich würde zunächst (ganz langweilig und trocken, weil man nix sieht) einen ContentProvider für die angeschlossenen PBM erstellen.
    (ContentProvider deshalb, weil Du dann damit auch von anderen Apps auf dieselben PBM und ihre Daten zugreifen kannst, ohne die Implementierung da nachbauen zu müssen. Beispielsweise ein Hilfstool zu Deiner App, die nur Geräteinformationen der PBM ausliest, eine Installation Deiner App aber voraussetzen soll.)


    Wenn dieser beispielsweise 'public ArrayList getConnectedPBM()' implementiert, kannst Du das Resultat als Quelle für Deine Auswahl nutzen.
    Noch einen Callback eingerichtet, der Dich über neu angeschlossene oder getrennte PBM informiert, dann kannst Du Änderungen auch ziemlich zeitnah im UI anzeigen.


    Naja, und wenn sich die Auswahl ändert, gibst Du den PBM an der Position in der Liste an den PagerAdapter weiter, der dann all seine Fragmente über die Änderung informiert und +zack+ stehen die neuen Daten wo sie hingehören.


    [Für Testzwecke sollte der Titel des Pagers angepasst werden. Also statt statisch 'Eingang' dynamisch 'PBM One: Eingang'. Idealerweise stammt das aus einem PBM Objekt über den Getter 'public string getTitle()']

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • WTF, da sieht man das Android um einiges kniffliger ist als Java für sich.


    Ich
    glaube ich werde mal überdenken ob ich so weiter machen werde.
    Vermutlich werde ich mich aber erst ein bisschen besser einarbeiten
    bevor ich dieses Projekt neu aufziehe.

    Hm, das hört sich schon sehr nach Anfänger an :P

    Zitat

    Ich würde zunächst (ganz langweilig und trocken, weil man nix sieht)
    einen ContentProvider für die angeschlossenen PBM erstellen.

    soll das separat zu installieren sein? So als Schnittstelle zwischen PBM und den Apps?

  • Naja, in Java für den Desktop nutzt Du ja Swing für so User Interface Krams.


    Tatsächlich sind diese Fragmente mit etwas mehr Hirnschmalz verbunden als normale Views.
    Als Android aber für Tablets raus kam musste man halt fest stellen, dass man nur mit Activities nicht weit kommt. Dementsprechend finde ich die Integration der Fragmente auch noch nicht soooo 100%ig gut gelungen. iOS ist da mit seinen View Controllern einige Schritte weiter, allerdings nutzen die den Kram seit den ersten Versionen genau so, wie sie auch heute noch sind.


    Wenn sich das nach 'Anfänger' anhört, ist das doch legitim. So heißt ja das Unterforum auch. ;)
    Tatsächlich sind das aber Erfahrungen, die man selbst erst einmal sammeln musste. ^^


    Nein, das ist eine Komponente, die mit Deinem Programm mitinstalliert wird und auf die andere Programme zugreifen können, wenn sie wissen wie damit zu kommunizieren ist.
    Dann ist es eine Schnittstelle zwischen den PBM und den Apps. So wie Android selbst ContentProvider für Kalender, Kontakte, Medien etc.pp. bietet.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Ich muss leider meine Idee hier wieder aufgreifen weil ich anders einfach nicht weiter komme.
    Dazu eine relativ simple Frage: Das ganze mit der flexiblen UI funktioniert soweit, wenn ich die App auf Phone und Tablet teste.
    Sobald ich nun meinen SectionsPagerAdapter (wir befinden uns in der MainActivity) einbauen lasse funktioniert die App nur noch auf dem Tablet.


    Ich habe nun, wie auf dem Screenshot weiter oben zu sehen ist, beim Tablet 2 Fragmente nebeneinander (links ListFragment, rechts FragmentPagerAdapter)
    Eingebaut wird das ganze hiermit...


    Teste ich die App nun auf dem Phone schmiert mir die ganze Sache ab sobald ich auf ein Elemnt im ListFragment klicke, und zwar an dieser Stelle...

    Java
    mViewPager.setAdapter(mSectionsPagerAdapter);


    mit der Fehlermeldung...


    Eigentlich sollte es doch für ein Fragment kein Problem sein einen FragmentPagerAdapter in den Adapter zu lade, oder?
    Oder liegt das Problem am ViewPager?

  • Die Fehlermeldung besagt, das irgendwas (vermutlich mViewPager) null ist.


    Und null.setAdapter(mSectionsPagerAdapter) funktioniert* meines Wissens nur unter Objective-C.


    Welches Layout auch immer er sich für das Phone zieht, ein View mit der ID R.id.pager dürfte er da schlicht nicht haben.




    *) "funktioniert" im Sinne von: Programm läuft weiter statt eine Exception zu werfen. Das Resultat findet natürlich nicht statt und beim Versuch die Änderungen zu lesen bekommt man auch nix zurück.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Vermutlich wird der im Layout des Phones einfach nicht gefunden?


    Frag doch einfach den Debugger, der beißt nicht. :)

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Frag doch einfach den Debugger, der beißt nicht. :)

    Klasse ^^ ^^ ^^ ^^ Aber ich bin wohl im Umgang damit noch nicht so geübt wie manch anderer. Ich lass ihn laufen und taste mich step by step vor, wenn er dann crasht schau ich mir die Fehlerausgaben an, bzw. starte ihn neu und schaue die Variablen kurz vorm crash an.



    Ich vermute ganz stark das es damit zusammen hängt das auf dem Tablet beide Fragmente (A, B) immer zu sehen sind und deshalb kann ich mir mit findViewByID den ViewPager holen. Aber beim Phone ist das zweite Fragment (B) noch nicht zu sehen! deshalb wird sehr wahrscheinlich findViewByID nix finden.



    Wenn ich ein Item aus der Liste wähle -> ins if läuft er beim Tablet rein, ins else beim phone


    in beiden Fällen wird ein SiteFragment erstellt...


    dieses wiederum inflatet mein site_view


    auf dem sich mein @+id/pager befindet.
    Wie könnte ich also dieses zeitliche Problem umgehen und erst dann nach dem ViewPager fragen wenn das Fragment auch wirklich aufgebaut ist?

  • Mein erster Versuch wäre herauszufinden, wie oft er versucht den mViewPager abzufragen.
    Dazu alle Arbeiten am mViewPager in ein Konstrukt packen, das vorher prüft, ob mViewPager auch ja nicht null ist.


    Manuell warten musst Du da eigentlich nicht, da das alles nacheinander abgearbeitet wird.
    Andererseits sagt die Dokumentation zur Commit–Methode:

    Zitat

    Schedules a commit of this transaction. The commit does not happen immediately; it will be scheduled as work on the main thread to be done the next time that thread is ready.


    Du könntest also versuchen, via transaction.executePendingTransactions(); dafür zu sorgen, dass das Ganze sofort umgesetzt wird.


    Ich bin aber nach wie vor der Meinung, dass ein Neuerstellen der Pager nach Auswahl eines Items der nicht so ganz korrekte Ansatz ist. ;)
    Das merkt man eigentlich immer dann, wenn etwas nicht so reibungslos funktioniert wie es sollte.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

  • Ich bin aber nach wie vor der Meinung, dass ein Neuerstellen der Pager nach Auswahl eines Items der nicht so ganz korrekte Ansatz ist. ;)

    Diese Methode hab ich nach deinem Rat auch verworfen, es geht sozusagen um die Erstinitialisierung des FragmentPagers. Nach dem Klick auf ein Item, sollte das neue Fragment zusammengebaut und darauf der FragmentPager erstellt werden.


    EDIT:
    Die Methode ".executePendingTransactions();" kennt er nicht ;(

  • Was geht an fragmentManager.executePendingTransactions() denn nicht?

    Oh sorry, stand total auf dem Schlauch :P ^^ ^^



    Auf jeden Fall schafft er es nun den ViewPager zu finden, läuft aber bisl später in eine Exception rein, bei...getListView().setItemChecked()


    und zwar genau in der ListFragment Klasse bei... getView()


    Also entweder ist der Weg zu einer komfortablen App sehr steinig und ich muss immer wieder solche schwierigkeiten umschiffen, oder ich befinde mich einfach nur auf dem Holzweg und habe einen total falschen Ansatz.


    Noch eine Frage am Rande, eigentlich sollten Fragmente den Activities sehr ähnlich sein, bin ich dann der einzige der irgendwie Schwierigkeiten hat mit Fragmenten zu arbeiten? Wenn ich mit Activities arbeite ist jede für sich wie eine kleine "Sandbox", dort kann ich alle möglichen Sachen anstellen (weitere Activities starten, Fragmente erzeugen und anzeigen, Fragmente austauschen, usw...).
    Habe ich ein Fragment tue ich mir aber irgendwie schwer von dort als Startpunkt weitere tolle Funktionen zu nutzen...

  • Naja, das bedeutet ja nur, dass Deinem einzelnen Fragment kein View zugeordnet ist.


    Was tust Du denn in der onCreateView() Deines Fragmentes?


    Ich hätte ja schon echt Bock Dir weiterzuhelfen, allerdings häng ich gerade an einem iOS Projekt, dessen Fertigstellungstermin immer näher rückt.
    Deshalb kann (und will) ich Dir das Grundgerüst nicht mal eben zusammenzimmern…


    Kannst Du das irgendwie bei GitHub, GitLab, BitBucket oder ähnlichen Anbietern hochladen?
    (Beziehungsweise die Frage, die eigentlich davor gekommen wäre: hast Du schon mal mit einem Source Code Management System wie Git gearbeitet?)


    Dann würde ich in meiner Pause mal rasch reinschauen.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!