The Binding feature of Xamarin is one of the most powerful one that I’ve seen when playing with the product. Indeed, it allows you to reuse any Java libraries (available as JAR files) directly from your application (written in C#).

This wonderful feature is made available by the Xamarin team thanks to the Managed Callable Wrappers. If you look at my first article about Xamarin, you’ll learn that the MCW are just JNI (Java Native Interface) bridges, some generated code, that are used every time the managed code needs to invoke Java code (on the other hand, when the Java code needs to call managed code, it’s another bridge, named Android Callable Wrapper, that is used).

 

Using the feature is really simple thanks to Visual Studio (or Android Studio). First, you need to create an Android Bindings Library:

image

Once this is done, the IDE will create a project containing the following elements:

  • A folder “Jars” that contains all the JAR files you want to reuse
  • A folder “Transforms” that contains some configuration files used to control the wrappers’ generation
  • A folder “Additions”, that can contains C# code which can be added to the generated classes

image

As we told previously, we’ll be able to reuse any Java library so, for this article, I’ve just grabbed a copy of the Java Image Library available here: http://www.jhlabs.com/ip/filters/download.html

Once you’ve downloaded the JAR file, simply drop it to the Jars folder and set its “Build Action” to “InputJar”:

image

This tells Xamarin to create a bridge for each Jar files defined using this build action.

So now, you’ve basically finished your job. Indeed, most of time, you have nothing else to perform but just compile to get a .NET DLL that can be referenced to your Xamarin.Android application.

If you care, you can take a look to the folder obj\Debug\generated\src to see the generated files used to create the DLL:

image

Sometimes, you might need to solve some issues due to the code generation. Indeed, folks at Xamarin performs 99% of the code generation but there are some things you need to change in order to compile correctly.

In our case, here is the result when we tried to compile our project:

image

Holy crap, it’s not working! According to the error message, it looks like we have a member of a class with the same name as its enclosing type. If we perform a double click on the error message, Visual Studio opens the generated file on the error:

image

Interesting right? We can see that the Histogram class that has been generated has a property named Histogram too, which is not allowed. So we need to find a way to rename this property automatically while performing code generation so the code could compile correctly.

To do this, we need to check in the “Transforms” folder to see the files available for the code generation customization:

  • EnumFields.xml is used to map a Java int value to a .NET enum
  • EnumMethods.xml is used to change the generation of methods’ parameters
  • Metadata.xml is used to change names of types, members, etc.

image

As we want to change the name of a class member, we need to edit the file Metadata.xml to instruct the code generator to change the name of the field Histogram of the type Histogram.

So we just add the following:

<attr path="/api/package[@name='com.jhlabs.image']/class[@name='Histogram']/field[@name='histogram']" name="name">Current</attr>

 

Doing so, we just tell the code generator to change the name of the field Histogram of the type Histogram and to replace it by “Current”. Now, if we build the library, we don’t get any errors and if we look on the generated file, we can see that the property’s name has changed:

image

Now, we can test our library! For that, it’s simple: just create a new Xamarin.Android application and add a reference to your library:

image

Note: If you have some issues when adding the reference as a project reference, try to add it as a DLL instead (see here)

Then, using the library is as simple as using any existing libraries:

image

Even if that works fine, there are at least 2 things that I don’t like:

    • The namespace are the Java’s one
    • The name of the parameters are p0, p1, p2, etc.

Changing the namespace is straightforward. Once again, we need to edit Metadata.xml:

<attr path="/api/package[@name='com.jhlabs.image']" name="managedName">ImageProcessingLibrary</attr>

Thanks to this line, we are able to change the name of the .NET namespace (without touching of the Java’s one):

image => image

Again, as the name of the namespace change, we need to modify the code of our test application:

image

Now, let’s see how to change the name of the parameters. This one is not complex but might take the most of time, as you may want to do it for all the methods.

Again, all will be done in Metadata.xml, by adding the following line (one line for each methods’ parameters you want to rename):

<attr path="/api/package[@name='com.jhlabs.image']/class[@name='LightFilter']/method[@name='addLight']/parameter[@name='p0']" name="name">lightToAdd</attr>
<attr path="/api/package[@name='com.jhlabs.image']/class[@name='LightFilter']/method[@name='removeLight']/parameter[@name='p0']" name="name">lightToRemove</attr>

We just instruct the code generator so in the namespace com.jhlabs.image, find the class LightFilter, look for the methods addLight and removeLigh and rename the parameter initially named p0.

Here is the code that has been generated:

image image

And when using the Intellisense, we can see the correct name for our parameters:

image

 

Previously, I talked about the “Additions” folder which can contains code that will be added to the generated classes.

Using this feature is as simple as writting code files and put them in the folder (all the magic is performed at compilation). All the classes generated by the code generator are marked as partial so it’s easy to add custom code. For example, add a file containing the following code:

public partial class LightFilter
{
    public void AddLightByName(string lightName)
    {
        //
    }
}

Now, if you compile and use your library, you’ll be able to use the new method AddLightByName:

image

 

As you can see, the Binding feature is really cool and easy to use! Of course, most of the job is performed under the cover by the Xamarin tools but it’s very flexible and configurable so let’s try it: you won’t regret it!

If you want to know more (specially about the possible errors you may encountered), you can check the official documentation.

Happy coding! :)

