Freitag, 27. Juli 2012

Horizontaler UITableView (Trick)

Einleitung
Wer hat sich als iOS Entwickler noch nicht gefragt warum die UITableView nur vertikal scrollt?! ...
Es wäre doch super wenn sie das auch horizontal könnte. Ein kleiner Trick den ich im Netz gefunden habe macht die UITableView auch horizontal Scrollbar.

Funktionsweise
Die Tabelle wird um 90 Grad gedreht (auf die Seite gekippt), damit die Zellen aber nicht auch auf der Seite liegen werden diese wieder zurück gedreht.

Schritt 1:
Normalen ViewController anlegen der von UITableViewController erbt.

Schritt 2:
in der ViewDidLoad folgende zeilen eintragen um die Tabelle zu drehen


- (void)viewDidLoad
{
    [super viewDidLoad];
    
    const CGFloat k90DegreesCounterClockwiseAngle = (CGFloat) -(90 * M_PI / 180.0);
    CGRect frame = tableV.frame;
    tableView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, k90DegreesCounterClockwiseAngle);
    tableView.frame = frame; 
}


Schritt 3:
In der Methode in der die UITableCellView erzeugt und konfiguriert wird die Zelle drehen

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
    if (!cell) 
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }    

    CGFloat k90DegreesClockwiseAngle = (CGFloat) (90 * M_PI / 180.0);    
    cell.transform = CGAffineTransformRotate(CGAffineTransformIdentity, k90DegreesClockwiseAngle);
    
   //your cell init here
    //.....................
    
    return cell;
}



Die Zellenbreite kann über die folgende Methode (die eigentlich für die Höhe zuständig ist) konfiguriert werden. In dem Codebeispiel gebe ich die Breite des Bildschirms zurück... so ist die Cell immer genau so breit wie eine Bildschirmbreite...

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return self.view.bounds.size.width;
}

Mittwoch, 25. Juli 2012

iPhone Bedienung mal anders

Einleitung

Wer das iPhone kennt weiß so ziemlich schnell wie es zu bedienen ist. Das ist dem Bedienkonzept von Apple zuzuschreiben. Dieses ist in seine Navigationsstrukturen auch recht Übersichtlich. Mir persönlich wird es immer schnell langweilig wenn ich die 1000 App mit einer TabBar oder NavigationBar sehe. Deshalb habe ich neues Bedienkonzept gebaut welches mal ein wenig mehr Abwechslung bringen soll.

Video
Funktionsweise


Der Grundaufbau besteht aus einem eigenen neuen Controler Typ den ich TileViewController nenne. Er kann eigentlich unendlich viele Unterviewcontroller beherbergen ähnlich wie z.B. ein TabViewController.
Nach dem Initialisieren des TileViewControllers fügt man ihm lediglich seine gewünschten ViewController hinzu und gibt für jeden ViewController die Zeile an in der er dargestellt werden soll. Die Kachelgrößen werden dann automatisch vom TileViewController zugewiesen. 


Im Pseudocode sieht das ungefähr so aus:


[tileviewController addViewController:vc1 inRow:0];
[tileviewController addViewController:vc2 inRow:0];
[tileviewController addViewController:vc3 inRow:1];
[tileviewController addViewController:vc4 inRow:2];

Und schon haben wir folgende Zeilen:
Zeile 1: vc1;vc2
Zeile 2: vc3
Zeile 3: vc4

Wer Code sehen möchte kann mich gerne in den Kommentaren fragen ... Gruß Maurice
Wanna see code? ask me via comments

Donnerstag, 15. März 2012

Flash Builder, Mobile und der SplashScreen

Seit Flash Builder 4.6 gibt es die Möglichkeit für Mobile Apps eine SplashScreenImage  anzulegen...
Leider waren die Beispiele von Adobe für meine Zwecke nicht ausreichend... wer z.B. iPad, iPhone 3GS, iPhone 4S, Android Smartphone und Android Tablet abdecken will hat mehr Probleme mit dem Splashscreen als man sich vorstellen kann... hier meine Lösung die alle Varianten Abdeckt:



