Get your MonoTouch apps ready for iPhone 5 / iOS 6 today!

 

So the new iPhone 5 has arrived, as well as the Gold Master iOS6 SDK! Hurray!

Unless you’ve been under a rock, you know that the iPhone 5 has a taller screen, which means a new screen resolution to deal with for us developers! Apple is lacking bit in their own documentation, but a few developers have figured out how to best handle the new resolution.

First of all, the new resolution is 640×1136, that’s 640 pixels wide, by 1136 high. Now, just like the Retina display, even though this is the resolution, many parts of the iOS API report back the sizes in points rather than pixels, which means the new size in points is really 320×568. I’d like to share with you how you can get your MonoTouch apps up and running to be compatible with the new resolution today!

First, Install the X-Code 4.5 GM iOS6 SDK from the Apple Developer site

It’s listed as the iOS6 beta at the time of writing this post, but it’s really GM once you get to the download section. You must be part of the paid Apple Developer program to be able to access this. Download the .dmg, mount it, and drag XCode into your Applications folder. You may want to rename the old one so you can revert to it if need be. I renamed the old one XCode 4.4.1.app.

Create a Default.png of the correct size

The way that iOS6 determines if your app is Tall compatible or not is by looking for a specifically sized and named image file for your splash/default screen. The name of this file is:

Default-568h@2x.png

This file must actually be 640×1136 pixels in size.
Add this file to your MonoTouch Application Project, and make sure the Build mode is set to Content.

Change the Simulator to iPhone (Retina 4-inch)

After your MonoTouch Application starts in debug mode, you may need to change the Simulator to use the new hardware type. Go to the Hardware -> Device menu, and select “iPhone (Retina 4-inch)”. You may need to re-launch your app after doing this.

Presto, your app now runs in ‘Tall’ mode!

Create new sizes of other Image assets

Unfortunately, the image naming convention of -568h@2x.png only seems to extend to the Default image, but not other images in your application. This means if you’re using a custom background image for your view (eg: UITableView background), you will likely need to create a new background image of the correct resolution, and determine in your application when to use each image.

For example, in my non-4inch compatible app, I have two images:

  1. Images/TableViewBackground.png – 320×358
  2. Images/TableViewBackground@2x.png – 640×716

With the new resolution, I’ll need to create a third image (I’ve decided to use the -568h@2x.png naming convention even though it isn’t observed by Apple):

  1. Images/TableViewBackground-568h@2x.png

Write some code to detect iPhone 5 and use the new Image Assets

Now as I mentioned, even though I’ve named the image just like the way Apple detects the new default image, iOS6 (at least currently) doesn’t know to use it automatically, so we have to write some code to detect when the app is running on an iPhone 5, and then to use the correct image when that’s the case.

Here’s some sample code to detect whether or not we have an iPhone 5. I’ve elected to call it ‘Tall’ detection, as the iPhone 6 will likely use this tall resolution too. NOTE: Thanks to @Clancey for some additions to the IsTall detection!

public static bool IsTall
{
  get
  {
    return UIDevice.CurrentDevice.UserInterfaceIdiom
             == UIUserInterfaceIdiom.Phone
           && UIScreen.MainScreen.Bounds.Height
             * UIScreen.MainScreen.Scale >= 1136;
  }
}

Finally, the approach I take in my applications is to use a common property for the image, and make that property getter decide on the height of the device, and which image to return:

static UIImage tableViewBackgroundImage = null;
public static UIImage TableViewBackgroundImage
{
  get
  {
      if (tableViewBackgroundImage == null)
          tableViewBackgroundImage = IsTall
              ? UIImage.FromFile("Images/TableViewBackground-568h@2x.png")
              : UIImage.FromFile("Images/TableViewBackground.png");

      return tableViewBackgroundImage;
  }
}

In this example, I keep a single static instance of my background image around, and lazy load it based on whether or not it’s a tall device. This way the same image instance is shared for multiple viewcontrollers that use it! In the case where it’s not a tall device, Apple still obeys the @2x.png naming convention to load retina graphics automatically, so you still don’t have to do that detection, it’s done for you.

Other considerations

If you have any other code that does anything with height calculations, or maybe creating a view to be a certain height, you may also need to update this code. The general rule is you should now be calculating heights and y-coordinates based on the UIScreen.MainScreen.ApplicationFrame or UIScreen.MainScreen.Bounds. This is probably a good practice anyway, and hopefully you don’t need to do too much work since you’ve already been following that good practice, right?