I’m proud to announce that my second MSDN article has been finally published in the August issue of MSDN Magazine!

Entitled “Build MVVM Apps with Xamarin and MvvmCross”, the article will let you know all you need to start developping MVVM apps with Xamarin and MvvmCross.

I hope you’ll like it!

 

Happy coding!

When using Xamarin.Forms, you have a lot of differents pages and layouts available to build your applications.

The TabbedPage is a very good one that allows you to navigate betweend children pages, using tabs. Unfortunately, the control does not offer the possibility to know when the current page is changing (or has changed).

So, a possible workaround, when using this base class, is to add an event handler on the PropertyChanged event and watch for the property CurrentPage. Here is a sample demoing that:

public delegate void CurrentPageChangingEventHandler();
public delegate void CurrentPageChangedEventHandler();

public class ExtendedTabbedPage : TabbedPage
{
    public event CurrentPageChangingEventHandler CurrentPageChanging;
    public event CurrentPageChangedEventHandler CurrentPageChanged;

    public ExtendedTabbedPage()
    {
        this.PropertyChanging += this.OnPropertyChanging;
        this.PropertyChanged += this.OnPropertyChanged;
    }

    private void OnPropertyChanging(object sender, PropertyChangingEventArgs e)
    {
        if (e.PropertyName == "CurrentPage")
        {
            this.RaiseCurrentPageChanging();
        }
    }

    private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "CurrentPage")
        {
            this.RaiseCurrentPageChanged();
        }
    }

    private void RaiseCurrentPageChanging()
    {
        var handler = this.CurrentPageChanging;
        if (handler != null)
        {
            handler();
        }
    }

    private void RaiseCurrentPageChanged()
    {
        var handler = this.CurrentPageChanged;
        if (handler != null)
        {
            handler();
        }
    }
}

To use it, you now just have to register for the event CurrentPageChanging or CurrentPageChanged:

public class MainPage : ExtendedTabbedPage
{
    private readonly OrganizerView _organizerView;
    private readonly AttendeeView _attendeeView;

    private readonly ToolbarItem _refreshToolbarItem;

    public MainPage()
    {
        this.Title = "Meeting Organizer";

        this._organizerView = new OrganizerView();
        this._attendeeView = new AttendeeView();

        this.Children.Add(this._organizerView);
        this.Children.Add(this._attendeeView);

        this._refreshToolbarItem = new ToolbarItem("Refresh", "refresh.png", () =>
        {
            //
        });

        this.CurrentPageChanged += OnCurrentPageChanged;
    }

    private void OnCurrentPageChanged()
    {
        if (this.CurrentPage == this._organizerView)
        {
            this.ToolbarItems.Clear();
        }
        else if (this.CurrentPage == this._attendeeView)
        {
            this.ToolbarItems.Add(this._refreshToolbarItem);
        }
    }
}

Simple but useful !

 

Happy coding!

I like to think that I’m open minded enough to look at a lot of things. Recently, I’ve started to look at Xamarin not to start developing apps on Android but just to be able to know the product and I have to say that it’s very interesting. I’ll try to make more posts on it but, for now, let’s take a look that the big picture of it!

 

