Diese Website verwendet Cookies, um Ihnen ein besseres Nutzungserlebnis bieten zu können. OK
14 Min Lesezeit 21 Kommentare

Apps entwickeln für Android und iPhone

Durch einen Artikel in der c't 16/2010 (Seite 96, Autonomie) bin ich auf die Möglichkeit aufmerksam gemacht worden, dass man native Apps für Android und iPhone nicht nur mit den offiziellen Entwicklungsumgebungen erstellen kann, sondern dass es diveres Crossplatform-Tools gibt, mit denen man seine App für mehrere Smartphone-Betriebssysteme entwickeln kann. Aus den vorgestellten Tools hat mir Appcelerator Titanium am Besten gefallen, bei dem man die Apps in JavaScript entwickelt, woraus Titanium dann eine native App compiliert. Also habe ich mich mal etwas damit auseinander gesetzt, eine kleine App geschrieben und einen Artikel dazu verfasst.

Musik am Smartphone: Streamen oder immer vorher über W-LAN laden?

Wähle Streamen oder W-LAN.

VS
  • 720
    Stimmen
    Ooops! Etwas ist schiefgelaufen. Aktualisieren sollte helfen.
    Streamen
  • 1300
    Stimmen
    Ooops! Etwas ist schiefgelaufen. Aktualisieren sollte helfen.
    W-LAN

Beginnen wir nun also mit unserem ersten selbst geschriebenen Projekt. Da heutzutage ja alle Welt ihre intimsten Gedanken auf Facebook, Twitter und Co. veröffentlicht, wie wäre es mit einer Tagebuch-App?. Diese soll bestehen aus einer Liste mit den Tagebucheinträgen, in der wir neue Einträge hinzufügen, bestehende ändern und löschen können. Desweiteren eine Seite mit Einstellungen, in der wir die maximale Anzahl an Tagebucheinträgen begrenzen können. Dabei behandeln wir folgende Elemente von Titanium:

  • TabGroup (Hauptansicht mit Tabreitern)
  • TableView (Liste mit mehreren Einträgen)
  • Window (Unterfenster zum Eingeben/Ändern von Tagebucheinträgen)
  • Buttons und Events (sowohl Standardevents, als auch selbstdefinierte)
  • Properties (eigene Daten lesen und schreiben)
  • Logging (Infos im Titaniumfenster ausgeben)

Zuerst erzeugen wir in Titanium ein neues Projekt über New Project:

Um den Code modifizieren zu können, müssen wir das Projekt in Eclipse importieren. Das geht am Besten, in dem wir über das Menü File - New - Project aufrufen und dort ein leeres Projekt namens Tagebuch anlegen. Wir müssen dabei darauf achten, ein allgemeines Projekt (General Project) anzulegen:

Auf dem folgenden Bildschirm geben wir dann noch den Projektnamen (Tagebuch) ein und beenden den Wizard mittels Finish. Nun haben wir in unserem Package Explorer ein leeres Projekt mit dem richtigen Namen. Über einen Rechtsklick auf das Projekt und Refresh aktualisieren wir die Anzeige in Eclipse und nach einem Doppelklick auf das Tagebuch-Projekt werden alle Dateien angezeigt, die uns Titanium erzeugt hat.

Zuerst editieren wir die app.js, die wir unter Resources finden. Diese stellt sozusagen das Hauptprogramm unserer Anwendung dar. Dort werden z.B. die Tabs und die dazugehörenden Fenster erzeugt. Wir löschen den bereits existierenden Inhalt und ersetzen ihn durch:

Titanium.API.info('app.js Start.');

var tabMain = Titanium.UI.createTabGroup();

// Das erste Tab enthält die Liste aller Tagebucheinträge
var winListe = Titanium.UI.createWindow({
    title:'Tagebuch',
    backgroundColor:'#ffffff',
    color:'#000000',
    url:'js/Liste.js',
    exitOnClose: true
});






var tabListe = Titanium.UI.createTab({
    title:'Tagebuch',
    window:winListe
});


// Auf das zweite Tab kommen die Einstellungen
var winEinstellungen = Titanium.UI.createWindow({
    title:'Einstellungen',
    backgroundColor:'#ffffff',
    color:'#000000',
    url:'js/Einstellungen.js',
    exitOnClose: true
});






var tabEinstellungen = Titanium.UI.createTab({
    title:'Einstellungen',
    window:winEinstellungen
});