Hopefully that helps get your MonoTouch apps prepared for iPhone 5, before it’s even out!

UPDATE:

Select the right Image!

@martinbowling contributed another nice method to add to your ‘helper’ class shortly after this post was originally published. It will help you select the right Image in code, easily! It expects that you name your ‘Tall’ image files with the -568h@2x convention. This is another, even better technique than I’ve illustrated above. Perhaps Xamarin will adopt this method in the future…

private static string tallMagic = "-568h@2x";
public static UIImage FromBundle16x9(string path)
{
  //adopt the -568h@2x naming convention
  if(IsTall())
  {
      var imagePath = Path.GetDirectoryName(path.ToString());
      var imageFile = Path.GetFileNameWithoutExtension(path.ToString());
      var imageExt = Path.GetExtension(path.ToString());
      
      imageFile = imageFile + tallMagic + imageExt;
      
      return UIImage.FromFile(Path.Combine(imagePath,imageFile));
  }
  else
  {
      return UIImage.FromBundle(path.ToString());
  }
}

The problem with Apples Push Notification Service… Solutions and Workarounds…

Push Notifications have intrigued me since Apple first introduced them in iOS years ago. RIM had been doing this for a while, but as a platform it never excited me. As soon as the documentation for their APNs protocol was released I started busily implementing a solution to send push notifications in C#. The first version of the protocol was already terrible, but I’m not going to harp on that as we’ve got a newer version that’s only slightly better to tear apart.