What is Xamarin ?

 

 Xamarin is a set of tools developers can use to delivers high performance compiled code with full access to all the native APIs so you can create native apps with device-specific experiences. Anything you can do in Objective-C or Java, you can do in C# with Xamarin.

The other good point is that even if you can use Xamarin Studio to develop your app, you can also use Visual Studio and all the other tools you already use for any C# development. This include Team Foundation Server (for the source control) but also plugins like Resharper, GhostDoc, etc.

Finally, to let you share code easily across iOS, Android and Windows Phone, you can also use the Portable Class Library (PCL) to create a core component that will be available on all the platforms (only the GUI part will be specific). The following article give your more details on how to work with the PCL and Xamarin Studio or Visual Studio (if you are already using the PCL on Visual Studio, you’ll see that there are no big differences!).

 

How does it work ?

Xamarin offers 2 mains products: Xamarin.iOS (MonoTouch.dll) and Xamarin.Android (Mono.Android.dll). Both of them are developed on top of Mono, the open source version of the .NET Framework. For those who have been on the .NET community for a long time, you may remembered that Mono project has been initiate by Miguel De Icaza, the co-founder and current CTO of… Xamarin :)

On iOS, a dedicated compiler (AOT: Ahead Of Time) compiles applications written on C# directly to native ARM code.

For Android, the process is similar to the .NET compilation and execution: the source code is compiled to an Intermediate Language (IL) and, when the code is executed on the device, a second compilation (performed Just-In-Time, JIT) compile the IL to native code. This makes sense because Android applications are used to be developed in Java, which has an internal architecture similar to the .NET architecture.

In both case, you don’t have to worry about the memory management, resources allocation, etc.: all is managed, for you, by the runtime delivered by Xamarin.

Once compiled, the Android applications are packaged in a file with the .apk extension. Like XAP files, these files are only ZIP files that contains:

  • The Android manifest file, on binary format (more on that later)
  • The application code (compiled into the file classes.dex)
  • The differents assets included in the package
  • The differents resources (layouts, drawable)
  • The native libraries containing the Mono runtime.

This last point is important. Indeed, an Android application must be deployed with the native libraries for the desired architecture (armeabi, armeabi-v7a, x86). Be careful that your application won’t be able to run on a particular plateform until the dedicated runtime libraries are deployed on it:

image image

Finally, the Android application also contains the Android Callable Wrappers (ACW), which allows you to call managed code from the Android runtime. The full definition of the Android Callable Wrappers can be found online but, basically, this is similar to the Runtime Callable Wrappers (RCW): a proxy object that allows Java (or COM) to allow .NET code, without having to handle the difference of type between the two worlds. On the other side, the Managed Callable Wrappers (MCW) are bridges allowing .NET code to invoke Android code (so this is the opposite of Android Callable Wrappers). Managed callable wrappers are responsible for converting between managed and Android types and invoking the underlying Android platform methods.

 

What tools are available ?

Xamarin has its own IDE, Xamarin Studio, that looks like a lot to Visual Studio (well, to be honest, it’s more like the first version of SharpDevelop but at least, it’s working):

image

But Xamarin Studio can only be used to develop Android applications, not iOS apps:

image

Fortunately, for the .NET developers we are, it’s also possible to use Visual Studio to develop iOS and Andoid applications!

image

Xamarin also come with a lot of emulators that are available through Xamarin Studio and Visual Studio:

image image

There is also a very nice device manager that allow you to manage the different emulators installed:

image image

image

You may notice that I talk/write a lot about Android. This is not that I dont want to try iOS but to be able to test iOS, you need a Mac (with Xamarin.iOS installed on it) to play the role of a proxy between your PC and the target device. Unfortunately, as I don’t have a such device, I’m not able to try and test that part (if a Apple evangelist read my blog and want to offer me a Mac, feel free to him to do so ;-)

The first time you’ll start an Android emulator, you’ll see this message:

image

Trust me, this is true! Indeed, the first time the emulator starts, the IDE need to deploy on it the Mono Shared Runtime and the Platform Framework corresponding to the API level that will be targeted by your application. So, in my case, the initial start was up to 7 minutes ! Of course, once the emulator is started, the deployments are more faster.

 