<?xml version="1.0" encoding="utf-8"?>
<s:SplashScreenImage xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Declarations>
<!-- Platzieren Sie nichtvisuelle Elemente (z. B. Dienste, Wertobjekte) hier -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
[Embed(source="assets/imgs/Default.png")] //320x480
[Bindable]
public var ios160p:Class;
[Embed(source="assets/imgs/DefaultLandscape.png")]  //480x320
[Bindable]
public var ios160l:Class;
[Embed(source="assets/imgs/Default@2x.png")]  //640x960
[Bindable]
public var ios320p:Class;
[Embed(source="assets/imgs/Default@2xLandscape.png")] //960x640
[Bindable]
public var ios320l:Class;
[Embed(source="assets/imgs/Default-Landscape~ipad.png")] //1024x748
[Bindable]
public var iosTablettL:Class;
[Embed(source="assets/imgs/Default-Portrait~ipad.png")] //768x1004
[Bindable]
public var iosTablettP:Class;
[Embed(source="assets/imgs/logoTabletPortraitDefault.png")] //800x1232
[Bindable]
public var andTablettP:Class;
[Embed(source="assets/imgs/logoTabletLandscapeDefault.png")] //1280x752
[Bindable]
public var andTablettL:Class;
[Embed(source="assets/imgs/logo160PortraitDefault.png")] //320x480
[Bindable]
public var and160p:Class;
[Embed(source="assets/imgs/logo160LandscapeDefault.png")] //480x320
[Bindable]
public var and160l:Class;
[Embed(source="assets/imgs/logo240PortraitDefault.png")] // 480x800
[Bindable]
public var and240p:Class;
[Embed(source="assets/imgs/logo240LandscapeDefault.png")] //800x480
[Bindable]
public var and240l:Class;
[Embed(source="assets/imgs/logo320PortraitDefault.png")] //640x960
[Bindable]
public var and320p:Class;
[Embed(source="assets/imgs/logo320LandscapeDefault.png")] //960x640
[Bindable]
public var and320l:Class;
// Override getImageClass() to return an image for iOS.
override public function getImageClass(aspectRatio:String, dpi:Number, resolution:Number):Class
{
// Is the application running on iOS?
var isIOS:Boolean = (Capabilities.version.indexOf("IOS") == 0 ? true:false);
if(aspectRatio == StageAspectRatio.PORTRAIT) //Portrait
{
if(dpi == 160 && resolution<1000)//real 160
return (isIOS==true?ios160p:and160p);
else if(dpi == 160 && resolution>1000)//tablett
return (isIOS==true?iosTablettP:andTablettP);
else if(dpi == 240) return and240p;
else if(dpi == 320)
return (isIOS==true?ios320p:and320p);
}
else //Landscape
{
if(dpi == 160 && resolution<1000) //real 160
return (isIOS==true?ios160l:and160l);
else if(dpi == 160 && resolution>1000)//tablett
return (isIOS==true?iosTablettL:andTablettL);
else if(dpi == 240) return and240l;
else if(dpi == 320)
return (isIOS==true?ios320l:and320l);
}
return super.getImageClass(aspectRatio, dpi, resolution);
}
]]>
</fx:Script> </s:SplashScreenImage>

Sonntag, 26. Februar 2012

Folder Sync für Minus

(english on the buttom)

Mein neustes Projekt entstand aus lauter Langeweile. Eigentlich benutze ich Dienste wie Drop Box und Co. eher selten. Aber mir ist aufgefallen, dass nur Drop Box einen guten Desktop Client anbietet, der es dem User möglichst einfach macht seine Daten mit der Drop Box zu synchronisieren. Da Minus.com deutlich mehr Speicher bietet und außerdem auch noch größere Dateien erlaubt das Desktop Tool aber eher mies ist, habe ich den Anfang gemacht ein eigenes Tool zu programmieren.

Grundlegende Idee ->  Ein Programm zum Synchronisieren eines lokalen Ordners auf der Festplatte mit allen Dateien die auf Minus.com gespeichert sind.

 Das heißt:
- Nach Eingabe von Benutzername und Passwort werden alle online Dateien in einen frei gewählten lokalen Ordner kopiert.
- Einfach Dateien per Windows Explorer in den lokalen Ordner kopieren und das Programm lädt die die Dateien automatisch hoch.

Aktueller Stand (funktionierende Features):
- Login
- Pfad auswählen
- Alle Dateien runterladen
- Letzte eingaben (name, passwort, pfad) speichern

Geplante Funktionen:
- Automatischer Upload von Dateien
- Automatisches regelmäßiges überprüfen ob neue Dateien auf dem Server sind zum Runterladen
- Hübschere Benutzer Schnittstelle (GUI)
- Minimieren ins System Tray

english:
Current State (working features):
- Login
- Choose  Path
- Download all online files to path
- save username, password, path for next App Start

whats next?:
- automatic file upload
- scheduled check for new online files to download
- more pretty GUI
- minimize app to system tray

aktueller (current) Build: 0.0.0.1:
https://rapidshare.com/files/301806078/FolderSync.zip



UPDATE:
Weitere Informationen unter ->

http://minusfoldersync.blogspot.com/

Donnerstag, 9. Februar 2012

Abschlussarbeit und das richtige Zitat in Word

Wer eine Abschlussarbeiten muss, weiß er hat vernünftig seine Quellenangaben zu machen. Wer seine Arbeit in Word schreibt erntet bei einigen Latex Fetischisten zwar unendlich viel Hohn, hat aber außerdem das Problem, dass Word einem nur wenige Zitat Vorlagen bietet. Nach langem Suchen und rumprobieren habe ich es jedoch aufgegeben mi selbst eine Vorlage zu bauen und bin Gottseidank noch auf folgende Seite gestoßen:


Einfach herunterladen, entpacken und je nach Word Version in das entsprechende Verzeichnis kopieren... bei mir: c:\Program Files (x86)\Microsoft Office\Office14\
.... und schon erhält man nach Neustart von Word schön viele neue Vorlagen die auch das machen was man will... ich persönlich fand die IEEE Variante ganz angenehm.

Montag, 12. September 2011

Flex: SnapScroller

Da ich derzeit an meiner Master Thesis sitze und via Flex eine Mobil App erstellen möchte, ist mir folgendes aufgefallen. Flex 4.5 ist zwar echt nett was die Veröffentlichung von Apps auf mehreren Plattformen angeht, hat aber leider recht eingeschränkte Komponenten zum zusammenbauen. So fehlte mir dringend die Paging Funktion die man aus iOS kennt. Sprich man hat eine Scrollview, die seitenweise Inhalte präsentiert. Da ich auch nach längeren Suchen keine Möglichkeit gefunden habe die Scroller Komponente zu parametrisieren, habe ich sie einfach mal erweitert.

Beispiel (rote Fläche nach links wischen):




Dazu folgenden Quelltext

MXML:

<local:SnapScroller  x="0" y="0" width="320" height="460">
<s:HGroup gap="0" width="100%" height="100%" >
<s:Image source="assets/Startscreen_Portrait.png"/><s:Image x="320" source="assets/Startscreen_Portrait.png"/><s:Image x="640" source="assets/Startscreen_Portrait.png"/>
</s:HGroup>
</local:SnapScroller>
Wichtig ist, das die Komponente vom Typ SnapScroller- und der Container eine HGroup ist. Gap sollte auf 0 stehen damit die Elemente direkt nebeneinander liegen und nicht unnötig mit Spacern getrennt sind.

Die AS3 Komponente (derzeit nur horizontales snapping):