I’m the author of PushSharp (https://github.com/Redth/PushSharp) which is a .NET library to assist developers in delivering push notifications on as many platforms as possible (iOS, Android, Windows, Windows Phone, and HTML5). This library was the culmination of my previous efforts in individual libraries (APNS-Sharp and C2DM-Sharp mostly), and represents a more abstracted, standardized, easier way to support push notifications on all the platforms you may target as a developer.

This post is a chance for me to vent, to explore my frustrations with Apple’s APNS protocol, and hope that they somehow listen and change it. You’ll notice how there’s no complaining about the way the other platforms implement their protocols. This is because they aren’t terrible (though they aren’t perfect either).

Apple’s Enhanced Format for Push Notifications

I had great hopes that Apple finally fixed its protocol when they introduced the Enhanced format (basically v2 of their protocol). Both the original and the enhanced format are binary protocols. You can quickly see the differences between the two in the diagrams below:

Original Protocol:
Original-Binary-Protocol

Enhanced Protocol:
Enhanced-Binary-Protocol

You’ll notice that in the enhanced protocol, there’s two additional bits of information (besides the first byte being 1, indicating that it’s the new protocol as opposed to 0 in the original). These are two very good additions to the protocol:

  1. Identifier – Your own 4 byte data to uniquely identify the notification – this is important as it’s returned to you in the error response packet if there’s a problem.
  2. Expiry – A point in time after which the message is no longer valid if it has not already been delivered and can be discarded from Apple’s servers

In the original protocol, whenever you send Apple a notification that has a problem with it (maybe it’s too big, or it has an invalid device token or malformed payload, etc.), it simply closes the TCP connection without any warning. You are left to assume something is corrupt in your notification.

With the enhanced protocol also handles bad notifications it receives a bit differently. It still closes the connection to you when there’s an error, but before it does so, it sends back an error response packet. You can see the format in the diagram below, along with a list of status codes and their meanings:

Error Response Packet:
Error-Response-Packet

Status Codes & Meanings
0 - No errors encountered
1 - Processing error
2 - Missing device token
3 - Missing topic
4 - Missing payload
5 - Invalid token size
6 - Invalid topic size
7 - Invalid payload size
8 - Invalid token
255 - None (unknown)

This packet is quite simple, with the first byte presumably indicating the protocol version, the second byte being the status or error code (Apple provides us with a list of status codes and what they mean – interestingly enough one of the status codes is ‘0 – No errors encountered’ – just keep this in mind for later). The final piece of info is the Identifier. This identifier will correspond to the identifier of the notification you sent which caused the error condition.

What’s the problem here?

So far so good, right? Well, not so much. In theory this all sounds very good. Finally, we get an error response from the service, and some additional functionality. But there are still two major issues with the protocol that you would discover very quickly if you decided to try and implement a client for it yourself:

  1. Apple never sends a response for messages that succeeded.
  2. An error response may not immediately be returned before you have a chance to send more notifications to the stream, but before Apple closes the connection. These notifications that might still ‘make it through’ are left in limbo. They are never acknowledged or delivered, and never have error responses returned for them.

How could Apple fix this?

Remember how I told you to keep in mind the error response status code of ‘0 – No errors encountered’? This is the silver bullet. If Apple simply always returned an error response, for every notification, even if the notification succeeded, we could simply build a library that wrote a notification to the stream, waited for a response, and then moved onto the next notification, over and over. There’d be no business of waiting around for an error response that might never come, and greatly simplify the pains of implementing this protocol. Apple might argue that this would consume more bandwidth, and while they may be right, in this day and age it would only amount to another ~6 MB per 1,000,000 notifications delivered. Considering that Google and Windows Phone both use HTTP protocols and generate significantly more bandwidth based on the underlying protocol alone, and are able to keep their infrastructure running, an extra 6 bytes per notification should be pocket change to Apple in the cost of maybe a few additional servers and bandwidth allocation.

It’s such a simple answer. It’s even in Apple’s own documentation. Yet, it’s not our reality.

So what is the workaround?

I’ve looked at many libraries, written in many different languages, to see how they worked around this problem. In about 99% of the cases I’ve observed, they all use the same, sadly inefficient approach: Waiting.

So again, we have a connection to Apple’s APNS server, and we want to send notifications over that connection repeatedly, and as fast as possible. Apple never sends us a response if a notification was sent successfully, but if one failed, they will send us an error response and close our connection.

The problem is, if we keep sending notifications over and over again, we might send a second, or third notification before Apple ever sends us an error response for the first one that failed. If this happens, the second and third notifications are never delivered, and are lost forever.

The easiest way to solve this is to asynchronously read from the connection stream, waiting for an error response. In doing so, however, this means you must also wait a little while after you write each notification to the stream to see if your asynchronous read ever receives anything. You can’t just do a synchronous blocking read on the stream since you’d be waiting indefinitely if the notification succeeded (since Apple sends no response in this case). To make matters worse, Apple doesn’t guarantee how quickly an error response will be sent to us. I’ve seen libraries wait for an error response from anywhere between 100 to 500 milliseconds.

It should be painfully obvious to you by now why this approach is flawed. If you have to wait even 100 milliseconds after sending every notification, that would take you almost 28 hours to send 1,000,000 notifications over a single connection!

Most libraries employ the use of multiple connections to circumvent this new issue they’ve created for themselves by waiting between each notification. If you use 10 connections to apple’s servers, that cuts your time down to 2.8 hours. This is better, but why should it take 10 connections 2.8 hours to deliver a theoretical maximum of only 300MB of data (1,000,000 notifications * 301 bytes maximum size per notification)? This is asinine!

A better workaround

I just couldn’t stand the thought of wasting 100-500 milliseconds per notification sent. I figured there had to be a better way, and I think I’ve found it! PushSharp employs a technique that is fairly easy in theory, and was a bit more difficult to implement in code.

Each time a notification is written to the connection stream, it is then added to a ‘Sent’ queue. If an error response is received, the corresponding notification is located in the ‘Sent’ queue (by its identifier). Anything before the error-causing notification in the queue is removed and assumed to be successfully sent. Anything after the error-causing notification is assumed to be lost, and re-queued to the ‘To Send’ queue to be tried again. There is also a cleanup thread running that constantly checks the oldest notification in the ‘Sent’ queue to see if it’s older than a few seconds and if so, it is assumed to have been successfully sent and is removed from the ‘Sent’ queue. This effectively moves the waiting period for an error response outside of the scope of the connection to the APNS servers. The diagram below illustrates how the Sent queue works:

PushSharp Sent Queue
PushSharp-Sent-Queue

Conclusion

So that’s it, that’s my big speech on why Apple’s Push Notifications are so troublesome, how they could make my life a lot easier with a couple small changes, and how I’ve learned to cope with the situation for now. I hope you enjoyed my ramble, and do please check out PushSharp!

Using the Android Contact Picker with Xamarin.Mobile to Send an SMS in Mono for Android 4.0

First and foremost: Xamarin has been doing an awesome job with their MonoTouch and Mono for Android product line! Huge kudos to the entire team for allowing us some much needed obj-c and java mobile platform escapism!

If you don’t know about Xamarin, they are the company behind products allowing developers to write TRUELY NATIVE applications for Android and iOS in C#! I honestly can’t say enough good things about these products, but you should check them out for yourself: http://xamarin.com

Onto the goodies. If it wasn’t enough for us to be able to access native iOS and Android API’s via C#, Xamarin has gone ahead and started building a cross mobile platform set of libraries which aim to help us developers even more in creating sets of code to be reused on all the great mobile platforms. You can check out more about this initiative here: http://blog.xamarin.com/2011/11/22/introducing-the-xamarin-mobile-api/

The latest preview version of Xamarin.Mobile just hit the intertubes, and I was keen to try it out as a replacement to some awful code I had to write to deal with the Android API’s for Contacts. This latest preview now contains Contacts and Location API support for both MonoTouch and Mono for Android. In the sample below, you can see some Android specific code, so I’m not truely writing cross platform code here, but with a bit of abstraction from the UI layer, this would be possible. However, the purpose of this example is more to show you just how bleeping easy it is to work with Contacts in Mono for Android using Xamarin.Mobile!

It’s so simple I don’t even think it needs any explanation past the comments in the code I’ve provided! Enjoy!

PS – A special thanks to @ermau who has been hard at work creating Xamarin.Mobile, and has been super helpful (how cliche of Xamarin folks!) in using it!

void button_Click(object sender, EventArgs e)
{
  //Create a new intent for choosing a contact
  var contactPickerIntent = new Intent(Intent.ActionPick,
      Android.Provider.ContactsContract.Contacts.ContentUri);

  //Start the contact picker expecting a result
  // with the resultCode '101'
  StartActivityForResult(contactPickerIntent, 101);
}
public override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
  //See if we are handling the contact picker request code
  //  and that the result code is ok!
  if (requestCode == 101 && resultCode == Result.Ok)
  {
      //Ensure we have data returned
      if (data == null || data.Data == null)
          return;

      //Xamarin.Mobile code here 🙂
      var addressBook = new Xamarin.Contacts.AddressBook(this);
      //Note: This is important 
      addressBook.PreferContactAggregation = true;

      //Load the contact via the android contact id
      // in the last segment of the Uri returned by the 
      // android contact picker
      var contact = addressBook.Load(data.Data.LastPathSegment);

      //Use linq to find a mobile number
      var mobile = (from p in contact.Phones where
                      p.Type == Xamarin.Contacts.PhoneType.Mobile
                      select p.Number).FirstOrDefault();

      //See if the contact has a mobile number
      if (string.IsNullOrEmpty(mobile))
      {
          Toast.MakeText(this, "No Mobile Number for contact!",
              ToastLength.Short).Show();
          return;
      }

      //Send SMS!
      var smsMgr = Android.Telephony.SmsManager.Default;

      smsMgr.SendTextMessage(mobile, null, "Hello World!", null, null);
  }
}