A first look of the development part

Each page, of an Android application, is represented by an Activity object. This is the equivalent of the Page objects on Windows (Phone) apps. To define the activity that need to be launched on the first start, you need to put the MainLauncher property to true:

[Activity(Label = "AndroidApplication1", MainLauncher = true, Icon = "@drawable/icon")]
public class Activity1 : Activity
{
}

From the point of view of a XAML developer, the development is quite similar. Indeed, on the XAML side, we have the XAML part that defines the UI and the code-behind that corresponds to the app logic. Well, here, this is the same: the activity corresponds to the code-behind part and the XAML part will be associated to the AXML (no, it’s not a typo) files that we will see more in details later.

On the activity, the method OnCreate need to be override to add our own logic. This method is called when the activity is starting so this is where we’ll define our user interface, etc.:

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

To define the user interface, we can do it using 2 ways:

  1. By using C# code
  2. By using XML code.

The first way consists in building the GUI by code:

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

    var btn = new Button(this);
    btn.Text = "Hello World!";
    btn.Click += (sender, args) => { };

    SetContentView(btn);
}

image

Even if that works, this is not the most useful way (in particular to create complex UI). So we’ll prefer the XML way.

Each project contains a “Resources” folder that is composed by a set of sub-folders:

  1. Drawable: contains all the resources (images for example) that need to be used in the app
  2. Layout: contains all the layouts that will be designed by the developer
  3. Values: contains all the strings resources available

To add a new view, simply right clic on the Layout folder and select Add –> New item –> Android Layout:

image

The screen that appears offers a visual designer where you can drag and drop controls from the toolbox to create your custom UI:

image

If you click on the “Source” button (located at the bottom of the view), you’ll be able to see the XML representation of the GUI. So, like for the XAML part, the visual designer is just here to serialize the XML content and render it on a surface view:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:minWidth="25px"
    android:minHeight="25px">
    <Button
        android:text="Button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button1" />
</LinearLayout>

You may notice the particular syntax used to specify the value of the id property: @+id/button1. This syntax tells the parser to generate a resource with the id indicated so, on the file Resource.Designer.cs (which is refreshed after all builds and which contains all the resources values as strongly type properties) a property is automatically added:

public partial class Id
{
    // aapt resource value: 0x7f050001
    public const int MyButton = 2131034113;

    // aapt resource value: 0x7f050000
    public const int button1 = 2131034112;

    static Id()
    {
        global::Android.Runtime.ResourceIdManager.UpdateIdValues();
    }

    private Id()
    {
    }
}

For the strings values (of the buttons, labels, etc.), you have 2 choices: you can hardcode the value and set it to the dedicated property (for example, the Text property of the button) or you can use a similar principle as the id property. Indeed, here is a valid code to set the text property:

<Button
        android:text="@string/TestButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button1" />

So again, we tell the Android parser to generate a dedicated property to the resources file:

public partial class String
{
    // aapt resource value: 0x7f040001
    public const int ApplicationName = 2130968577;

    // aapt resource value: 0x7f040000
    public const int Hello = 2130968576;

    // aapt resource value: 0x7f040002
    public const int TestButton = 2130968578;

    static String()
    {
        global::Android.Runtime.ResourceIdManager.UpdateIdValues();
    }

    private String()
    {
    }
}

But this time, this is a bit different. The String class contains the property corresponding to the string resources we want to use but we have to define the values of these resources. To do so, we need to open and edit the file Strings.xml which is in the subfolder Values of the folder Resources:

 image

The content of this file is a simple list of key/value:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="Hello">Hello World, Click Me!</string>
    <string name="ApplicationName">AndroidApplication1</string>
    <string name="TestButton">My Super Button!</string>
</resources>

Using this system, it’s easy to create a localized version of your application. In the Resources folder, just add a folder “Values-XX” where XX corresponds to the two-letter language code (if you want to support multiples locales of the same language, add the two-letter region code prefixed by the –r letter, for example: Values-fr-rFR for the French France locale; Values-fr-rCA for the French Canadian locale, etc.):

 image