// Und jetzt die Startansicht anzeigen
tabMain.addTab(tabListe);
tabMain.addTab(tabEinstellungen);

tabMain.open();

Titanium.API.info('app.js Ende.');

Die einfachste Art in Titanium die Oberfläche einer Anwendungen zusammenzubauen, ist mittels einer TabGroup. In diese kann man beliebig viele Tabs einhängen, die den einzelnen Seiten der Anwendung entsprechen. Jedes Tab benötigt allerdings noch ein Fenster, in dem dann die konkreten Oberflächenelemente dargestellt werden.

Unsere TabGroup besteht aus zwei Tabs, Tagebuch und Einstellungen. Für jeden Tab legen wir ein eigenes Fenster an. Über den url-Parameter bei createWindow kann man die JavaScript-Datei mitgeben, die den Programmcode für das entsprechende Fenster enthält. Daher legen wir auch als nächstes ein neues Unterverzeichnis unter Resources Namens js an und erzeugen in diesem zwei Datei namens Liste.js und Einstellungen.js. Je nach Projektgröße sollte man sich eine übersichtliche Verzeichnisstruktur überlegen. Wir werden einfach alle JavaScript-Dateien in das js-Verzeichnis packen. Erst wenn wir ein wirklich großes Projekt erstellen, lohnt es sich hier weitere Unterverzeichnisse anzulegen, wie z.B. eines für jedes Fenster usw.

Mittels exitOnClose können wir zumindest in der Android-Version festlegen, dass sich die Anwendung beenden soll, wenn im Fenster die Zurück-Taste gedrückt wird. Dies finde ich beim Entwickeln manchmal ganz nützlich, zum Beispiel wenn ich mir mehrmals anschauen möchte, ob der Start der Anwendung und das Laden der Daten einwandfrei funktioniert, denn Android behält die Anwendung ansonsten im Speicher, so dass die Initialisierung bei weiteren Aufrufen nicht mehr durchgeführt wird.

Kümmern wir uns nun um die Liste. Wir legen eine neue Datei namens Liste.js an. In dieser definieren wir zunächst das Tagebuch-Objekt. Dieses ist ein Array aus TagebuchEintraegen. Jeder TagebuchEintrag besteht aus einem Text (Eintrag) und aus einem Wert für unsere Laune (-1: schlecht, 0:mittel, 1:gut gelaunt). Mithilfe der im folgenden definierten Funktionen können wir recht elegant neue Einträge zu unserem Tagebuch hinzufügen.





Titanium.API.info('Liste.js Start.');

//Tagebuch-Liste definieren
var Tagebuch = new Array();

// Konstruktor
function TagebuchEintrag(Laune, Eintrag)
{
    this.Laune = Laune;
    this.Eintrag = Eintrag;
}




// Hinzufügen-Methode definieren und setzen
function EintragHinzufuegen(Laune, Eintrag)
{
    this[this.length] = new TagebuchEintrag(Laune, Eintrag);
}



Tagebuch.EintragHinzufuegen = EintragHinzufuegen;

Wer noch etwas Nachhilfe in JavaScript benötigt, findet im JavaScript-Workshop oder beim Galileo Openbook JavaScript zwei kostenlose Online-Bücher zur Programmiersprache.

Als nächstes lesen wir eventuell bereits vorhandene Daten ein. Dies geschieht über die Funktion Ti.App.Properties.getString bzw. getInt. Mit getInt wird, wie der Name schon andeutet, ein Integerwert gelesen. Mit getString kann man beliebige Datenstrukturen lesen, wenn man diese zuvor über JSON.stringify eingepackt hat. Auspacken können wir diese dann mit JSON.parse. Ob überhaupt etwas in den Properties gespeichert ist, fragen wir zuvor mit hasProperty ab, damit unsere Anwendung nicht auf die Nase fällt, wenn sie das allererste Mal aufgerufen wird. Was und wieviel geladen wurde, protokollieren wir über Titanium.API.Info; eine sehr hilfreiche Funktion, hat Titanium doch keinen Debugger!

// Tagebuch laden
if (Ti.App.Properties.hasProperty('Tagebucheintraege'))
{
    Tagebuch = JSON.parse(Ti.App.Properties.getString('Tagebucheintraege'));
    Titanium.API.info('Tagebuch geladen (' + Tagebuch.length + ' Einträge).');
}




