Udostępnij za pośrednictwem


Xamarin Tips and Tricks

Xamarin Tips and Tricks

In this blog post I’ll cover some of the basics of getting started with Xamarin along with some more advanced features. I’ll also cover common problems that you will doubtless encounter when developing with Xamarin.

Installing Xamarin

The Xamarin install is now included in Visual Studio 2015 (VS), so make sure you select it when installing VS. If you already have VS, then you can just download Xamarin from Xamarin.com and install it over the top. Try building an empty project and running it to check your install. On the MAC install from Xamarin.com and install Xamarin Studio and both the Android and iOS development environments. Don’t think you will not need to build Android on the MAC, sometimes you do.

Connecting to the MAC

One of the biggest hassles of doing iOS development is the need for a MAC to do development. The connection to the MAC is unreliable and sometimes doesn’t connect, even though it has connected before. Try removing your connection and adding it as an IP address (192.168.1.206). Also make sure you are using your short username (ptallett, not Paul Tallett) for the MAC. If you are still having troubles try restarting VS and rebooting both machines. Download an SSH client and check you can SSH from your Windows machine to the MAC (Xamarin uses an SSH connection). Also make sure you have compatible Xamarin versions on both machines. If you update Xamarin on Windows you will probably need to update the MAC before it will connect. There’s a troubleshooting guide here https://developer.xamarin.com/guides/ios/getting_started/installation/windows/connecting-to-mac/troubleshooting/

Remote Simulator

You probably want VNC to remote into your MAC from Windows, but a neat addon for VS is the remoting tool for the iOS simulator. It remotes the UI for the simulator onto your Windows machine so you don’t have to deal with OSX so much.

https://developer.xamarin.com/guides/cross-platform/windows/ios-simulator/

If it hangs when you first start it checking for updates, just kill it and run your project again. It should be fine then. I find this a really helpful tool.

Xamarin Versions

Its always worth going with the latest versions of everything, usually including NuGet packages as the general quality of the available code is somewhat buggy. Even pre-release can often help you. Upgrading Xamarin versions is somewhat painful so don’t fix it unless its broke, but be aware that you should always try to be on the latest versions when you have some breathing space.

NuGet is your friend

The NuGet integration in Visual Studio is really nice and is the preferred way to incorporate other libraries in your code. Visual Studio Source Control tends to add the contents of the packages folder into your repository, but you don’t really need it.

Xamarin Studio

Xamarin Studio on the MAC uses the same project file structure as VS and on occasion you may need to build your project on the MAC (see Native Code later).

Choice of frameworks

We use the PRISM navigation framework on our projects and it seems to work very well.

SkiaSharp is a Xamarin produced wrapper for the Google Skia graphics library and worked well for us.

HockeyApp has telemetry and app distribution which has been good for us.

NewtonSoft JSON is one of the most downloaded NuGet packages.

Xamarin Forms or Xamarin Native

Xamarin Forms has come a long way in the past 12 months and can now be used for quite complex projects. It is said that you need to go native if you have a lot of animations to do, but we found with SkiaSharp we were able to create quite complex cross-platform animations.

PCL or Shared Library

When you create your project you get the choice of a PCL (Portable Class Library) or Shared Library for your no-platform specific code. PCL is the older variant and if you have had experience of PCL’s on Windows, you may think they are quite restrictive and go for Shared Libraries. However, PCL is the way to go as they are not that restrictive (they have the full Mono .NET APIs), all the examples and code on the web seems to be PCL, and with Shared Libraries you can’t add references.

Platform Specific code

For platform specific code, create interfaces in your PCL and implement those interfaces in each of your platform specific projects. We used the Xamarin Forms dependency injection which worked well for us, so in the PCL you would write

DependencyService.Get<IAudioEffects>().PlaySoundOverBluetooth("HurryUpSound.wav");

Peculiar build problems

Often you may get compiler errors or linking/runtime errors which don’t make sense. That’s probably because they don’t. Exit out of VS, delete all your obj and bin folders, delete your packages folder and then do a Rebuild All.

MVVM

MVVM seems to be a popular pattern and is supported by Xamarin Forms with data binding and Command properties. Use the PRISM ViewModelLocator to wire up your View Models automatically in markup.

Displaying an image

Although this sounds like a trivial task, there are many different aspects regarding image display. Actually we realised during one project, that displaying images at all is actually a bad idea, and we switched over to using all SVG (Scalable Vector Graphics) images. These are much smaller, don’t require multiple resolutions as they scale, and are much crisper on high definition devices. To draw SVG images, we used SkiaSharp. We will cover displaying SVG images in another post, but if you really want to display PNG images, here’s some tips.

If you are developing for iOS and Android, you need to put copies of the images at different resolutions in both the iOS and Android projects, not your shared PCL. Android has some really fast methods for drawing images, but they only work on AndroidResources not stuff in your PCL. The paths to your images is different on both Android and iOS so we wrote a helper class to do the mappings (IMarkupExtension).

On Android, the Resources folder has subfolders called drawable, drawable-hdpi, drawable-xhdpi etc). You need to put your images in those folders (as AndroidResource’s) and create larger resolution images for the higher density displays. See https://developer.android.com/guide/topics/resources/providing-resources.html

On iOS, the Resources folder contains the images (as BundleResources) at different resolutions directly, eg icon.png, icon@2x.png, icon@3x.png. Note that the scale factors for iOS are different to Android.

Don’t try and put a subfolder structure into your Resources folders. They are largely ignored and just confuse developers.

If you are trying to get the path to your resources, temporarily call the LIST methods to list the resources so you can see where they are and what the path is to the resources.

Generally using images uses up a lot of memory and really should be avoided.

Xamarin Forms

If you are familiar with XAML on Windows, you will find Xamarin Forms quite limited, but there is enough to get by.

Windows XAML                                                 Xamarin Forms

TextBlock                                                            Label
TextBox                                                               Entry
Grid                                                                     Grid
StackPanel                                                          StackLayout
ProgressRing                                                      ActivityIndicator
CheckBox                                                            No equivalent
Image                                                                  Image
Tapped event                                                      GestureRecognizer
SplitView                                                             MasterDetail page
ComboBox                                                          Picker (there’s a BindablePicker on the web)
Ellipse, Rectangle etc                                          No equivalent (use SVG or custom renderers)

 

To use App.xaml see https://blogs.msdn.microsoft.com/devfish/2016/06/24/global-resources-in-xamarin-forms-no-app-xaml-create-one/

Be careful with App.xaml though, creating a lot of global Styles can use up a lot of memory. Might be better to create your Styles in code.

Native Code

Calling native code (Java/Objective-C) is possible in Xamarin but I’ve found it quite tricky. Here’s some pointers:

https://blogs.msdn.microsoft.com/vcblog/2015/02/23/developing-xamarin-android-native-applications/ https://jonathanpeppers.com/Blog/xamarin-ios-under-the-hood-calling-objective-c-from-csharp

Note you can't build a native binding for iOS native code from Visual Studio, you have to do it in Xamarin Studio.

https://forums.xamarin.com/discussion/comment/5371#Comment_5371

Setting your application badge

iOS supports badges on your app icon natively, Android does not but most vendors have added this functionality in their extensions.

The Xam.Plugin.Badge NuGet package handles all this, but you need to make sure you have the permissions in your Android manifest:

<!-- For Android -->

<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
<!--for Samsung-->
<uses-permission android:name="com.sec.android.provider.badge.permission.READ" />
<uses-permission android:name="com.sec.android.provider.badge.permission.WRITE" />
<!--for htc-->
<uses-permission android:name="com.htc.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.htc.launcher.permission.UPDATE_SHORTCUT" />
<!--for sony-->
<uses-permission android:name="com.sonyericsson.home.permission.BROADCAST_BADGE" />
<uses-permission android:name="com.sonymobile.home.permission.PROVIDER_INSERT_BADGE" />
<!--for apex-->
<uses-permission android:name="com.anddoes.launcher.permission.UPDATE_COUNT" />
<!--for solid-->
<uses-permission android:name="com.majeur.launcher.permission.UPDATE_BADGE" />
<!--for huawei-->
<uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE" />
<uses-permission android:name="com.huawei.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.huawei.android.launcher.permission.WRITE_SETTINGS" />
<!--for ZUK-->
<uses-permission android:name="android.permission.READ_APP_BADGE" />
<!--for OPPO-->
<uses-permission android:name="com.oppo.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.oppo.launcher.permission.WRITE_SETTINGS" />

Or request badge permissions on iOS

var settings = UIUserNotificationSettings.GetSettingsForTypes(UIUserNotificationType.Badge, new NSSet());

UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);

Internationalisation

If you want to build apps that support multiple spoken languages (eg English, German, French) then the Multilingual App Toolkit supports Xamarin projects now and is brilliant for managing all the resource strings.

How do I bind to a command in a ListView

In a ListView ItemTemplate, your BindingContext is your data item, but you probably want gestures that bind to your ViewModel. You can use x:Static to reference your View, then BindingContext to get to your ViewModel:

<ListView x:Name="CaptureListView" ItemsSource="{Binding Captures}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<!-- Red grid for Delete command -->
<Grid x:Name="BackGrid" BackgroundColor="Red">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.DeleteCaptureCommand, Source={x:Reference HomePage}}" CommandParameter="{Binding}" />
</Grid.GestureRecognizers>

 

Navigation

Avoid creating loops in your navigation scheme which constantly push new copies of your View and ViewModel onto the back stack. Your users will very quickly run out of memory. Consider using back navigation to get back to the previous page rather than navigating to a new instance.

Custom Fonts

Xamarin now supports custom fonts out of the box, but the ways to invoke it are different on iOS and Android. Consider using

<OnPlatform x:Key="FontVWTextWebBold" x:TypeArguments="x:String" iOS="VWTextWeb" Android="Fonts/VWTextWeb-Bold.ttf#VWTextWeb"/>

Then set the FontFamily property.

 

 

I hope this helps you! Happy developing!

Paul Tallett, App Dev Architect, UX Global Practice, Microsoft, February 2017

Disclaimer: The information on this site is provided “AS IS” with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use.