package
{
 package
{
 import flash.events.MouseEvent;
 import flash.events.TimerEvent;
 import flash.events.TouchEvent;
 import flash.ui.Mouse;
 import flash.ui.Multitouch;
 import flash.ui.MultitouchInputMode;
 import flash.utils.Timer;
 
 import flashx.textLayout.formats.Float;
 
 import mx.core.InteractionMode;
 import mx.core.ScrollPolicy;
 
 import spark.components.Group;
 import spark.components.Scroller;
 
 
 public class SnapScroller extends Scroller
 {
  private var isMouseDown:Boolean;
  private var xStart:Number;
  private var mouseUpDownXDistance : Number;
  private var t:Timer;
  private var nextHorizontalPosition: Number; 
  private var nextHorizontalPositionDistance : Number;
  
  public function SnapScroller()
  {
   super();
   
   this.setStyle('horizontalScrollPolicy',ScrollPolicy.OFF);
   this.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);
   this.addEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);
   
  }
  
  protected function onMouseDown(event:MouseEvent):void
  {
   this.addEventListener(MouseEvent.MOUSE_UP,onMouseUp);
   stage.addEventListener(MouseEvent.MOUSE_UP,onMouseUp);
   
   if (t)
    t.stop();
   
   isMouseDown = true;
   xStart = mouseX;
  }
  
  protected function onMouseMove(event:MouseEvent):void
  {
   if(isMouseDown)
   {
    mouseUpDownXDistance = mouseX-xStart;
    this.viewport.horizontalScrollPosition -= mouseUpDownXDistance;
    xStart = mouseX;
   }
  }
  
  protected function onMouseUp(event:MouseEvent):void
  {
   isMouseDown = false;
   
   if(mouseUpDownXDistance > 0)
    nextHorizontalPosition = (int(this.viewport.horizontalScrollPosition/this.width))*this.width;  
   else
    nextHorizontalPosition = (int(this.viewport.horizontalScrollPosition/this.width)+1)*this.width;
   
   if (nextHorizontalPosition > ((this.getElementAt(0) as Group).contentWidth)-this.width)
    nextHorizontalPosition = ((this.getElementAt(0) as Group).contentWidth)-this.width;
   
   t = new Timer(1,0);
   t.addEventListener(TimerEvent.TIMER,timerEnds);
   t.start();
   
   stage.removeEventListener(MouseEvent.MOUSE_UP,onMouseUp);
   this.removeEventListener(MouseEvent.MOUSE_UP,onMouseUp);
  }
  
  protected function timerEnds(event:TimerEvent):void
  {
   var distanceToTarget:Number = Math.abs(this.viewport.horizontalScrollPosition - nextHorizontalPosition);
   
   if(this.viewport.horizontalScrollPosition > nextHorizontalPosition)
    this.viewport.horizontalScrollPosition -= Math.sqrt(distanceToTarget);
    
   else
    this.viewport.horizontalScrollPosition += Math.sqrt(distanceToTarget);
   
   if (distanceToTarget < 0.01)    
   {     
    this.viewport.horizontalScrollPosition = nextHorizontalPosition;          
    t.stop();     
    t.removeEventListener(TimerEvent.TIMER,timerEnds);    
   }   
  }  
 } 
}

Tutorial Video

Dienstag, 16. August 2011

Synergy

Wer viel an 2 Computern z.B. einen Mac und einem PC gleichzeitig arbeitet, hat oft auch zwei Mäuse und Tastaturen vor sich liegen. Außerdem möchte man oft auch Copy/Paste von System zu System machen.

Abhilfe verschafft das Tool Synergy.

Man installiert es auf einem System (z.B. Mac) und auf einem anderen (z.B. PC) und startet auf einer Seite die Server Version und auf der anderen die Client Version. Die Serverversion shared nun Keyboard und Maus mit dem Client. Sprich man kann mit der Maus zum anderen Bildschirm wechseln und eingaben via Tastatur tätigen. Auch Copy/Paste klappt. Die Tastatur ist immer auf dem Bildschirm aktiv, wo die Maus gerade ist. Für den PC ist die Oberfläche optisch schön realisiert. Bei der Mac Variante sollte man sich z.B. SynergyKM googlen.... Dieses kleine Tool trägt Synergy in die Systemeinstellungen ein und macht die Konfiguration deutlich leichter.

Tipp: Wer den Mac als Server nutzt, sollte darauf achten, dass unter den Systemeinstellungen -> Bedienungshilfen die Option "Zugriff für Hilfsgeräte aktivieren" angehakt ist. Ansonsten könnte es sein, dass die Tastatur nur auf der Mac Seite eingaben empfängt und nicht weiterreicht zum Client.

Synergy gibt es für Mac, PC, Linux....

...

PS:
Eine einfache Alternative ist übrigens ShareMouse. Kostenlos für max 2 verbundene Systeme