//MaxAnzahl lesen
var MaxAnzahl = 10;
if (Ti.App.Properties.hasProperty('MaxAnzahl'))
{
    MaxAnzahl = Ti.App.Properties.getInt('MaxAnzahl');
    Titanium.API.info('Max. Anzahl = ' + MaxAnzahl + '.');
}





Nun merken wir uns das aktuelle Fenster in einer lokalen Variablen namens win. Anschließend erzeugen wir einen TableView, über den man Listen sehr einfach darstellen kann.

var win = Titanium.UI.currentWindow;

// Den TableView erzeugen
var tvListe = Titanium.UI.createTableView({
    editable:true
});


Das Flag editable sollte auf dem iPhone dafür sorgen, dass man einen Eintrag über einen Wisch von rechts nach links löschen kann. Ausprobieren konnte ich das allerdings noch nicht, da ich zur Zeit auf einem Windows-PC arbeite, auf dem nur die Android-Entwicklungsumgebung läuft. Für die iPhone-Entwicklung benötigt man ja leider zwingend einen Mac.

Für jeden Eintrag in unserem Tagebuch erzeugen wir eine TableViewRow. Wir setzen den Text auf unseren Eintrag und fügend gemäß unserer Laune noch ein Icon hinzu. Die Icons habe ich übrigens in der Wikimedia gefunden und einfach mittels Paint auf eine passende Größe verkleinert. Dann als PNG in das Unterverzeichnis images unter Resources abgespeichert. Mit createTableViewRow erzeugen wir eine neue Row, schreiben mit unserer selbstdefinierten Funktion SetzeTableRow die Inhalte hinein und fügen diese dann mit appendRow zum TableView hinzu. Nachdem wir alle Einträge des Tagebuchs hinzugefügt haben, ergänzen wir noch einen weiteren Eintrag namens "Neuer Eintrag...", über den wir dann später neue Einträge erfassen können.

// Schreibt die Daten in den TableView (insb. setzen der Icons)
function SetzeTableRow(row, n)
{
    row.title = Tagebuch[n].Eintrag;





    switch (Tagebuch[n].Laune)
    {
        case -1:
            row.leftImage = '../images/sad.png';
            break;




        case 0:
            row.leftImage = '../images/plain.png';
            break;

        case 1:
            row.leftImage = '../images/smile.png';
            break;
    }
}



// Und die einzelnen Zeilen hinzufügen
for (var n=0; n<Tagebuch.length;n++)
{
    var row = Ti.UI.createTableViewRow({color:'#000000'});
    SetzeTableRow(row, n);
    tvListe.appendRow(row);
}








// Leerer Eintrag für Hinzufügen
var row = Ti.UI.createTableViewRow({title:'Neuer Eintrag...',color:'#404040'});
tvListe.appendRow(row);


Nun benötigen wir einen EventListener, der aufgerufen wird, wenn der Anwender auf eine Zeile des TableViews tippt. Diesen definieren wir über tvListe.addEventListener('click', callback). 'click' ist der Event, auf den wir horchen und callback die Funktion, die aufgerufen werden soll, wenn der Event eintritt. Diese definieren wir direkt inline. Der callback-Funktion wird ein Objekt (e) übergeben, dass die Parameter des Events enthält. Von diesen benötigen wir e.index (den Index der angeklickten Zeile) und e.row (die TableViewRow der angeklickten Zeile). Zur besseren Kontrolle geben wir den Index im Titanium-Fenster aus. Als nächstes öffnen wir dann das Detailfenster, über das wir den ausgewählten Eintrag editieren wollen.