MonoDroid – Custom ListAdapter for your ListView

I don’t know about you, but the main thing I’m interested in on any new mobile development platform for some reason, is LISTS. I think I’m so fixated on lists is because of the way the iPhone so successfully introduced the paradigm of list based navigation. Everything can be done in a series of lists (ok not really, but they are crucial to many apps!).

Xamarin Android Custom List

Naturally then, the first thing I sought out to do on MonoDroid was to create a list. Easy, piece of cake… If you want to create a boring old list with a single line of text for each item. This is no doubt, an important part of every developer’s Hello World development phase, but it doesn’t take long before you’re craving images, several text elements, and possibly even some checkboxes and/or buttons (easy there tiger). For every ListView in Android, there is a prince charming ListView Adapter to save the day.

The most basic of examples which you’ve no doubt seen involve an ArrayAdapter of some sort, with the default Android.R.Layout.SimpleListItem or whatever it is called. BOOORING. What we need to do to make something exciting is create our own custom ListView Adapter. Now, you could use a SimpleAdapter to map fields to certain resource id’s of a layout, but if you look at a java example of this, ‘Simple’ quickly becomes a relative term. What I like to do is create my own adapter deriving from the BaseAdapter class (how fitting).

Here’s some code for my custom list adapter (explanation to follow):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Graphics.Drawables;

