[2/2] Storm.CrossLocalization : how to share your strings on Xamarin applications

This is the second part of the tutorial to use Storm.CrossLocalization to share your strings in Xamarin (and Windows) applications. For this second part, we will start from the project created in the previous part that you can find there [1/2] Storm.CrossLocalization : how to share your strings on Xamarin applications or if you only want the source code, it’s available on Github

If you start from the previous project, you should have an Android project named LocalizationApp.Droid and an iOS project named LocalizationApp.iOS. In this part we will see how Storm.CrossLocalization can simplify your life to access shared strings in those two projects and even in a PCL shared by the two projects.

How to access shared strings

Android

Let’s start with the Android project, in the previous part we saw that the resx file has been turned into a strings.xml file which is the android native format to handle strings as resources. This means that you can simply use any methods available with resources to access your strings. For instance using the well known form @string/ApplicationName in any of your layout. This is indeed the easiest way to do it in layout files. But if you want to use strings resources from a C# code, you gonna have to do something like below (supposing you’re in an Activity method)

this.GetString(Resource.String.ApplicationName)

This method has two drawbacks, first one is if you are not in an Activity or have easy access to a Context because the method GetString is only availble on Context class. So you need to give a Context reference to any object that require to access strings, not really good isn’t it ? The second drawback (maybe only from my point of view ?) is this code has too many characters with auto completion not working really well everytime on Resource.String class.

Now that I finish to complain on Android, I come with a proposal of solution (at least my solution). If you right click on your android project (supposing you have built it a least once and the strings.xml file has been well generated) and choose to add existing file you will notice two C# file that are not in the project, LocalizationService.Localization.cs which will be used later to share strings with a PCL project and the second one LocalizedStrings.Localization.cs which we will add to the project and use now.

Good practice: if you are using any source control system, you can add *.Localization.cs to the ignore list pattern to avoid to commit those generated file.

If you now open the LocalizedStrings.Localization.cs file, you will see that it is a static class which contains an Initialize method to give the Android Context to be able to access strings and a static property for each of the key you have in your resx file.

// a static property for each string available 
public static string ApplicationName
{
	get
	{
		return LocalizedStrings._ctx.GetString(Resource.String.ApplicationName);
	}
}

// an initialize method 
public static void Initialize(Context ctx)
{
	LocalizedStrings._ctx = ctx;
}

To use this class you simply need to call the initialize method once giving it the ApplicationContext of your Android app. This can be done in the OnCreate of your launcher Activity or if you override the Application, you can do this in the OnCreate method too (sample below). Both those methods works well even if I have a personnal preference for the second that has the advantage to work well even if later you change your first Activity or a specific Activity is started from an Intent (like from a push notification).

//Using the first Activity
[Activity(Label = "LocalizationApp.Droid", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
	protected override void OnCreate(Bundle bundle)
	{
		base.OnCreate(bundle);
		LocalizedStrings.Initialize(this.ApplicationContext);

		SetContentView (Resource.Layout.Main);
	}
}


//Using an override of the Application class 
[Application]
public class LocalizedApplication : Application
{
	public LocalizedApplication (IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer)
	{
	}

	public override void OnCreate()
	{
		base.OnCreate();
		LocalizedStrings.Initialize(this);
	}
}

After calling the Initialize method you can access to any strings from your resx file with simply accessing the corresponding property in the LocalizedStrings class.

LocalizedStrings.ApplicationName

And that’s all for Android, you can now simply access your strings from C# without a Context class and without too much verbosity.

iOS

For iOS, the same file as for Android project is generated so start by including it in your project (LocalizedStrings.Localization.cs). For iOS, you can see there is no Initialize method because we simply does not need one. In iOS, accessing strings stored in the Localizable.strings file can be done by only accessing static property from NSBundle class.

NSBundle.MainBundle.LocalizedString("ApplicationName", null);

The real issue with the method to access shared string in iOS is that you give the key as a string so you have great chance to mess up some string when you do some refactoring or change some key in the resx file. Moreover, I don’t know for you, but I can never remember how to access those strings using NSBundle. Since there is no Initialize method in the iOS version, just include the file and you are good to go.

Windows Phone

I didn’t speak so much about the Windows Phone version in the previous article because using resx file on Windows platform is really straightforward since it is the native format of the platform. (Some target could use resw file but sorry to broke the myth, it is just a rename of the extension of a resx file, it works exactly the same way, at least for strings). But for this part, the Windows Phone LocalizedStrings.Localization.cs file contains a class with an Initialize method. Indeed, in order to access shared strings on Windows Phone (or WinRT and UWP), you need access to the ResourceLoader. In general, I initialze it in the App.xaml.cs in the OnLaunched method after the creating of the rootFrame and before the navigation to the first page.

LocalizedStrings.Initialize(ResourceLoader.GetForViewIndependentUse());

And after that, it works like a charm.

Compare to iOS and Android, you maybe noticed that the LocalizedStrings class does not have a private constructor but a public one. The reason is without the public constructor, you could not use the class as a resource in App.xaml which is the only way to make it availble in xaml. Thanks to that, you can access to all shared strings directly from xaml. In order to do that, you just need to add the LocalizedStrings to the resource in App.xaml like below.

<Application x:Class="LocalizationApp.WP.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:localizationApp="using:LocalizationApp">
	<Application.Resources>
		<ResourceDictionary>
			<localizationApp:LocalizedStrings x:Key="Strings" />
		</ResourceDictionary>
	</Application.Resources>
</Application>

And then in any of your xaml file you can access strings like below

<Page x:Class="LocalizationApp.WP.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
	<Grid>
		<TextBlock Text="{Binding ApplicationName, Source={StaticResource Strings}}" />
    </Grid>
</Page>

Easy but yet useful feature

What if my designer/client/project manager (delete as appropriate) want to have some different text for each platform ?

This is a common request because of screen or font size different for each platform to have some text that will be different for each platform, and there is an easy way to do that without using a key for Android, a key for iOS and so on which will increase the number of resource available for each platform because with this method, iOS application can use the Android resource and vice-versa.
Let’s suppose you have a resource with the key PlatformText as below

<data name="PlatformText" xml:space="preserve">
  <value>You are using a smartphone</value>
</data>

but now you want to be able to say which OS your application is running on. So you will need to have a text for Android, another for iOS and another for Windows Phone. For this, you will add at the end of the key a suffix :

  • _iOS : for iOS
  • _Android : for Android
  • _WP : for Windows phone (and other windows platform)

so you will add three resource to your resx file which now looks like below

<data name="PlatformText_iOS" xml:space="preserve">
  <value>You are using a smartphone on iOS</value>
</data>
<data name="PlatformText_Android" xml:space="preserve">
  <value>You are using a smartphone on Android</value>
</data>
<data name="PlatformText_WP" xml:space="preserve">
  <value>You are using a smartphone on Windows Phone</value>
</data>

When native resource file will be generated, the suffix will be analyzed and if it do not correspond to the current platform, the string will be ignored. And when the resource file will be written, all suffix will be removed. This means you can access to this strings on any platform using the same key : PlatformText.

Using shared strings in PCL


Using Xamarin, you have two way to share code accross platforms, PCL or shared project. Since shared project are nearly like an Add as link on all file in the shared project, I will not speak about them since the can already use the LocalizedStrings class since it has the same class name and property names on all platforms.

We will create a PCL project named LocalizationApp.Core and add as link the resx file to it. (I choose to add it to a Strings directory but you can add it anywhere you want) After installing the nuget package in the PCL too and setting the build action of the resx file to LocalizationFile, you can now build your project. Normally, it should build without any problem.

Now, right click on the PCL project and choose to add existing files, you can see that on the root of the project directory, 3 files has been generated :

  • EnumStrings.Localization.cs : it is an enum which contains a value for each key in your resx file
  • ILocalizationService.Localization.cs : it is a simple interface with one method which take a value of the enum above and should return the associated string
  • LocalizedStrings.Localization.cs : a static class to access strings with property (declared as internal class to not conflict with platform class)

Add them all to the project and create an helper class with the code below. Now your project should look like the image on right.

namespace LocalizationApp.Core
{
	public static class Helper
	{
		public static ILocalizationService Localization { get; set; }
	}
}

This Helper class will be used as a dependency container for this example but if you have a real IoC/DI in your project, use it, it will be better.
In all of your platforms project, also add the LocalizationService.Localization.cs file we ignored earlier and reference the PCL project. We now have to inject in the Helper class an instance of LocalizationService for each platform.

In Android application, right after the initialization of the LocalizedStrings class

public override void OnCreate()
{
	base.OnCreate();
	LocalizedStrings.Initialize(this);
	Helper.Localization = new LocalizationService(this);
}

In iOS application, in the FinishedLaunching method of AppDelegate

public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
	Helper.Localization = new LocalizationService();
	// create a new window instance based on the screen size
	Window = new UIWindow(UIScreen.MainScreen.Bounds);

	//...

And in Windows Phone, the same as Android, right after the initialization fo the LocalizedStrings class in App.xaml.cs

LocalizedStrings.Initialize(ResourceLoader.GetForViewIndependentUse());
Helper.Localization = new LocalizationService(ResourceLoader.GetForViewIndependentUse());

Now that our service is injected, it can be accessed from the PCL using this code

Helper.Localization.Get(EnumStrings.ApplicationName)

If you want to use the LocalizedStrings in the PCL as well, you need to do some change on the helper class which then look like below

namespace LocalizationApp.Core
{
	public static class Helper
	{
		public static ILocalizationService Localization { get; set; }

		static Helper()
		{
			LocalizedStrings.Initialize(() => Localization);
		}
	}
}

and then simply access the property of LocalizedStrings class in your PCL.

Conclusion

As for the previous part, all the sample code is available on Github .
If you encounter any issue with this tool or have ideas about how to improve it, do not hesitate to reach me via github or twitter.

Reach me on twitter @Storm0x2A
Storm.CrossLocalization on Github
Storm.CrossLocalization as

Creative Commons License

[1/2] Storm.CrossLocalization : how to share your strings on Xamarin applications

First post of this new year, it concerns a simple tool I created for work. We are creating mobile applications with Xamarin (Android, iOS, Windows Phone) and a usual problem is how to share strings accross all applications in the native way. Android have a strings.xml file, iOS need a Localizable.strings file and Windows Phone need a Resources.resw file. With all of this differents targets and formats, it’s not easy to have a simple solution to use on all platforms.

Here comes Storm.CrossLocalization. Source code is available on Github and a is available to be used in your projects. For nuget use this line to install via the Package Manager Console.

Install-Package Storm.CrossLocalization

Ok good, I can install your project but why and how should I use it ?

Really good question, if you installed it with the nuget package, you can see that there is no reference added to your project, that is because it is not a library, it will simply add a new target for msbuild (or xbuild if you are using it on OS X). This target has for goal to transform resx or resw file to native platform file format.

Let’s use a quick sample to understand how to make it work.

Step by step setup

All screenshots are made on Visual Studio but you can use Xamarin Studio too.

Start by creating a new solution with an Android Blank Application and an iOS Blank Application which will be respectively named LocalizationApp.Droid and LocalizationApp.iOS after that, you should have your solution explorer looks like the screenshot on right. (Explanation for Windows Phone is available at the end of the article since it’s really more straightforward to be used with Windows Phone)

You can see that for Android, localization file is already in the project (strings.xml in Resources/values). If you open this file, you’ll see that the default project template created two strings with keys Hello and ApplicationName. If your file (like mine) is named Strings.xml (with an uppercase S), rename it in lower case (strings.xml).

For iOS, the default template doesn’t come with localization file, so we need to add a few things. First, the localization files will be stored under the Resources/xx.lproj directory where xx must be replaced by the two letter iso code of the language you want to support. For this sample, we will use en.lproj. So create this directory Resources/en.lproj.

Now that we are ready to write translations, we can add a resx file, to be able to find translations file easily, we will first add a solution folder named Strings and then create a resx file named en.resx in this folder. To create this file, you will probably need to create it in one of your project and then move it since neither Visual Studio or Xamarin Studio will propose you the option to create a resx file in a Solution folder.

Resx file are available in Visual Studio in C#/General/Resources file and in Xamarin Studio in Misc/Resources file. If you are using Visual Studio, the resx file should open in a nice key/value editor. But if you are using Xamarin Studio, it should open as a simple xml file, that’s good, resx file are indeed simple xml file and can be edited as is without any problem.

We will now add one translation to the resx file, we will call it ApplicationName and you can give the value you want. For me, it will be Blog localization sample. For Xamarin Studio users, you have to add this xml snippets at the end of the file (before the end tag </root>).

<data name="ApplicationName" xml:space="preserve">
  <value>Blog localization sample</value>
</data>

The value of the name attribute is the key of your string and the associated value is between <value> and </value>.

You can now add the Storm.CrossLocalization nuget package to the two projects. Then, you can add your resx file as a link to Resources/values in your android project and to Resources/en.lproj in your ios project. And then set the build action as LocalizationFile. When using Visual Studio take care that the CustomTool field is empty.

Now, build both of your project, if build is successful the strings.xml file for Android has been updated with the content from your resx file. In the ios project, a Localizable.strings file has been generated in Resources/en.lproj but you need to add it to your project.

And that’s all, your projects are setup to share translations between your applications.
The sample project created with this tutorial is available on Github

Other platforms

If you also want to share your translations for Windows Phone, WinRT or UWP, you can just add the resx file with the same build action as the others in directory Strings/en. Just take care of not naming your resx/resw file Resources.resw, it will be the file generated by the localization task and the one you need to add to your project.

Next upcoming post for advanced features like using strings in PCL.

Creative Commons License

Part 1: Storm.Mvvm, a new Mvvm framework for Xamarin

What is Storm.Mvvm?

Storm.Mvvm is (another) Mvvm framework to use with Xamarin. But compared to other framework like MvvmLight or MvvmCross, you have a really good support of Binding and all related things (like converter, resources …) in it.

Today full support is only available on Xamarin.Android, and most of the things are available on Windows 8. Implementation for Windows Phone 8 is a work in progress and support for Xamarin.iOS will be available as soon as I find an easy way to use binding with it.

The framework is available as multiple nuget packages:

  • Storm.Mvvm is the portable implementation (use it in your PCL projects)
  • Storm.Mvvm.Android is the android implementation (use it in your Xamarin.Android projects)
  • Storm.Mvvm.Android.Support is the same as the android implementation but came with Support Library v4 to be able to use features like Fragment on Android 1.6 and further.
  • Storm.Mvvm.Tablet is the Windows 8 implementation. (Only partial for now)

More to come: I planned to release the phone version and the iOS version the same way. Also an Android package with support for things like RecyclerView or CardView which came in Support Library v7 is in preparation and will be available soon.

The Android version is today the most complete and up-to-date because of a project I’m working on which use this framework. The project is open source and you can check it on github.com/Julien-Mialon/IndiaRose to see some samples of how to use this framework. Since only the Android support is complete, I’m going to use a sample with Android.

How to design an Mvvm Android application with Storm.Mvvm

Now, let’s deep into code. First of all, suppose we create an android application (name it MyApplication.Android) and then create a PCL project to store our ViewModels (name it MyApplication.Portable). Next we need to import the correct nuget packages in both projects. (Storm.Mvvm for both and Storm.Mvvm.Android or support version in the android project) The core package has a dependencies to Funq for dependency injection so this package will be imported too.

In this sample, we want to create a small app with:

  • A button with the text “you’ve clicked X times on this button” where X will be the number of clicks,
  • An input text where the user can enter its name,
  • A label where the text will be “Hello X!” where X will be the content of the input text.

ViewModel implementation

We are going to create our first ViewModel in the PCL project (Let’s call it HomeViewModel.cs). You have to make this ViewModel extend Storm.Mvvm.ViewModelBase which provide implementation for INotifyPropertyChanged (to update the view) and take care of navigation things. In order to implement our sample, we need in our ViewModel:

  • A Command to react on button click (ButtonCommand)
  • A string for the button text (ButtonText)
  • A string for the input text (Name)
  • A string for the label (Greetings)

To update the view when a property change, we need to use the SetProperty method to affect its value (or you can raise the PropertyChanged event manually). A simple implementation for commands is provided with the framework: DelegateCommand (or DelegateCommand if you need to pass a parameter to the command).

The ViewModel code is available just below and shouldn’t be strange for anyone who already used Mvvm.

using System.Windows.Input;
using Storm.Mvvm;
using Storm.Mvvm.Commands;

public class HomeViewModel: ViewModelBase
{
	private string _buttonText;
	private string _name;
	private string _greetings;
	
	private int _clickCounter = 0;
	
	public string ButtonText
	{
		get { return _buttonText; }
		set { SetProperty(ref _buttonText, value); }
	}
	
	public string Name
	{
		get { return _name; }
		set 
		{ 
			if(SetProperty(ref _name, value))
			{
				// if the input changed, we need to update the associated label
				Greetings = string.Format("Hello {0}!", value ?? "");
			}
		}
	}
	
	public string Greetings
	{
		get { return _greetings; }
		set { SetProperty(ref _greetings, value); }
	}
	
	// Since it will only be affected once, we do not need to raise the PropertyChanged event there
	public ICommand ButtonCommand { get; private set; }
	
	public HomeViewModel()
	{
		ButtonCommand = new DelegateCommand(ButtonClicked);
		Greetings = "Hello !";
		
		// initialize button text
		ButtonClicked();
	}
	
	private void ButtonClicked()
	{
		ButtonText = string.Format("You've clicked {0} times on this button", _clickCounter++);
	}
}

You can check that your portable project build without error at this point.

Android project configuration for Mvvm

For the android project, we need to adjust some configuration in order to initialize our framework correctly. First of all, remove everything in Resources/layout (do not remove the folder!) then, at the root of your project, create a MyMvvmApplication.cs file and put this code in it:

using System;
using Android.App;
using Android.Runtime;
using Storm.Mvvm;
using Storm.Mvvm.Inject;

[Application]
public class MyMvvmApplication : ApplicationBase
{
	public MyMvvmApplication(IntPtr handle, JniHandleOwnership transfer) : base(handle,transfer)
	{
	}
	
	public override void OnCreate()
	{
		base.OnCreate();
		AndroidContainer.CreateInstance<AndroidContainer>(this, null);
	}
}

The last line of the OnCreate method is used to initialize some default services (like Navigation, Logging …) we will use it in a next post. You can also add any initialization code you need in the OnCreate function.

The Android view

Next we will create the HomeActivity and the HomeView, for that, create the file HomeActivity.cs and HomeView.xml at the root of the project. The HomeActivity has to inherit ActivityBase and be a partial class. In this class, we will just link the View and the ViewModel with the Activity.

using Android.App;
using Android.OS;
using Storm.Mvvm;
using MyApplication.Portable;

[Activity(Label = "HomeActivity", MainLauncher = true, Icon = "@drawable/icon")]
public partial class HomeActivity : ActivityBase
{
	protected override void OnCreate(Bundle bundle)
	{
		base.OnCreate(bundle);

		// Set our view from the home file in layout
		SetContentView(Resource.Layout.Home);
		// Set our view model
		SetViewModel(new HomeViewModel());
	}
}

The SetContentView function come from Android, just be careful with the name of the view you give, you need to remember it. And the SetViewModel function associate your ViewModel with your View. Patterns like Locator to retrieve the ViewModel could be used but in our sample, we just create it with a new to simplify.

Now for the view file, you can change its build action to “None” to avoid the build process to add it to your final apk. And in this file, you can write your normal android view, with a little bit of binding to use property provided by our ViewModel.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
			  android:orientation="vertical"
			  android:layout_width="match_parent"
			  android:layout_height="match_parent">
	<Button android:layout_width="match_parent"
			android:layout_height="wrap_content"
			Click="{Binding ButtonCommand}"
			Text="{Binding ButtonText}"
			/>
	
	<EditText android:layout_width="match_parent"
			  android:layout_height="60dp"
			  Text="{Binding Name, Mode=TwoWay, UpdateEvent=TextChanged}"
			  />
			  
	<TextView android:layout_width="match_parent"
			  android:layout_height="wrap_content"
			  Text="{Binding Greetings}"
			  />
</LinearLayout>

In this view file, you can see some binding expression, if you are comfortable with Mvvm, I’m sure you already used something like that. For the others, {Binding PropertyName} link the content of the property of the view model with name “PropertyName” to the current xml property. For instance with our TextView, Text=”{Binding Greetings}” will update the Text property of the TextView every time the Greetings property in our ViewModel is updated. You can see you do not need the “android:” prefix for attribute using binding cause they will be translated to C# code. For the same reason, attributes name are case insensitive.

Since Android doesn’t natively support command and only event, if you bind a command to an event a proxy will handle the call to your command transparently. (CommandParameter are supported but will be introduced in another post)

For basic binding, everything looks exactly like binding with WPF or Windows 8/Phone, The difference come with TwoWay binding. TwoWay binding allow the view to update the property of the ViewModel (which could be really useful in case of EditText) whereas the “standard” mode (OneWay) only update from the ViewModel to the View.
To make TwoWay binding works, we need to know the event raised when the property of the view is updated, that’s why, you must provide an UpdateEvent. This UpdateEvent must be an event available in the control class you are binding to.

To be able to run this sample, you only need one last things, specify links between view file and activity. Since the Binding engine will preprocess your view file to generate:

  • A valid android layout file (without bindings expressions),
  • C# code to handle all of your bindings (that’s why your activity is marked partial).

He needs to associate one view with its activity. This information needs to be provided in a json file. A sample file (ActivityDescription.json) should have been added to your Android project with the nuget package. This file is just a sample to explain all available configurations.

We are going to create a new file: MyApplication.json and set its build action to “BindingProcess” (If the build action is not available in the list, unload and reload your project and it should be available. If it’s still not available, edit the .csproj file to change the build action manually). Only two things are required in this file, the root namespace of your Android application in “namespaces” and the link between your views and your activity in the “fileDescriptions” field. So you json file should look like:

{
    "namespaces": [ "MyApplication.Android" ],
    "fileDescriptions": [
        {
            "activity": {
                "namespaceName": "MyApplication.Android",
                "className": "HomeActivity"
            },
            "view": {
                "inputFile": "HomeView.xml",
                "outputFile": "Home.axml"
            }
        }
	]
}

You need to take care of two things, that your activity namespace/class name are right and that your view output file match the name you put in the SetContentView function in your Activity. To specify the view input file, you need to give the path relative to the json file.

Now, you should be able to run your application and see the magic of Mvvm with Android.
To summarize what we’ve done so far:

  • Create a PCL project for your ViewModels,
  • Create an Android application project for your Views,
  • Add nuget Storm.Mvvm to both projects,
  • Add nuget Storm.Mvvm.Android to the Android application project,
  • Code your ViewModel in PCL,
  • Create an Application to initialize framework in Android project,
  • Create an Activity and a View in Android project,
  • Create a json file to describe links between Activities and Views in Android project,
  • Run and enjoy your apps ūüėČ

More posts to come about other feature of the framework like advanced binding, styles, IoC…

Link to the project on github : github.com/Julien-Mialon/StormXamarin
A documentation is also available on github project wiki : github.com/Julien-Mialon/StormXamarin/wiki

Présentation de Xamarin @OrléansTechTalks

Xamarin logo

Mercredi 29/04/2015, je faisais une pr√©sentation de Xamarin √† Orl√©ans Tech Talks. Le but, pr√©senter les possibilit√©s qu’offre Xamarin pour du d√©veloppement mobile multi-plateforme (que ce soit avec ou sans Xamarin.Forms). Avec un public d’une trentaine de personnes, certaines se sont r√©v√©l√©es tr√®s int√©ress√©es par Xamarin et pourrait s’y mettre suite √† cette pr√©sentation.

Les exemples de code utilisé lors de la démo sont sur mon github : https://github.com/Julien-Mialon/XamarinTalk

Les slides sont disponible ici : OrleansTechTalks.pptx sous Licence Creative Commons Attribution РPartage dans les Mêmes Conditions 4.0 International.
Licence Creative Commons

Cours introduction à Xamarin

Depuis Janvier, j’ai eu l’occasion de donner un cours d’introduction √† Xamarin √† l’universit√© d’Orl√©ans pour les 2√®me ann√©e de master sp√©cialis√© dans le d√©veloppement mobile. Cette (courte) introduction de 10h m’a oblig√© √† partir sur un enseignement de Xamarin.Forms qui semblait plus simple dans un temps si court surtout sachant que les √©l√®ves ne connaissait pas le C#. J’ai donc pu faire une rapide introduction √† C# en prime en basant plut√īt le cours sur les diff√©rences entre Java (qu’ils connaissent bien) et C#.

Le reste du cours fut consacr√© √† Xamarin.Forms. Le temps assez court dont on disposait √† tout de m√™me permis de voir la plupart des choses “communes”, que ce soit le d√©veloppement avec Mvvm, des composants graphique complexe tel que la ListView ou l’impl√©mentation de Service par plateforme. Seul regret, de ne pas avoir eu le temps d’explorer la personnalisation des composants graphique pour chaque plateformes.

Afin de simplifiez une partie de la mise en place du cours, un petit framework Mvvm leur était mis à disposition sur NuGet : Storm.Mvvm.Forms (https://www.nuget.org/packages/Storm.Mvvm.Forms/)

Ce module fut √©valu√© avec un projet, n√©anmoins, vu qu’il √©tait doubl√© avec un cours de d√©veloppement iOS, seul certains √©l√®ves ont choisi de rendre leur projet en Xamarin plut√īt qu’en iOS. Je r√©cup√®re donc √† la fin, 5 projets, je ne discuterais ci-dessous que de deux d’entre eux qui m’ont sembl√© int√©ressant.

Je n’ai jamais

Le premier projet fut de faire une application sur le principe du jeu “Je n’ai jamais…”, l’id√©e de ce jeu est la suivante : dans une partie √† X joueurs, le jeu choisi al√©atoirement un joueur et lui affecte un “Je n’ai jamais…” que celui-ci doit lire √† haute voix et dire si il l’a d√©j√† fait ou non. Ensuite, les autres joueurs doivent r√©pondre √† cette question. √Ä l’origine un jeu √† boire, celui-ci peut facilement √™tre d√©clin√© et permet d’en apprendre un peu plus sur ses amis.

En plus de permettre le principe de base du jeu, l’application permet de prendre des photos de la partie ainsi que de conserver un historique de la partie afin de pouvoir la revoir. Elle permet √©galement d’enregistrer des statistiques de r√©ponses pour chaque question. (On pourrait peut √™tre s’en servir pour des √©tudes marketing…)

Le design de l’application est plut√īt simpliste mais l’application reste ergonomique est assez intuitives. Seul b√©mol, l’application n’a √©t√© faite que pour Android m√™me si quasiment la totalit√© du code est portable et permettrait d’adapter l’application pour une autre plateforme assez rapidement et facilement.

Le code de l’application est disponible ici pour les personnes int√©ress√©es : JeNaiJamais.zip

Gestion d’une collection de jeux vid√©o

Ce second sujet de projet fut choisi par plusieurs √©tudiants malheureusement la plupart avait une exp√©rience ergonomique absolution d√©sastreuse. Celui que je pr√©sente ici est pour moi le plus aboutis. Le but de ce projet √©tait de permettre de stocker sa collection de jeux vid√©o dans son t√©l√©phone. Assez simpliste, l’application demandait toutefois de pouvoir prendre des photos des bo√ģtes dont on dispose et de g√©rer toute une collection √† travers une base de donn√©es ou un simple fichier JSON (solution utilis√© dans le projet pr√©sent√©).

Le code de l’application est disponible ici pour les personnes int√©ress√©es : VideoGameManager.zip

 

En bref, dans le peu de temps disponible que ce soit pour le cours et pour les √©tudiants, le temps de faire les projets, nous avons pu avoir des projets tout de m√™me assez aboutis ce qui me conforte dans le choix de l’enseignement de Xamarin.Forms. Les diff√©rents slides de cours sont disponible ci-dessous.

Cours 04 – C#.pptx
Cours 05 – MVVM & Xamarin.Forms.pptx
Cours 06 РXamarin avancé.pptx

Découverte de Xamarin.Forms

Xamagon Je me suis r√©cemment lanc√© dans le d√©veloppement d’application mobile cross-platform avec Xamarin (India Rose). Pour cette premi√®re application, nous avions fait le choix de ne pas prendre la solution Xamarin.Forms du fait de sa jeunesse et des diff√©rentes sp√©cificit√©s de l’application. N√©anmoins, j’ai voulu voir ce que permettait cette solution. Je vous livre ici le retour d’exp√©rience que j’ai pu avoir durant ma premi√®re exp√©rience avec Xamarin.Forms.

Pour rappel, Xamarin.Forms est le nouveau framework d√©velopp√© par Xamarin vous permettant outre de partager tout le code business de votre application, de partager aussi toute la partie UI. N’est ce pas merveilleux, un seul code pour trois plateformes !

Pour me lancer, j’ai d√©cid√© de r√©adapter l’application XamarinStore, permettant de commander un T-Shirt sur la boutique Xamarin (https://xamarin.com/c-sharp-shirt), en utilisant Xamarin.Forms. Le r√©sultat est disponible sur GitHub : https://github.com/Julien-Mialon/XamarinStore.Forms et est fonctionnel.

Toutefois, l’interface est loin d’√™tre aussi abouti que celle pr√©sente dans l’application d’origine. Toutes les animations ne sont par exemple pas impl√©ment√© et certains design ont √©t√© refais un peu √† la va vite. Toutefois, l’application permet la m√™me chose que l’ancienne.

Durant le d√©veloppement de cette application, j’ai tout de m√™me rencontr√© quelques probl√®mes, notamment pour essayer de partager le plus de code possible. L’exemple que je prendrais est celui des images que l’ont est sens√© pouvoir utiliser tr√®s simplement (juste en mettant le nom de l’image + son extension) mais qui implique de mettre les images dans les 3 projets (WindowsPhone, iOS et Android) √† des endroits sp√©cifique pour chacune des plateformes. Il s’est av√©r√© que pour WindowsPhone & Android, aucun probl√®me mais impossible d’afficher des images sous iOS avec cette m√©thode ūüôĀ La seule solution que j’ai pu trouv√© fut de mettre les images en tant que “EmbeddedResource” dans le projet portable (PCL) et de les charger depuis les ressources de ce projet.

Un autre probl√®me majeur rencontr√©, c’est la possibilit√© d’avoir des lignes de taille variable (ou tout du moins non connu √† la compilation) dans une ListView. Aucun probl√®me pour Windows Phone & Android, par contre sous iOS, ce n’est pas possible. Seul choix possible sp√©cifier une hauteur en “dur” pour iOS. Pas forc√©ment pratique mais on esp√®re que √ßa s’am√©liorera avec le temps.

Pour conclure, Xamarin.Forms est quelque chose que je garderais √† l’oeil et qui a un tr√®s bon avenir devant lui si les quelques probl√®mes que j’ai rencontr√© peuvent √™tre r√©gl√© dans une prochaine version.