// Bei Klick auf den Eintrag soll ein Detailfenster aufgehen
tvListe.addEventListener('click', function(e)
{
    // Index des aktuellen Eintrags und dazugehörige TableViewRow merken
    var index = e.index;
    var row = e.row;




    Titanium.API.info('Eintrag (' + index + ') ausgewählt.');

    // Öffne Details-Fenster
    var wndDetails = Titanium.UI.createWindow({
        backgroundColor:'#ffffff'
    });


Das Detailfenster bekommt nun die folgenden Oberflächenelemente: eine Textarea zur Eingabe des Eintrags und drei Buttons zur Festlegung der Laune. Da jeder Button wieder einen eigenen EventListener bekommt, wird das folgende Codesegment etwas umfangreicher:

// Das Textfeld für den Eintrag ganz oben, wegen der Tastatur
var txtEintrag = Titanium.UI.createTextArea({
    value:(index < Tagebuch.length)? Tagebuch[index].Eintrag : '',
    top:20,
    width:300,
    height:150,
    suppressReturn:false
})
wndDetails.add(txtEintrag);







// Darunter die Buttons für den Gemütszustand

// Traurig
var btnSad = Titanium.UI.createButton({
    backgroundImage:'../images/sad60.png',
    borderColor:((index < Tagebuch.length) && (Tagebuch[index].Laune == -1))? '#00ff00' : '#000000',
    borderWidth:3,
    borderRadius:10,
    left:Titanium.Platform.displayCaps.platformWidth/2-110,
    top:190,
    width:60,
    height:60
});
wndDetails.add(btnSad);

// Beim Klick wird dieser Button aktiv (grüner Rahmen)
btnSad.addEventListener('click', function()
{
    btnSad.borderColor = '#00ff00';
    btnPlain.borderColor = '#000000';
    btnSmile.borderColor = '#000000';
});

// Unentschieden
var btnPlain = Titanium.UI.createButton({
    backgroundImage:'../images/plain60.png',
    borderColor:((index < Tagebuch.length) && (Tagebuch[index].Laune == 0))? '#00ff00' : '#000000',
    borderWidth:3,
    borderRadius:10,
    left:Titanium.Platform.displayCaps.platformWidth/2-30,
    top:190,
    width:60,
    height:60
});
wndDetails.add(btnPlain);

// Beim Klick wird dieser Button aktiv (grüner Rahmen)
btnPlain.addEventListener('click', function()
{
    btnSad.borderColor = '#000000';
    btnPlain.borderColor = '#00ff00';
    btnSmile.borderColor = '#000000';
});

// Glücklich
var btnSmile = Titanium.UI.createButton({
    backgroundImage:'../images/smile60.png',
    borderColor:((index < Tagebuch.length) && (Tagebuch[index].Laune == 1))? '#00ff00' : '#000000',
    borderWidth:3,
    borderRadius:10,
    left:Titanium.Platform.displayCaps.platformWidth/2+50,
    top:190,
    width:60,
    height:60
});
wndDetails.add(btnSmile);

// Beim Klick wird dieser Button aktiv (grüner Rahmen)
btnSmile.addEventListener('click', function()
{
    btnSad.borderColor = '#000000';
    btnPlain.borderColor = '#000000';
    btnSmile.borderColor = '#00ff00';
});




























































Um die Buttons unabhängig von der tatsächlichen Displayauflösung halbwegs vernünftig auf der Oberfläche zu verteilen, verwenden wir die Property Titanium.Platform.displayCaps, um die Bildschirmbreite und -höhe auszulesen. Und um den aktiven Laune-Button optisch zu kennzeichnen, verpassen wir ihm einen grünen Rahmen ('#00ff00'). Daher werden in den EventListenern der Buttons einfach nur die Rahmenfarben umgeändert.

Was jetzt noch fehlt, sind die Buttons für Schließen, Speichern und Löschen. Am einfachsten ist der Schließen-Button zu implementieren, da er nur das aktuelle Fenster mittels close() schließen muss.

// Und noch die Buttons Schließen und Speichern
var btnClose = Titanium.UI.createButton({
    title:'Schließen',
    left:20,
    top:270,
    width:Titanium.Platform.displayCaps.platformWidth/2-30,
    height:30
});
wndDetails.add(btnClose);







btnClose.addEventListener('click', function()
{
    Titanium.API.info('Eintrag schliessen.');
    wndDetails.close();
});



Beim Speichern passiert schon etwas mehr. Zuerst unterscheiden wir, ob ein bestehender Einträg geändert werden oder ob ein neuer Eintrag angelegt werden soll. Im letzteren Fall müssen wir das Tagebuch um einen weiteren Eintrag ergänzen und auch eine neue TableViewRow ans Ende des TableViews hängen. Danach lesen wir den Text aus der Textarea aus und fragen die drei Laune-Buttons ab, wer eine grüne Umrandung hat und setzen die entsprechende Property des Tagebucheintrags. Nun schreiben wir den neuen Eintrag in die TableViewRow, und speichern anschließend das gesamte Tagebuch ab, da man bei einer Smartphone-App ja nie weiß, wann der Anwender diese verlässt. Deshalb ist man gut beraten bei jeder Änderung die Daten direkt wegzuschreiben.

var btnSave = Titanium.UI.createButton({
    title:'Speichern',
    left:Titanium.Platform.displayCaps.platformWidth/2 + 10,
    top:270,
    width:Titanium.Platform.displayCaps.platformWidth/2-30,
    height:30
});
wndDetails.add(btnSave);






btnSave.addEventListener('click', function()
{
    if (index < Tagebuch.length)
    {
        Titanium.API.info('Eintrag speichern.');
    }
    else
    {
        Titanium.API.info('Eintrag neu anlegen.');







        // Neuen Tagebucheintrag anlegen. Dieser benutzt die alte Neuerstellen-Row
        Tagebuch[Tagebuch.length] = new TagebuchEintrag(0, '');
        Titanium.API.info('Tagebuch hat jetzt ' + Tagebuch.length + ' Einträge.');

        // Farbe der Neuerstellen-Row auf schwarz ändern.
        row.color = '#000000';

        // Neuen Eintrag für Neuerstellen anfügen
        var rowNeu = Ti.UI.createTableViewRow();
        rowNeu.title = 'Neuer Eintrag...';
        tvListe.appendRow(rowNeu);
    }



    // Geänderte Werte aus der Oberfläche lesen und direkt ins Tagebuch zurückschreiben
    Tagebuch[index].Eintrag = txtEintrag.value;


    if (btnSad.borderColor=='#00ff00')
    {
        Tagebuch[index].Laune=-1;
    }
    else if (btnPlain.borderColor=='#00ff00')
    {
        Tagebuch[index].Laune=0;
    }
    else if (btnSmile.borderColor=='#00ff00')
    {
        Tagebuch[index].Laune=1;
    }












    // TableRow aus Tagebuch neu befüllen
    SetzeTableRow(row, index);

    // Tagebuch speichern
    Ti.App.Properties.setString('Tagebucheintraege', JSON.stringify(Tagebuch));

    // Detailfenster schliessen
    wndDetails.close();
});

Zum Schluß kümmern wir uns um das Löschen eines Eintrags. Dieses habe ich der Einfachheithalber ebenfalls über einen Button realisiert. Dieser bekommt eine rote Aufschrift, damit er direkt ins Auge fällt, und wird natürlich nur angezeigt, wenn man einen bestehenden Eintrag ausgewählt hat, und nicht etwa bei der Neuanlage. Zum Löschen des Tagebucheintrags verwende ich die mächtige JavaScript-Funktion splice, die ein (oder bei Bedarf auch mehrere) Element(e) aus dem Array herauslöscht (Schnelle Infos zu JavaScript-Funktionen findet man übrigens auch in SelfHtml). Die entsprechende TableViewRow löschen wir dann mit deleteRow. Anschließend speichern wir das Tagebuch wieder ab und schließen das Detailfenster.

// Ganz zum Schluss noch Löschen (außer beim Neuanlegen)
if (index < Tagebuch.length)
{
    var btnDelete = Titanium.UI.createButton({
        title:'Löschen',
        color:'#ff0000',
        top:340,
        width:Titanium.Platform.displayCaps.platformWidth-40,
        height:30
    });
    wndDetails.add(btnDelete);









    btnDelete.addEventListener('click', function()
    {
        Titanium.API.info('Eintrag löschen (' + index + ').');

        Tagebuch.splice(index,1);
        tvListe.deleteRow(index, {animationStyle:Titanium.UI.iPhone.RowAnimationStyle.UP});

        // Tagebuch speichern
        Ti.App.Properties.setString('Tagebucheintraege', JSON.stringify(Tagebuch));

        wndDetails.close();
    });
}

Was jetzt noch fehlt, wenn man den bisher gelisteten Sourcecode untereinander schreibt, ist das Öffnen des Detailfensters (wir haben ja bisher nur die Oberflächenelemente hinzugefügt), das Schließen der } vom EventListener('click'), und, last but noch least, dass Hinzufügen des TableViews zum aktuellen Fenster.

    // Nachdem alles definiert ist, dass Detailfenster öffnen
    wndDetails.open();
});

