Mobile Anwendungen für iOS, Android und BlackBerry Touch

Sencha Touch
Kommentare

Einrichten der Panels

Die beschrifteten Icons (Home, Bookmarks, Detailansicht), die Sie im unteren Bereich von Abbildung 1 sehen, ist die eben erwähnte TabBar. Die Beschriftung und das Icon sind jeweils

Einrichten der Panels

Die beschrifteten Icons (Home, Bookmarks, Detailansicht), die Sie im unteren Bereich von Abbildung 1 sehen, ist die eben erwähnte TabBar. Die Beschriftung und das Icon sind jeweils Eigenschaften der konfigurierten Panels (Configoptionen title und iconCls). Für die Icons liefert Sencha Touch bereits eine Vielzahl nützlicher Icons, die Sie über iconCls: bookmarks nutzen können. Eine vollständige Liste finden Sie z.B. in der generell sehr hilfreichen Kitchen-Sink-Demo [6]. Wie die Definition des Home-Panels mit Titel und Icon aussieht, zeigt Listing 4. Den kompletten Quelltext finden Sie in der Datei js/lib/Home.js.

Listing 4

Score11.Mobile.Home = Ext.extend(Ext.form.FormPanel, {
    iconCls: 'home',
    title: 'Home'
});
Listen

Wie Sie in Abbildung 1 bereits sehen können, wird auf der Startseite eine Liste mit Filmtiteln angezeigt. Diese Listen sind in mobilen Apps und Anwendungen recht geläufig und können in Sencha Touch sehr einfach erstellt werden. Seit Version 1.1.0 bietet Sencha Touch zudem auch noch zwei sehr nützliche Plug-ins für die Listen: Paging und PullRefresh. Wie Sie solche Listen erstellen und wofür die Plug-ins gut sind, sollen Sie als Nächstes erfahren.

Prinzipiell besteht so eine Liste aus zwei Komponenten: der Liste selber und einem Store, also einer Komponente, welche die Daten lädt und bereitstellt. In der Beispielanwendung erstelle ich erst einmal den Store, der anschließend beim Erstellen des Home-Panels als Argument mitgegeben wurde. Somit kann die Liste an anderer Stelle problemlos mit einem anderen Store verwendet werden.