Add a new XML file on the newly created folder (be sure to set its Build Action property to AndroidResource) and just translate the content:

image  image

OK so now that our user interface is almost finished (eventually using string resources for the different labels), we need to display it! To do that, let’s go back to the code of the activity and just modify the parameter of the SetContentView to use our newly interface:

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

    // Set our view from the "demolayout" layout resource
    SetContentView(Resource.Layout.demolayout);
}

Again, after finishing the user interface, the parser generates a dedicated property so we can manipulate it:

public partial class Layout
{
    // aapt resource value: 0x7f030000
    public const int demolayout = 2130903040;

    // aapt resource value: 0x7f030001
    public const int Main = 2130903041;

    static Layout()
    {
        global::Android.Runtime.ResourceIdManager.UpdateIdValues();
    }

    private Layout()
    {
    }
}

image

Your view is now display on screen but you may wonder how you can interact with it so you can retrieve user inputs (clicks con button, etc.). For that, you’ll need to use the FindViewById method:

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

    // Set our view from the "demolayout" layout resource
    SetContentView(Resource.Layout.demolayout);

    var button = FindViewById<Button>(Resource.Id.button1);
}

This method takes in parameter the id of the control you want to manipulate through code (and you can notice, once again, the use of the Resource.Id nested class, which contains all the ids of the graphical elements). Once you get access to the controls, you can manipulate them easily:

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

    // Set our view from the "demolayout" layout resource
    SetContentView(Resource.Layout.demolayout);

    var button = FindViewById<Button>(Resource.Id.button1);
    button.Click += (sender, args) => SetContentView(Resource.Layout.Main);
}

You may also wonder how to access to some assets resources you can embed on the application. To do so, you have 2 choices. For the image files, you need to put them on the “Drawable” folder. After the build, the file Resource.Designer.cs will be updated (as we seen before). Then, to use your new file, simply use it as before:

<ImageView
        android:src="@drawable/Yoda"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/imageView1" />

Here, for the src property, I access to the Yoda file within the “Drawable” folder:

image image

For the other types of files (text files, sound files, video files, etc.), you need to put them on the Assets folder. Files placed on that folder will have a build definition set to AndroidAsset. To be able to use them, you need to call one of the methods of the Asset API of the AssetManager (Asset.Open, Asset.OpenFd, etc.):

var button = FindViewById<Button>(Resource.Id.button1);
button.Click += (sender, args) =>
{
    var assets = Assets.List(string.Empty);
    if (assets.Any())
    {
        var videoFilename = assets.FirstOrDefault(a => a.EndsWith(".mp4"));
        if (!string.IsNullOrWhiteSpace(videoFilename))
        {
            var fileDescriptor = Assets.OpenFd(videoFilename);

            var player = new MediaPlayer();
            player.SetDataSource(fileDescriptor.FileDescriptor, fileDescriptor.StartOffset, fileDescriptor.Length);
            player.Prepare();
            player.Start();
        }
    }
};

To be able to perform some actions, you might need to set the desired required permissions on the Android Manifest file. To do that, open the properties of your project and select the tab “Android Manifest”:

image

In the previous screenshot, the SEND_SMS permission is selected. So the application is free to write code that will send SMS:

SmsManager.Default.SendTextMessage("0123456789", null, "First SMS from Xamarin", null, null);

Without selected this permission, the code throws an exception (one thing I regret currently about exceptions: we don’t have a lot of information about the exact issue):

image

On the project properties, you can also look at the different options you can change like, for example, the particular platforms for which your application will be available or the API version needed to be able to run your app:

image

Some actions you’ll need perform will not need special permissions, even if you think there are needed. Indeed, let’s re-write the sample to send a SMS (don’t forget to uncheck the dedicated permission):

var phoneNumber = Android.Net.Uri.Parse("smsto:0123456789");
var smsIntent = new Intent(Intent.ActionSendto, phoneNumber);
smsIntent.PutExtra("sms_body", "First SMS from Xamarin");
StartActivity(smsIntent);

If you execute this code, you’ll note that there are no errors/exceptions:

image

But how is it possible, as we don’t select the right permission ?! In fact, this is because this sample use an Intent (Android.Content.Intent):

