2014-12-29

Android Studio-Tipp: Projekt aus Recent Projects entfernen

Auf dem Willkommensbildschirm von Android Studio gibt es eine Liste der kürzlich geöffneten Projekte:

Screenshot: Android Studio-Willkommensbildschirm

Wenn man die leeren muss, um z. B. Screenshots für ein Buch anzufertigen Smiley, kann man mit den Cursortasten das gewünschte Projekt ansteuern oder mit der Maus darüber fahren und dann die Taste Entf drücken.

2014-12-27

Tipp: Android-Log-Tags kurz halten

Es gilt unter Android als common practice, eine Konstante TAG zu definieren, die den Namen einer Klasse enthält, und bei Log-Ausgaben übergeben wird. Google macht das in seinen Beispielen immer so:


public class DigitalWatchFaceService extends CanvasWatchFaceService {

  private static final String TAG = "DigitalWatchFaceService";

  ..

Ich finde folgende Variante schöner, weil sie sich m. E. besser beim Refactoren verhält:


public class C64WatchFaceWearableConfigActivity extends Activity {

  private static final String TAG = C64WatchFaceWearableConfigActivity.class.getSimpleName();

  ..

 

Das Ergebnis ist dasselbe. Allerdings ist mir heute trotzdem dieses Codeschnipsel auf die Nase gefallen, wenngleich aus einem anderen Grund.

Screenshot: Fehlerausgabe in Logcat

Die Ausgabe auf der Konsole:

java.lang.IllegalArgumentException: Log tag "C64WatchFaceWearableConfigActivity" exceeds limit of 23 characters

Stand heute sagt die Doku zur Klasse android.util.Log nichts dazu.

Fazit: Klassennamen kurz halten. Smiley

2014-12-24

Linktipp: Commodore VIC-II Color Analysis

Für mein Zifferblatt im C64-Look war ich auf der Suche nach den “richtigen”, möglichst originalgetreuen Farben. Da es unzählige Emulatoren gibt, könnte man natürlich einfach einen Screenshot machen und die Farben abgreifen. Aber das verschiebt das Problem nur, denn: Wo haben die Emulatoren die Farben her? Seit es Truecolor gibt, sind wir gewöhnt, im RGB-Farbraum nach Belieben zu stöbern. Aber der C64 kannte nur 16 Farben, und die waren nirgendwo als RGB-Werte hinterlegt, sondern wurden vom Videochip erzeugt. Wie der das tut, und wie man doch noch zu RGB-Werten kommt, ist im großartigen Artikel Commodore VIC-II Color Analysis beschrieben.

2014-12-23

Stylisches Zifferblatt für Android Wear

Da mein Android-Buch ein Kapitel zu Android Wear enthalten wird, wollte ich die neue Watch Face API ausprobieren. Herausgekommen ist C64 Tribute Watch Face.

Für Neugierige ohne Android Wear ein Screenshot:

Screenshot: C64 Style Watch Face
Ein (auf dem Screenshot nicht sichtbarer) Cursor hat zwar keine Funktion, blinkt aber (in etwa) so schnell wie ein C64.

Update am 18.04.2016: Fehlendes Bild ersetzt

2014-12-17

Alte Dateiformate: .mdi

Beim Aufräumen meiner Festplatte bin ich über eine Datei mit der Endung .mdi gestolpert. MDI steht hier für Microsoft Office Document Imaging, ein proprietäres Format, das mit Office 2010 eingestellt wurde. Ein Doppelklick bewirkt also in Verbindung mit modernen Office-Versionen gar nichts mehr. Allerdings gibt es von Microsoft ein Commandline-Tool, das solche Dateien in TIFF umwandeln kann. Die Daten sind also dank dieses MDI to TIFF File Converters nicht verloren. Der Setup-Assistent installiert das Programm nach C:\Program Files (x86)\modiconv. Bitte bei der Nutzung in der Eingabeaufforderung beachten, dass der Vorgang nur startet, wenn der Parameter –log … mit angegeben wird. Sonst werden nur die Aufrufparameter ausgegeben. Wenn Sie das Tool nicht mehr benötigen, können Sie es wie gewohnt über die Systemsteuerung deinstallieren.

2014-12-14

Tipp: Navigationsproblem in der Android-Kontakte-App lösen

Meine App TKBirthdayReminder delegiert das Anlegen von Kontakten an die dafür zuständige App. Das – immer noch geniale - Intent-System macht dies möglich. Nachdem der Anwender einen neuen Kontakt hinzu gefügt hat, erscheint in der App ein Dialog, der das Geburtsdatum abfragt. So zumindest die Theorie. Ganz offenkundig hat das schon seit geraumer Zeit nicht mehr funktioniert. Da ich das Programm etwas fitter für Lollipop machen wollte, habe ich mal wieder damit  gespielt, und bin prompt in das Problem gelaufen. Die Doku weiß hierzu folgendes zu berichten:
In Android 4.0 (API version 14) and later, a problem in the contacts app causes incorrect navigation. When your app sends an edit intent to the contacts app, and users edit and save a contact, when they click Back they see the contacts list screen. To navigate back to your app, they have to click Recents and choose your app.
Glücklicherweise folgt postwendend die Lösung:
To work around this problem in Android 4.0.3 (API version 15) and later, add the extended data keyfinishActivityOnSaveCompleted to the intent, with a value of true. Android versions prior to Android 4.0 accept this key, but it has no effect.
Also ein simples…
editIntent.putExtra("finishActivityOnSaveCompleted", true);

2014-12-12

HTML-Dialoge mit Feinschliff

Erinnern Sie sich noch an meine Frage aus meinem vorangehenden Post, was mit dem dort gezeigten Dialog nicht 100%-tig passt? Gucken Sie sich mal diese Version an:

Screenshot: HTML-Dialog mit "richtigen" Font

Es ist die Schrift. Die hier hat keine Serifen.

Swing beizubringen, in HTML nicht Times New Roman zu verwenden, ist einfach. Zum einen gibt es die Client Property HONOR_DISPLAY_PROPERTIES. Außerdem kann die Zeichensatzfamilie auch in HTML selbst gesetzt werden:

<body style="font-family: ...">

2014-12-05

Breite von Dialogen

Was ist eine geeignete Breite für Dialoge? Die Frage mag sich komisch anhören. Was ich meine, ist folgendes… Nehmen wir an, Sie haben eine Menge Fließtext, zum Beispiel die Linzenzbestimmungen Ihrer Software. Um die anzuzeigen, bietet es sich an, sie in Swing in eine JEditorPane zu packen, die wiederum von einer JScrollPane (denken Sie an meinen vorherigen Post) gekapselt wird. Mit der JEditorPane können prima einfache HTML-Texte angezeigt werden, deren Links sogar anklickbar sind. Die Breite der Komponente ergibt sich aus der Breite der scroll pane; diese bezieht sie vom Layoutmanager des übergeordneten Containers. Hat der Dialog also in sich eine passende Größe, bekommt auch der Fließtext eine geeignete Breite. Was aber, wenn ein entsprechendes ordnendes Element fehlt?
Screenshot: viel zu breiter Dialog
Solche Monster möchte und sollte man niemandem zumuten. Zumal die Lösung recht einfach ist. Die Basis vieler Swing-Komponenten, java.awt.Component, kennt seit Java SE 5 die Methode setPreferredSize(). Der kann man eine bevorzugte Größe mit auf den Weg geben.
Nur – sind wir jetzt wirklich weiter? Woher sollen wir im Zeitalter von Hoch-DPI-Anzeigen passende Pixelwerte nehmen? Mein pragmatischer Vorschlag ist, sich am verwendeten Zeichensatz und einem Stück Text mit geeigneter Länge zu orientieren. Ich habe das in Notes and Tasks umgesetzt, der entsprechende Code ist eingecheckt. Als Text verwende ich den berühmten Blindtext Lorem ipsum: Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy. Hier die Methode, die die Größe berechnet:
 private static final String LOREM = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy";  
   
 /**  
  * Gets the rectangle for one line of lorem ipsum  
  *  
  * @param font font  
  * @return size  
  */  
 public static Rectangle2D getSizeForLoremIpsum(Font font) {  
     Graphics2D g = (Graphics2D) Application.getInstance().getGraphics();  
     return font.getStringBounds(LOREM, g.getFontRenderContext());  
 }  
Und so wird sie verwendet:
 Rectangle2D r = FontUtilities.getSizeForLoremIpsum(pane.getFont());  
 pane.setPreferredSize(new Dimension((int) r.getWidth(), 12 * (int) r.getHeight()));  
Screenshot: Dialog mit geeigneter Breite
Sieht hübsch aus, oder?
Anmerken möchte ich noch, dass sich die grundsätzliche Idee auch in anderen Frameworks prima umsetzen lässt. Gefällt Ihnen meine Idee? Schreiben Sie mir.