// Und hier zum Schluss den TableView auf dem Bildschirm anzeigen
win.add(tvListe);

Damit wäre die Liste fertig und wir können sie sogar schon ausprobieren. Fehlt zum Abschluß noch die Seite mit den Einstellungen. Diese ist relativ simpel gehalten: ein TextField zur Eingabe und ein Button zum Speichern und das war's eigentlich.

Titanium.API.info('Einstellungen.js Start.');

var win = Titanium.UI.currentWindow;

var MaxAnzahl = 10;

//MaxAnzahl lesen
if (Ti.App.Properties.hasProperty('MaxAnzahl'))
{
    MaxAnzahl = Ti.App.Properties.getInt('MaxAnzahl');
    Titanium.API.info('Max. Anzahl = ' + MaxAnzahl + '.');
}




var lbMaxAnzahl = Titanium.UI.createLabel({
    text:'Maximale Anzahl der Einträge',
    left:30,
    top:10,
    width:260,
    height:'auto'
});
win.add(lbMaxAnzahl);






var fldMaxAnzahl = Titanium.UI.createTextField({
    hintText:'Maximale Anzahl Einträge',
    left:30,
    top:35,
    width:260,
    height:40,
    borderStyle:Titanium.UI.INPUT_BORDERSTYLE_ROUNDED,
    value:''+MaxAnzahl
});
win.add(fldMaxAnzahl);