namespace MonoDroid.CustomList
{
  public class CustomListAdapter : BaseAdapter
  {
    Activity context;

    public List<Animal> items;

    public CustomListAdapter(Activity context) //We need a context to inflate our row view from
      : base()
    {
      this.context = context;

      //For demo purposes we hard code some data here
      this.items = new List<Animal>() {
        new Animal() { Name = "Elephant", Description = "Big and Gray, but what the hey", Image = Resource.drawable.elephant },
        new Animal() { Name = "Chinchilla", Description = "Little people of the andes", Image = Resource.drawable.chinchilla },
        new Animal() { Name = "Lion", Description = "Cowardly lion, anyone?", Image = Resource.drawable.lion },
        new Animal() { Name = "Skunk", Description = "Ello, baby. I am ze locksmith of love, no?", Image = Resource.drawable.skunk },
        new Animal() { Name = "Rhino", Description = "Most live to about 60, pretty old eh?", Image = Resource.drawable.rhino },
        new Animal() { Name = "Zebra", Description = "Stripes maybe not so great for hiding", Image = Resource.drawable.zebra },
        new Animal() { Name = "Squirrel", Description = "Nuts nuts, where's my nuts?!", Image = Resource.drawable.squirrel },
        new Animal() { Name = "Walrus", Description = "I am he as you are he as you are me", Image = Resource.drawable.walrus },
        new Animal() { Name = "Giraffe", Description = "Bigger than your ford pinto", Image = Resource.drawable.giraffe },
        new Animal() { Name = "Chicken", Description = "I'll take 2 eggs over easy", Image = Resource.drawable.chicken },
        new Animal() { Name = "Duck", Description = "He's all quacked up", Image = Resource.drawable.duck },
        new Animal() { Name = "Hawk", Description = "He needs to be on a t-shirt", Image = Resource.drawable.hawk },
        new Animal() { Name = "Lobster", Description = "We were at the beach...", Image = Resource.drawable.lobster },
        new Animal() { Name = "Pig", Description = "Babe, Orson, Piglet, whatever", Image = Resource.drawable.pig },
        new Animal() { Name = "Rabbit", Description = "Thumper is the best rabbit name ever", Image = Resource.drawable.rabbit },
        new Animal() { Name = "Turtle", Description = "Slow and steady wins the race", Image = Resource.drawable.turtle },
      };
    }

    public override int Count
    {
      get { return items.Count; }
    }

    public override Java.Lang.Object GetItem(int position)
    {
      return position;
    }

    public override long GetItemId(int position)
    {
      return position;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
      //Get our object for this position
      var item = items[position];			

      //Try to reuse convertView if it's not  null, otherwise inflate it from our item layout
      // This gives us some performance gains by not always inflating a new view
      // This will sound familiar to MonoTouch developers with UITableViewCell.DequeueReusableCell()
      var view = (convertView ?? 
        context.LayoutInflater.Inflate(
          Resource.layout.customlistitem, 
          parent, 
          false)) as LinearLayout;

      //Find references to each subview in the list item's view
      var imageItem = view.FindViewById(Resource.id.imageItem) as ImageView;
      var textTop = view.FindViewById(Resource.id.textTop) as TextView;
      var textBottom = view.FindViewById(Resource.id.textBottom) as TextView;

      //Assign this item's values to the various subviews
      imageItem.SetImageResource(item.Image);
      textTop.SetText(item.Name, TextView.BufferType.Normal);
      textBottom.SetText(item.Description, TextView.BufferType.Normal);

      //Finally return the view
      return view;
    }

    public Animal GetItemAtPosition(int position)
    {
      return items[position];
    }
  }
}

Oh, and here’s the Animal class if you’re curious:

namespace MonoDroid.CustomList
{
  public class Animal
  {
    public string Name
    {
      get;
      set;
    }

    public string Description
    {
      get;
      set;
    }

    public int Image
    {
      get;
      set;
    }
  }
}

Now for the sake of the demo, I create my own data inside the adapter, and of course nothing is stopping you from getting that data from a webservice, or somewhere more fashionable. The first thing to note is that I’m requiring an Activity object in the ctor. This really is only used to get the LayoutInflator for the given Activity so that we can inflate our row’s View later on, but it is important to have it. Next thing of interest is the overrides. All we really need to override is the Count property, GetItem method, GetItemId method, and GetView method. The last method (GetItemAtPosition) is my own addition so that I can read out the object for a given position elsewhere in the project (in this case, when a ListView.ItemClicked event is fired).