image

An Intent is a kind of concept that is used to say: “Hey, do the following but don’t do it automatically: use a dedicated application to do that!”. So, basically, it’s not your code that performs the action, it’s another app. An intent generally has two pieces of information associated with it; first, what the intent is (a phone call, a camera ), and second, what data does the intent need (such as a phone number) to perform the intention.

That’s why the following code, which use an Intent, does not need special permissions (although it access special information such battery data):

var filter = new IntentFilter(Intent.ActionBatteryChanged);
var battery = RegisterReceiver(null, filter);
int level = battery.GetIntExtra(BatteryManager.ExtraLevel, -1);
int scale = battery.GetIntExtra(BatteryManager.ExtraScale, -1);

var batteryLevel = Math.Floor(level * 100D / scale);

int status = battery.GetIntExtra(BatteryManager.ExtraStatus, -1);
var isCharging = status == (int)BatteryStatus.Charging || status == (int)BatteryStatus.Full;

// How are we charging?
int chargePlug = battery.GetIntExtra(BatteryManager.ExtraPlugged, -1);
var usbCharge = chargePlug == (int)BatteryPlugged.Usb;
var acCharge = chargePlug == (int)BatteryPlugged.Ac;

 

Access to the user’s contacts

To be able to access to the user’s contacts, it’s pretty easy. We’ll use the ManagedQuery API to query the contact’s properties:

var uri = ContactsContract.Contacts.ContentUri;

string[] projection = { ContactsContract.Contacts.InterfaceConsts.Id, ContactsContract.Contacts.InterfaceConsts.DisplayName, };
var cursor = ManagedQuery(uri, projection, null, null, null);

var items = new List<string>();

if (cursor.MoveToFirst())
{
    do
    {
        items.Add(cursor.GetString(cursor.GetColumnIndex(projection[1])));

    }
    while (cursor.MoveToNext());
}

The API takes in parameters the list of properties you want to retrieve. In the previous code, we load the Id and DisplayName properties and we add the last one on a list of string objects. Of course, when using the ManagedQuery object, it’s possible to filter the results:

var uri = ContactsContract.Contacts.ContentUri;

string[] projection = { ContactsContract.Contacts.InterfaceConsts.Id, ContactsContract.Contacts.InterfaceConsts.DisplayName, };
var cursor = ManagedQuery(uri, projection, null, null, null);

var items = new List<string>();

if (cursor.MoveToFirst())
{
    do
    {
        items.Add(cursor.GetString(cursor.GetColumnIndex(projection[1])));

        var userId = cursor.GetString(cursor.GetColumnIndex(projection[0]));
        var userEmailCursor = this.ManagedQuery(ContactsContract.CommonDataKinds.Email.ContentUri, null, ContactsContract.CommonDataKinds.Email.InterfaceConsts.ContactId + "=" + userId, null, null);
        if (userEmailCursor.Count > 0)
        {
            while (userEmailCursor.MoveToNext())
            {
                var userEmail = userEmailCursor.GetString(userEmailCursor.GetColumnIndex(ContactsContract.CommonDataKinds.Email.InterfaceConsts.Data));
            }
        }

    }
    while (cursor.MoveToNext());
}

Ok so now, we have a list of the contacts stored in memory but we need to find a way to display it on the screen. For that, we’ll replace the base type for the current activity by the ListActivity. This is a particular activity type that expose a ListAdapter object, which allow you to directly displays a list of items on the screen using a particular template:

ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, items);

As its name suggests, the SimpleListItem1 display the items using a simple list:

image

If you want to display the items with some Checkboxes, you have just to use SimpleListItemsSingleChoice:

ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItemSingleChoice, items);

Which displays the following:

image

So, by changing a simple property, you can change the display of your items! If you want to know which item is clicked by the user, you just have to override the OnListItemClick method (available because we are on a ListActivity):

protected override void OnListItemClick(ListView l, View v, int position, long id)
{
    var item = items[position];

    Android.Widget.Toast.MakeText(this, item, ToastLength.Short).Show();
}

 

Of course, there are a lot of other things that you can do in your applications but I hope this first overview gave you all the pointers you need to start !

Happy (Xamarin) coding!