The purpose of the original "M"osetta Stone post was to give cross-platform developers a 'head start' with some high-level concepts. This post will look a little closer at a screen from the Monospace11 app: the Speakers list.
This may be a massive oversimplification, but...
if you have ___ in iOS | then you want ___ in Android | to |
---|---|---|
UIViewController | Activity | subclass to present a screen/form/page to the user |
ViewDidLoad() | OnCreate() | setup the UI |
Add() or AddSubview() | SetContentView() | use in ViewDidLoad/OnCreate to 'attach' UI to display |
ViewWillAppear() | OnResume() | load/re-load data that might change and bind to UI |
UITableView | ListView | visual control that presents a scrolling list |
UITableViewSource | Adapter | subclass to broker the display of a data collection to the UI |
GetCell() | GetView() | to build the layout(UI) for each cell/row, including re-using cells/views for performance |
RowSelected() | ItemClick EventHandler | perform an action when a row is touched |
RowsInSection | Count | tell the table/list how many rows to cater for |
Here's how it looks in a Visual Studio Class Diagram*
* I've greyed out some of the methods not relevant to the discussion - the iOS implementation of the alphabetic index down the right edge doesn't have an Android equivalent, for example
Notes:
UITableViewSource
has been implemented as an nested class to resemble the iOS pattern of implementing the equivalent Obj-C protocols on the ViewController - this pattern makes no sense in Android so the classes are separate.- The MonoTouch example code builds the UI in C# (eg.
tableView=new UITableView();AddSubview (tableView);
) whereas MonoDroid loads layout XML filesSetContentView(Resource.Layout.Speakers);
. This can happen in bothViewDidLoad/OnCreate
andGetCell/GetView
where UI controls must be created and presented to the user. - The 'touch event handler' is in a different class: in MonoTouch the
TableViewSource
handles a touch for a specific row (NSIndexPath
); MonoDroid implements theItemClick EventHandler<ItemEventArgs>
on theListView
for a givenGetRow(e.Position)
. - Both examples use the constructor (
TableViewSource/SpeakersAdapter
) of the 'broker' class to pass the actual business object collection for display. This pattern lets the data be filtered/sorted/whatever before being passed in for display. - Calling
refreshSpeakers()
fromViewDidLoad/OnResume
is kinda redundant in this example since the list never changes - but in other spots (eg the Favorites screen) you would want to refresh the list each time because it may have changed.
The Code
You can have a look at the MonoTouch code SpeakersViewController.cs and the MonoDroid SpeakersActivity.cs, SpeakersAdapter.cs to see the actual implementation. For MonoDroid you'll also need to check out the layout XML files Speakers.axml and SpeakersItem.axml.
One more thing...
One final piece which takes some getting used to... in MonoTouch this screen is part of a
UINavigationController
stack and your RowSelected
creates a new ViewController object (passing whatever parameters you need) and calls NavigationController.PushViewController()
. The ViewController instances in the navigation stack are 'stateful' and it is really easy to pass business objects around as parameters.In MonoDroid, the ever-present 'back-stack' does not require a specific 'navigation controller' BUT at it's simplest the mechanism is much more primative and involves passing simple type parameters (eg. strings) like this
var intent = new Intent();
intent.SetClass(this, typeof(SpeakerActivity));
intent.PutExtra("Name", speaker.Name);
StartActivity(intent);
There are more sophisticated approaches but it is probably best to keep your parameter-passing to a minimum - this way the Android hardware 'Back' button "just works".
HTH Slava ;-)
Nice Explanation, but to support tablet and future ice cream sandwich you should also show the example using the fragments API which is back compatible by jar to Android 1.6. So you would want the Activity with a fragment with the actual UI logic. That way the fragment could be composed into a more elaborate tablet friendly layout. Hopefully Mono-On-Android will have fragments from the beginning. Thanks for the good blog posts.
ReplyDeleteThere's a few reasons I don't touch on Fragments here:
ReplyDelete* "Novell's Mono-for-Android" never supported Android 3.0 (and therefore the _built-in_ implementation of Fragments)
* The vast majority of Android devices out there are still phones, not tablets, so Fragments could be considered overkill in many cases
* This is really an example for beginners, and as such is simpler _without_ Fragments
* It is a little more work to use external JAR files (gregshackles.com...using-admob-in-a-monodroid-application) -- the only way you could use the Fragment implementation that is floating around for pre-SDK-11 -- which again doesn't really suit a 'beginners example'
Thanks for the feedback though. I'm sure Fragments will be a part of future Mono-on-Android implementations that target Honeycomb and newer Android releases.