Count is easy, just return your object list’s count (duh). GetItem and GetItemId I’m still not convinced are necessary, but I override them anyways and just return the position in each case. The only significance I know of so far with these properties is in some ListView events, the item Id is passed as an event arg. However, in these same events, we also get the item’s position, which is why I have the GetItemAtPosition method, so I can retrieve the relevant object for the event. I’d love to hear from anyone who knows more about why I might want to pay more attention to the GetItem and GetItemId methods.

GetView is where the magic happens. Basically, I get the item for the given position first. Next, I determine if the convertView parameter is null or not, and inflate my CustomListItem’s layout into a usable View (LinearLayout to be specific). This is basically a way for us to reuse resources. Anyone familiar with MonoTouch and the Reusable UITableViewCell will feel right at home here. We could inflate the resource every time, but that would waste unnecessary resources. So, best practice here is to always reuse if the convertView is not null. Now then, with my LinearLayout instance, I can locate all of the views within that I want to assign information to, for the given row. As you can see in this case, I have an ImageView, and two TextView’s.

Here is what the layout xml looks like for my custom list item:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/widget28"
  android:layout_width="fill_parent"
  android:layout_height="80px"
>
  <ImageView
  android:id="@+id/imageItem"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="center_vertical"
    >
  </ImageView>
  <LinearLayout
  android:id="@+id/linearText"
  android:layout_width="wrap_content"
  android:layout_height="fill_parent"
  android:orientation="vertical"
  android:layout_marginLeft="10px"
  android:layout_marginTop="10px"
    >
    <TextView
    android:id="@+id/textTop"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView"
      >
    </TextView>
    <TextView
    android:id="@+id/textBottom"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="TextView"
      >
    </TextView>
  </LinearLayout>
</LinearLayout>

Once I have found references to these, I can set their text and image. Finally, I can return the LinearLayout View that I’ve been working on for this row. That wasn’t so hard, was it? Last, but not least, we need to actually deal with our Activity that holds the ListView. Up until now we had just created the adapter that our ListView was going to use. Now we need to actually hook an adapta’ up.

Here’s what my Activity code looks like:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace MonoDroid.CustomList
{
  [Activity(Label = "1 CustomList", MainLauncher = true)]
  public class CustomList : Activity
  {
    CustomListAdapter listAdapter;

    public CustomList(IntPtr handle)
      : base(handle)
    {
    }

    protected override void OnCreate(Bundle bundle)
    {
      base.OnCreate(bundle);

      //Set the Activity's view to our list layout		
      SetContentView(Resource.layout.customlist);

      //Create our adapter
      listAdapter = new CustomListAdapter(this);

      //Find the listview reference
      var listView = FindViewById<ListView>(Resource.id.listView);

      //Hook up our adapter to our ListView
      listView.Adapter = listAdapter;

      //Wire up the click event
      listView.ItemClick += new EventHandler<ItemEventArgs>(listView_ItemClick);
    }

    void listView_ItemClick(object sender, ItemEventArgs e)
    {
      //Get our item from the list adapter
      var item = this.listAdapter.GetItemAtPosition(e.Position);

      //Make a toast with the item name just to show it was clicked
      Toast.MakeText(this, item.Name + " Clicked!", ToastLength.Short).Show();
    }
  }
}

Here’s the layout xml behind this activity:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/widget28"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
>
  <ListView
  android:id="@+id/listView"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
>

  </ListView>
</LinearLayout>

So you can see in my Activity’s OnCreate, I’m calling the base method (important), and then setting the activity’s content view to the layout xml that I showed you above. I’m also creating an instance of the CustomListAdapter I made earlier, and finding a reference to my ListView, so that I can set my ListView’s .Adapter property to the instance of the CustomListAdapter. As a bonus, I register the ItemClick event of my ListView, and in it, retrieve the item for the given position, from my CustomListAdapter, using the method I added to the adapter (GetItemPositionAt). I then display a Toast with the name of the Animal clicked.

Hopefully this little tutorial enlightens you on how to make some fancy lists (not those boring default ones). I’ve also made the source code of the entire project available:

http://goo.gl/AcGI