var btnSpeichern = Titanium.UI.createButton({
    title:'Anwenden',
    left:30,
    top:80,
    width:260,
    height:30
});
win.add(btnSpeichern);






Aufmerksamen Lesern wird sicher auffallen, dass wir auch hier MaxAnzahl aus den Properties laden. Das hat den Grund, dass jedes Tab einen eigenen Kontext mit eigenen Variablen bekommt, wie ich ja ganz zu Beginn bereits geschrieben hatte. Wie tauschen wir jetzt aber Änderungen an der Variable MaxAnzahl zwischen den Tabs aus? Da der Code der Seite nur ein einziges Mal durchlaufen wird und nicht jedesmal, wenn das Fenster aktiv wird, fällt das simple Nachlesen aus den Properties aus. Wir könnten auf das Event focus lauschen, doch leider bekommt das unter Android nicht das Fenster, sondern nur die TabGroup und die ist ja im Kontext von app.js definiert. Ein Bug oder ein Feature? Schwer zu sagen.

Was leider auch nicht funktioniert ist die Übergabe von Referenzen auf Variablen, wie sie in der Beschreibung zum window-Objekt erklärt wird. Das funktioniert zwar angeblich auf dem iPhone, aber leider mal wieder nicht unter Android. Hierzu existiert auch ein Bugreport, der auf eine Korrektur zum nächsten Release (1.5) hoffen lässt.

Was aber auf jeden Fall funktioniert (zumindest unter Android), ist das Senden eines applikationsweiten Events mittels fireEvent. Dieser kann auf jeder Seite gefangen und bearbeitet werden, also auch in Liste.js. Hier zunächst das Senden, wenn der Speichern-Button gedrückt wird.



// Beim Speichern schicken wir mittels fireEvent eine Nachricht an die Liste
btnSpeichern.addEventListener('click', function()
{
    // Nur Speichern, wenn Anzahl geändert wurde
    if (MaxAnzahl != fldMaxAnzahl.value)
    {
        MaxAnzahl = fldMaxAnzahl.value;
        Ti.App.Properties.setInt('MaxAnzahl', MaxAnzahl);
        Titanium.API.info('MaxAnzahl = ' + MaxAnzahl + '.');







        // Nun der App (-> Liste.js) Bescheid geben, dass sich MaxAnzahl geändert hat
        Titanium.App.fireEvent('MaxAnzahlChanged', {MaxAnzahl:MaxAnzahl});
    }
});


Titanium.API.info('Einstellungen.js Ende.');

Und am Ende von Liste.js ergänzen wir noch den dazugehörenden EventListener.

//Auf den Event von Einstellungen.js horchen
Titanium.App.addEventListener('MaxAnzahlChanged', function(e)
{
    Titanium.API.info('Titanium.App: MaxAnzahl = ' + e.MaxAnzahl + '.');


    MaxAnzahl = e.MaxAnzahl;

    // Das Tagebuch entsprechend kürzen
    if (Tagebuch.length > MaxAnzahl)
    {
        // Merke vorletztes Element für das Löschen der TableViewRows (letztes = Neuanlegen)
        var n = Tagebuch.length - 1;



        // Tagebuch kürzen
        Tagebuch.splice(MaxAnzahl, Tagebuch.length - MaxAnzahl);
        Titanium.API.info('Tagebuch gekürzt auf ' + Tagebuch.length + ' Einträge.');

        // Und direkt wieder speichern
        Ti.App.Properties.setString('Tagebucheintraege', JSON.stringify(Tagebuch));

        // Rows des TableViews löschen
        for (; n >= MaxAnzahl; n--)
        {
            Titanium.API.info('Lösche TabViewRow ' + n);
            tvListe.deleteRow(n);
        }
    }
});