Ein Store benötigt an sich nur zwei Configoptionen, um lauffähig zu sein: Model und Proxy. Das Model gibt die Struktur der Daten an, der Proxy kümmert sich um die Beschaffung und Bereitstellung der Daten (das wird meistens ein AJAX-Proxy sein, kann aber auch Memory für lokal gespeicherte Daten, Script-Tag u.v.a. sein). Ebenfalls im Proxy wird der Reader definiert, der entsprechend dem Datenformat konfiguriert sein muss. In unserem Fall haben wir in der Liste im Home-Panel einen Script-Tag-Proxy (theoretisch wäre es ein AJAX-Proxy, aufgrund der Same Origin Policy von XHR musste ich allerdings auf den Script-Tag-Proxy zurückgreifen) mit einem JSON-Reader, die Daten liegen in etwa folgendem Format vor: {movies: [{„movieID“:“48054″,“title“:“Merlin – Vergifteter Kelch“,“year“:“2008″},{…}, total: 5}. Für den Script-Tag-Proxy bedurfte es einer minimalen Änderung aufgrund der Implementation des Proxies, Genaueres dazu finden Sie in der Sencha Touch-API-Dokumentation [2]. Da wir später in der Anwendung zwei Stores haben werden, die dasselbe Model verwenden, habe ich noch eine Abstraktionsebene eingezogen. Wie ein Store dafür aussehen würde, sehen Sie in Listing 5.1 und Listing 5.2, auf der Heft-CD finden Sie den vollständigen Store in den Dateien js/store/RemoteMovieList.js und js/store/AbstractMovieList.js. Eine kleine Anmerkung noch zur Funktionalität: Das angegebene PHP-Script liefert immer 25 zufällige Filmtitel.

Listing 5.1

Ext.ns('Score11.Mobile.Store');

Score11.Mobile.Store.AbstractMovieList = Ext.extend(Ext.data.Store, {
    modelName: 'Movielist',
    pageSize: 25,
    clearOnPageLoad: false,
    constructor: function(passedConfig) {
        if (!passedConfig) {
            passedConfig = {};
        }
        this.createStoreModel();
        config = this.getDefaultConfig();
        Ext.apply(config, passedConfig);
        Score11.Mobile.Store.AbstractMovieList.superclass.constructor.call(this, config);
    },
    createStoreModel: function() {
        // Nichts machen, falls das Model bereits registriert wurde
        if(Ext.ModelMgr.isRegistered(this.modelName)) {
            return false;
        }
        Ext.regModel(this.modelName, {
            fields: [
                {name: 'movieID', type: 'int'},
                {name: 'title', type: 'string'},
                {name: 'year', type: 'int'}
            ]
        });
        return true;
    }
});

Listing 5.2

Ext.ns('Score11.Mobile.Store');

Score11.Mobile.Store.RemoteMovieList = Ext.extend(Score11.Mobile.Store.AbstractMovieList, {
    getDefaultConfig: function() {
        return {
            model: this.modelName,
            autoLoad: true,
            proxy: {
                type: 'scripttag',
                url: 'http://www.score11.de/germanTitles.php',
                reader: {
                    type: 'json'
                }
            }
        };
    }
});

Falls Sie bereits Erfahrung mit Ext JS gemacht haben, wird Ihnen sicherlich aufgefallen sein, dass das Model nicht, wie in Ext JS, per fields-Attribut im Store gesetzt wird, sondern dass hier ein Model-Manager verwendet wird, in dem das Model nur einmal definiert werden muss und dem Store nur noch der Modelname mitgeteilt wird. Für einmalige Models ist das sicherlich minimal mehr Tipparbeit, für den (gar nicht so unwahrscheinlichen Fall) identischer Models innerhalb der Applikation ist das aber schon ziemlich nützlich.

Nun, da wir den Store für die Liste fertig konfiguriert haben, können wir die Liste selber erstellen. Wie beim Store ginge auch das mit nur zwei Configoptionen (store und itemTpl). Da unsere Liste aber auch scrollbar sein soll, ist es nur mit den zwei Optionen nicht getan. Das Attribut itemTpl definiert, welche Informationen aus dem Store (definiert im Model) als Anzeige verwendet werden sollen. Variablen aus dem Store werden mit {} umklammert, Kombinationen wie {year} – {title} (Film) sind also problemlos möglich. Wie die Liste mit dem Store aus Listing 5.1 und 5.2 aussieht, zeigt Listing 6.

Listing 6

this.list = new Ext.List({
    height: '100%',
    scroll: 'vertical',
    itemTpl: '{title}',
    store: this.movieStore
});

Plug-ins für Listen

Seit Sencha Touch 1.1.0 gibt es zwei Plug-ins für Listen: PullToRefresh und Paging. Ersteres fügt der Liste eine Funktionalität hinzu, durch die sie neu geladen wird, wenn man sie weit genug nach oben zieht, ähnlich wie man es etwa von der Facebook- und Twitter-App für das iPhone kennt. Das Paging-Plug-in wiederum erweitert die Liste um (wie der Name bereits verrät) Paging. Standardmäßig wird dann einfach am Ende der Liste ein „Load More …“ ausgegeben, das beim Antippen die nächste Seite lädt (genauer wird eine Ladeoperation auf den Store getriggert, die die Parameter start und limit mit übermittelt – das Limit haben wir bereits vorher im Store mit dem Attribut pageSize festgelegt, siehe Listing 5.1). Das Paging-Plug-in ermöglicht es aber auch die nächste Seite automatisch zu laden, sobald man weit genug heruntergescrollt hat. Dazu muss man das Plug-in lediglich mit autoPaging: true konfigurieren. Erwähnt sei zudem noch, dass das Paging standardmäßig den Store jedes Mal leert und dann die neue Seite anzeigt. Möchte man eine fortlaufende Liste, muss man den Store mit clearOnPageLoad: false konfigurieren, was in Listing 5.1 bereits geschehen ist. Dann wird der Store nur noch beim PullToRefresh geleert. Beim Laden einer neuer Seite werden die Elemente unten angehängt. Um die Plug-ins nun der Liste zu übergeben, müssen wir sie in der Configoption plugins übergeben. Wie die Listendefinition dadurch aussieht, zeigt Listing 7, wie das PullToRefresh-Plug-in in Aktion aussieht, sehen Sie in Abbildung 2, das Paging-Plug-in in Abbildung 3.

Listing 7

this.list = new Ext.List({
    height: '100%',
    scroll: 'vertical',
    itemTpl: '{title}',
    store: this.movieStore
});

AAbb. 2: Das PullToRefresh-Plug-in in AktionAbb. 2: Das PullToRefresh-Plug-in in Aktion (Vergrößern)

Abb. 3: Das Paging-Plug-in in AktionAbb. 3: Das Paging-Plug-in in Aktion (Vergrößern)

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -