After my little rant about Three20 in a previous post I figured I should at least try to make things better for other people.
One of the first things I struggled with was getting the TTLauncherView working. I had followed the steps on the Three20 website to add the necessary files to the project but I wasn’t sure how I then got the TTLauncherView displaying on the screen.
So, to hopefully help someone else… here goes.
Start off in your AppDelegate.m file. It should have been created automatically for you when you created your project in XCode. First thing you need to do is actually include the Three20 header file.
#import "Three20/Three20.h"
I’m sure you could probably just import the TTLauncherView header file but I figured I’d just make it easier on myself and include the main Three20.h file.
After that, you need to setup the TTNavigator and the relevant view controller mappings. All this stuff needs to be done in the
-(void)applicationDidFinishLaunching:(UIApplication *)application
method.
Create the TTNavigator instance
TTNavigator *navigator = [TTNavigator navigator];
Set the navigator persistence mode
navigator.persistenceMode = TTNavigatorPersistenceModeNone;
My understanding of this is that Three20 actually keeps a record of where you are in the navigation while the app is running. This means when you close the app and reopen it, Three20 can start off from where you left it. In this case I am telling Three20 to not do that and instead the app will just start up as normal.
The next step is to setup the TTURLMap. Three20 has this neat feature where you can refer to view controllers using a URL. This actually makes working with view controllers a lot simpler, at least once you get the hang of it. NOTE: This also means you are pretty much locked into using Three20 once you start using TTURLs. If you get part way and decide you no longer want to use Three20 you are going to have to re-write everything.
Get a pointer to the navigators URL map.
TTURLMap *map = navigator.URLMap;
Use that pointer to setup all your URL mappings
[map from:@"*" toViewController:[TTWebController class]];
[map from:@"tt://launcher" toSharedViewController:[LauncherViewController class]];
[map from:@"tt://first" toViewController:[FirstViewController class]];
[map from:@"tt://second" toViewController:[SecondViewController class]];
[map from:@"tt://third" toViewController:[ThirdViewController class]];
etc
etc
After doing this you can then use the URL tt://launcher in your code to refer to your LauncherViewController (or whatever you have called it). I’ll give an example of this in a second.
Each of the ViewControllers referenced in the mapping code are standard UIViewController classes. You can actually map the URLs to any class.
After that you can actually get the launcher view controller to displaying using
[navigator openURLAction:[TTURLAction actionWithURLPath:@"tt://launcher"]];
One line of code instead of the usual 3 or 4 thats regularly needed to push a view controller onto the navigation stack. You can see there how using the URL makes things a lot easier. It took me a while to get my head around this.
So when my app starts, it will run the applicationDidFinishLaunching method and setup the mappings and then get Three20 to launch the tt://launcher URL, which is mapped to the LauncherViewController class.
Now, on to the LauncherViewController file.
My LauncherViewController is a subclass of TTViewController. I believe it has to be in order to crate the launcher view.
In the LauncherViewController.m file we setup the Launcher View in the loadView method
First we allocate and initialise the launcherView using the views bounds. This means the launcher view will take up the whole screen.
launcherView = [[TTLauncherView alloc] initWithFrame:self.view.bounds];
Then we set the background color of the launcher view.
launcherView.backgroundColor = [UIColor whiteColor];
Then we set the number of columns we want
launcherView.columnCount = 1;
In this example I’m only having one column with 3 items. You can adjust this value at anytime and Three20 will automatically reposition the icons in your launcherView to fit.
The next part involves setting up the actual items that will be displayed in the launcherView. You do this by setting the pages property of the launcherView instance.
launcherView.pages = [NSArray arrayWithObjects:
[NSArray arrayWithObjects:
[self launcherItemWithTitle:@"First" image:@"bundle://firsticon.png" URL:@"tt://first"],
[self launcherItemWithTitle:@"Second" image:@"bundle://secondicon.png" URL:@"tt://second"],
[self launcherItemWithTitle:@"Third" image:@"bundle://thirdicon.png" URL:@"tt://third"],
nil], nil];
This creates our pages structure. It’s an array of arrays where the inner array represents the icons on the page and the outer array represents the page. So you could define a structure that has any number of pages and on each page you have a number of icons.
Next thing we have to do is set the launcherViews delegate. In this case I’m setting the LauncherViewController as the delegate.
launcherView.delegate = self;
Once that’s done, we can add the launcherView to the LauncherViewControllers view.
[self.view addSubview:launcherView];
Then release the launcherView instance
[launcherView release];
When creating the pages above, I used a separate method to make things less cluttered. The launcherItemWithTitle method looks as follows:
-(TTLauncherItem *)launcherItemWithTitle:(NSString *)pTitle image:(NSString *)image URL:(NSString *)url
{
TTLauncherItem *launcherItem = [[TTLauncherItem alloc] initWithTitle:pTitle image:image URL:url canDelete:YES];
return [launcherItem autorelease];
}
All this is doing is taking the items passed in an creating a TTLauncherItem from them.
With this done, all thats left to do is to implement the necessary delegate methods.
- (void)launcherView:(TTLauncherView*)launcher didSelectItem:(TTLauncherItem*)item
{
[[TTNavigator navigator] openURLAction:[TTURLAction actionWithURLPath:item.URL]];
}
This method is called when an item is selected from the launcherView. It’s quite simple really. Using the mappings we created earlier we simply tell the TTNavigator instance to open the URL. We create the URLAction required using the URL we set when creating each TTLauncherItem.
What this means is that when an item is tapped in the launcherView we want it to load the relevant View Controller. This will push the relevant view controller onto the navigation stack and it will be displayed.
I think that pretty much covers a basic LauncherView implementation. It’s not really that hard once you understand the way Three20 handles navigation.
It’s a lot to get your head around especially if you are starting out in iOS development. Stick with it though.