One of the more interesting parts of Earnest was that it was highly visual, and well designed. The FreeAgent folks didn’t want to use any (or many) of the standard iOS styles, and wanted the app to follow their new branding and style that they have developed for the visual update of FreeAgent.
The app is designed for very small businesses (usually sole-traders) who are under the VAT limit (73k). It lets them easily track their income, expenses and estimated tax liability, and combined with the new HMRC rules around 3-line accounting (income, expenses, gross profit), the government is hoping this will increase the compliance by those at the tiny end of the market.
If you want to try Earnest out, it’s a free download from the AppStore.
There were two main areas I want to cover that came out of the development of Earnest: use of iOS5 UIAppearence apis, and some deep customisation of MonoTouch.Dialog to change the default rendering on table cells. I’ll also cover a little bit of how to integrate animations into existing components.
We decided from the start that while the application should work on iOS4 (4.3 to be exact – the last one that the iPhone 3G can run), we should focus on iOS5 as much as possible.
The normal iOS method of doing OS-version-specific code involves just not calling the methods which are not available on the older versions, so I ended up with a lot of “if (version 5) do something” type code. The code for checking the version, however, is quite simple
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
After that, you can do things like:
1 2 3 4 5 6 7
It’s not elegent, but it works well, and beats the “I’ve built it for X, so it’ll work on X+1, without any new stuff”, or “it’s build for Y, so Y-1 will not work at all”. Anyone with a keen eye will see that the output of this could (should) be cached, as once the application is running, the iOS version can never change.
For the first time since I started writing iOS applications, I had access to a proper, real-life (scottish-talking) designer, in the form of Robbie Manson, the resident designer at FreeAgent. He designed the interface and flow of Earnest, and I can’t recommend highly enough finding a good designer. Of all the developers (or designers) I know, I only know 2 people who are really capable of doing both design – UI, UX, pixel pushing – and coding to a high standard. There is something about design and development: they go together, but seldom in the same person.
Two of the main sections that were customised in Earnest were the UINavigationController, and the UITabBarController. As I said above, we decided early on to focus on iOS5, and just “make it work” in iOS4, so I was able to use the UIAppearence APIs (which MonoTouch supports with strongly typed classes/properties).
1 2 3 4 5 6 7 8 9 10 11 12 13
While this code doesn’t cover all the customisations I did, the total lines of code to change all the required items was one method, and about 20 lines. This beats the other option, which is to inherit from UINavigationBar and override the drawRect: method.
The result was quite striking:
You can see the iOS 5 header at the top, and in the tabbar at the bottom. The iOS4 versions just use the existing TintColor on the header, and nothing on the tabbar.
I can’t recommend this method highly enough. It ment I could focus on the iOS5 version, and making it perfect, while knowing that it will still work on iOS4.
On a side note, I’m also using the UIImage.CreateResizableImage method, which allows you to make a small image (eg a button) and have it scale up in a sensible way. Miguel de Icaza details it more here.
Custom Sections in MonoTouch.Dialog.
One of the design elements that Robbie came up with involved changing how the standard Grouped UITableView cells looked. He wanted a much smaller corner radius, a different drop shadow, and a different coloured line, all of which matches the new FreeAgent design language.
To do this, I inherited from Section, and added a CustomizeCell method into the base:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
There are 4 separate situations here
- A cell on it’s own, which has rounded top and bottom, using it’s own image.
- A top cell, which has a background of just a top rounded edge
- A middle cell, with no rounding at ll
- A bottom cell, with rounding on the bottom edges and a drop shadow.
We had one image for each of these states, tho it might be possible to do it using manual drawing.
I also extended DialogViewController (in MonoTouch.Dialog) to call this when it was building each cell.
1 2 3 4 5 6 7 8 9
Again, the results work in both iOS4 and 5, but look a lot better in iOS5. I’m not sure I got them pixel-perfect to the designs, but it is very close.
MonoTouch.Dialog provides a search facility, which works very well, and makes use of the iOS standard UISearchBar. Earnest uses this, with a couple of tweeks (outside of the visual changes, which were just part of the UIAppearence settings above)
When you tap in the search box, the UINavigationBar animates away, allowing the user to focus on searching, making it quite modal without preventing the user from doing other things.
This sounds difficult, but iOS makes it very easy to do. In the MT.D’s DialogViewController, there is a SearchDelegate. This delegate has methods which are called when searching starts, and when the cancel button is pressed (we wanted the user to explicitly exit search). Adding a simple animation in there removes – and adds – the Navigation bar.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
The two bits of interest are the following:
1 2 3 4 5 6 7 8 9 10 11
Animations in iOS are very easy to do with the UIKit properties which are CoreAnimation aware (most are), and it gives your app a very polished, “Apple” feeling.
There is a lot more that I did in Earnest to get it looking “just right”, but this covers most of the nitty-gritty. In general, if you have to do something in CocoaTouch, assume Apple has provided it already, rather than having to re-invent it yourself.
Version 2 of Earnest is under way, which is “more of the same” – extending it to cover the areas we wanted to do on day one, but didn’t have time to do.