Titanium.API.info('Liste.js Ende.');

Damit wäre der Sourcecode für unsere erste App komplett. Da vermutlich kaum jemand diesen wirklich abtippt, habe ich die kompletten Quellen inkl. Projektstruktur und Images mal gezippt und auf meinen Webserver gestellt, von dem ihr das Ganze herunterladen könnt. Einfach den Inhalt der ZIP-Datei in eurer Workspace-Verzeichnis entpacken, ein leeres Projekt in Eclipse für dasselbe Verzeichnis anlegen, Refresh aufrufen, und schon könnt ihr auch bequem den Sourcecode in Eclipse ansehen. Zum Ausprobieren dann das Projekt in Titanium mit Import Project hinzufügen und, wie im letzten Kapitel beschrieben, unter Test und Package ausprobieren. Hier mal ein paar Screenshots der Anwendung:

Natürlich funktioniert unser Tagebuch nur rudimentär. Ein paar Details sind nicht schon gelöst oder funktionieren nicht so, wie wir es erwarten würden. Daher habe ich hier ein paar Aufgaben für euch, wie ihr die Applikation noch verbessern könnt:

  • Ändert die App so ab, dass die Tagebucheinträge in umgekehrter Reihenfolge erscheinen, die neuesten also immer am Anfang stehen.
  • Erweitert die App dann so, dass beim Hinzufügen eines neuen Eintrages geprüft wird, ob die maximale Anzahl Einträge überschritten wird. Falls dies der Fall sein sollte, löscht die ältesten (untersten) Einträge.

Bei weiteren Fragen wendet euch bitte per PN an den Author dieses Blogs.

21 Kommentare

Neuen Kommentar schreiben:
  • Wer einen interessanten Beitrag zur App Entwicklung lesen möchte, der kann auch hier schauen:

    http://www.appdream.de/de/wie-erstelle-ich-meine-app

  • Ich habe diese Woche ein geliehenes MacBook hier und konnte meine App mal auf das iPhone portieren. Ganz ohne Aufwand ging das leider nicht, aber das Ergebnis sieht ziemlich ordentlich aus. Vergleichsbilder und eine Beschreibung, was ich alles ändern musste, findet ihr auf meinem Blog:

    http://crossplatform.blog.de/2010/09/15/plattformbesonderheiten-ios-iphone-9387086/

  • Apple hat gestern seine Lizenzbedingungen gelockert und lässt nun auch Apps im Appstore zu, die mit Konvertern oder in anderen Programmiersprachen entwickelt wurden.

    Damit gibt es keinen Grund mehr, warum man seine App nicht auch mit Appcelerator Titanium oder anderen Tools erstellen sollte. Außer natürlich, man möchte besonders plattformnah entwickeln.

    Presseerklärung:
    http://www.apple.com/pr/library/2010/09/09statement.html

    Artikel bei Heise.de:
    http://www.heise.de/ct/meldung/Apple-lockert-Auflagen-fuer-iOS-Entwickler-1076182.html

  • Wenn man über MobileCrossPlatforms spricht sollte man sich auf jeden Fall mal Rhomobile ( http://rhomobile.com/ ) anschauen. Man schreibt sein App in Ruby (mit dem Framework Rhodes, ähnlich wie RubyOnRails). Dieses App wird dann auf den verschiedenen Betriebssystemen mit einen RubyServer ausgeführt.

    Echt klasse!

  • Bzw. ich finde diese Art von Blog sehr interessant. Das ist mal was anderes ;-)

    Also Dankeschön

  • Kev 16.08.2010 Link zum Kommentar

    Vielen Dank für diesen Spitzenblog, sehr informativ, sehr nützlich! Respekt!

  • Zu den Bedenken, ob Apple mit Titanium erstellte Apps in den AppStore lässt, habe ich gerade eine News auf Golem.de (von Freitag) gefunden:

    http://www.golem.de/1008/77208.html

    Danach wurde Piwik Mobile mit Titanium erstellt und man kann es aktuell tatsächlich im AppStore herunterladen.

  • Super Blog!

  • Ja, das finde ich auch seine sehr gute Idee. Kann man bzw. der Autor bei weiteren Blogs ja so machen.

  • @ Michael Dunstheimer: Stimmt, als "Blog" passt es hier rein. Ich finde den Vorschlag von Martin W. sehr gut, den Artikel als Blog zuverfassen und einen kurzen Umriss über das Thema zugeben, in Folge dann aber ein Link zum Forum einzufügen, in dem das ausführliche Tutorial zufinden ist.

  • @Christian Jungen: Zumindest behaupten sie, dass Titanium native Apps erzeugt. Überprüft habe ich das nicht. Wüsste auch nicht wie.

    Was mir aber wichtiger erscheint, ist, ob Titanium-Apps sich genauso schnell anfühlen, wie native Android-Apps. Da suche ich noch jemanden, der Zeit und Lust hat, die App in Java nachzubauen.

  • Sehr guter Artikel!

    Hab die c't Ausgabe auch weshalb ich auch mal in phonegapp ausprobieren möchte. Aber auch Titanium hat mich jetzt neugierig gemacht.


    Lg, chris

  • Versteh ich das richtig, dieser Compiler erzeugt nativen Machinencode?
    Das wäre schon mal der Hammer. Denn laut Google ist nativer Code
    10 bis 100 mal schneller als Java-Code. Das wäre echt der Hammer.
    Ich kann echt nicht verstehen, wieso man eine Interpreter-Spache
    als Hauptentwicklungssprache für Android genommen hat.
    Es geht ja nicht nur um Geschwindigkeit sondern auch um Batterieverbrauch.

  • Also ich find den Blog gar nicht mal so schlecht...zumindest sehr interessant. Man hätte vielleicht das Thema anreißen können so nach dem Motto "Sowas gibt es wirklich" und das Tutorial im Forum weiterführen können. Dann hätte man das nur noch hier verlinken müssen und Voila. Dann wäre es zumindest nicht so ein riesen Eintrag geworden.

  • Als News würde ich das auch nicht bezeichnen, aber als Blog. Was das angeht, ist es in diesem Fall nicht so einfach. Zwei Admins (inklusive mir) haben sich entschieden diesen Blog freizuschalten und ich habe auch einen Moment überlegt. Allerdings dürfte es ja keine Problem sein, wenn dieser Blog/dieses Tutorial anklang findet, und der Autor zukünftig weiter in der Richtung was machen will, dies dann im Forum weiterzuführen. Von daher finde ich es in diesem Fall absolut okay, das als Blog zu bringen.

  • Informativer Artikel, dennoch denke ich das er im Forum besser aufgehoben wäre. Es handelt sich dabei nicht hauptsächlich um "News". Eher ist es ein Tutorial für webbassierte App's.

  • Also man darf keine fremden tools einsetzen sagen sie, aber wenn man das nicht merkt wird das schon klar gehen.

  • Ich versuche aktuell einen Freund, der einen Mac besitzt und Interesse an der iPhone-Entwicklung hat, hierfür zu gewinnen. Wenn er meine Demo-App auf dem iPhone-Simulator hat laufen lassen, werde ich Screenshots posten.

    Warum soll man damit nicht in den AppStore gelassen werden? Wg. den geänderten Lizenzbedingungen? Laut Appcelerator erzeugt Titanium native Apps und fällt angeblich nicht darunter. Auch retweeten die recht häufig andere Entwickler, die ihre mit Titanium geschriebenen Apps erfolgreich in den AppStore gebracht haben. Könnten natürlich alles Fakes sein, aber ich denke mal positiv und glaube, dass das alles klappt. :)

    JavaScript finde ich auch nicht toll. Komme aus der c#-Ecke. Aber ich hab mich dran gewöhnt.

  • Ich stelle mir gerade die Frage ob man dann nicht "einfach" die eigentliche App mit Tools wie z.B. jQuery mobile (http://jquerymobile.com/) entwicklen soll und dann für z.B. android nur noch eine "simple-app" mitliefert welche lediglich einen WebView anzeigt und sonst nichts.

    Ganz allgemein muss ich jedoch sagen, dass ich, obwohl ich mittlerweile schon diverse Dinge mit/in javascript programmiert habe absolut kein Fan dieser Sprache bin. OO ist mit js ein gefühlter 3-facher Knochenbruch, ohne externe Bibliothek ist es streng genommen ohnehin völlig unbrauchbar.

    Deshalb werde ich einfach weiterhin nur für Android entwickeln und das in Java (so lange und Oracle noch lässt...).

  •   12

    ja fände ich auch gut...

Zeige alle Kommentare

Diese Website verwendet Cookies, um Ihnen ein besseres Nutzungserlebnis bieten zu können. Mehr dazu

Alles klar!