Corrado's Blog 2.0

Online thoughts of a technology funatic

Xamarin Forms preview with Gorilla Player

One of the major complaints about Xamarin Forms is the lack of designer with relative preview so, at the time of this writing, the development process is made up of a continuous sequence of: write XAML, deploy, see result, stop, edit XAML and try again, not a very convenient and productive way to work Sad smile

GorillaPlayer is a tool from a company named UXDivers that provides real time XAML preview on any Emulator/Simulator speeding up development process.

Note: GorillaPlayer is actually in beta and available via invite only, go request your invite here: www.gorillaplayer.com the player is available for both Visual Studio and Xamarin Studio (both Windows and iOS)

Once you get the invite, download the installer for your platform, enter the invitation code and let the installer complete installation, I encourage you to select the “Install Player + SDK + Samples” option since it contains a fundamental component (a.k.a. The Player)

image
If everything goes well, you should now have a new element in your tray area (on Windows Platform)

image

Right clicking the icon you’ll see all Gorilla Player’s options, I suggest you to have a look at Getting Started Walkthrough

image:

In order to see your XAML output you must install the Gorilla Player App in target emulator/simulator (in alternative using included Gorilla Player’s SDK, the player can be integrated directly in your app, see SDK page for more details) the player will try to connect with the host running on your machine

image

and once connection is completed (you have both automatic and manual setup options)  you’ll see the monkey smiling and ready to render your XAML

image

Let’s see some XAML then!

While the player app is running, create a brand new Xamarin Forms app (or open an existing one…) and open/add a XAML page, you should see the preview live on the emulator/simulator, if not check Gorilla Player’s option under: Tools->Gorilla Player (in Visual Studio) if not connected select the Connect option and check Follow me option

image

Note: using Stick to this XAML will let you freeze the rendered XAML while working on another file.

If Gorilla can’t render your XAML you’ll see an error message like this:

image

Otherwise you’ll get the final output, here’s a demo XAML fragment:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="GorillaTest.Views.MyView"> <ContentPage.Resources> <ResourceDictionary> <Style x:Key="MyLabelStyle" TargetType="Label"> <Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="VerticalOptions" Value="CenterAndExpand" /> <Setter Property="FontSize" Value="20" /> </Style> </ResourceDictionary> </ContentPage.Resources> <StackLayout BackgroundColor="Teal"> <Image Source="icon.png" WidthRequest="100" HeightRequest="100" /> <Label Text="Gorilla Player Rocks!" Style="{StaticResource MyLabelStyle}" TextColor="White" /> </StackLayout> </ContentPage>

image

As you see the Player supports every XAML element including Images, Styles, Resources, etc it also support ContentViews (see here)

But what about design time data? : If you have a ListView I presume you want to see how it renders at runtime right? luckily Gorilla Player has a great support for design time data too, with several options (see here) probably the quickest one is to use add a json file with sample data to your project.

Let’s take this XAML as example (taken from Gorilla’s demo MyCoolCompanyApp)

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MyCoolCompanyApp.MyPeople" xmlns:common="clr-namespace:UXDivers.Artina.Player;assembly=UXDivers.Artina.Player.Common" BackgroundColor="#455a64" xmlns:local="clr-namespace:MyCoolCompanyApp;assembly=MyCoolCompanyApp"> <ContentPage.Content> <Grid> <Image Opacity="0.5" x:Name="img" Source="bridge_bg.png" Scale="1.5" Aspect="AspectFill"/> <StackLayout Padding="10,30,20,0"> <ListView ItemsSource="{Binding .}" SeparatorVisibility="None" BackgroundColor="Transparent" SeparatorColor="#DFDFDF" HasUnevenRows="false" RowHeight="120"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <local:MyPeopleTemplate /> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </Grid> </ContentPage.Content> </ContentPage>

The output rendered by Gorilla Player is:

image

Awesome! but since we are at design time, were do the ListView data come from? If you look at PCL project you’ll see that it includes a SampleData.json file

image

with this content:

{ "MyPeopleTemplate.xaml": { "Name": "John Silverstain", "City": "MELBOURNE", "Department": "Marketing", "Color": "Red", "Age": 29, "Followers": 243, "Photo": "friend_thumbnail_27.jpg" }, "MyPeople.xaml": [ { "Name": "John Silverstain", "City": "MELBOURNE", "Department":"Marketing", "Color":"Red", "Age":29, "Followers":243, "Photo":"friend_thumbnail_27.jpg" }, { "Name": "Pam Tailor", "City": "SIDNEY", "Department":"Design", "Age":32, "Followers":24, "Photo":"friend_thumbnail_75.jpg" }, { "Name": "Casy Niman", "City": "HOBART", "Department":"Accounts", "Age":58, "Followers":267, "Photo":"friend_thumbnail_93.jpg" }, { "Name": "Gorge Tach", "City": "NEWCASTLE", "Department":"Design", "Age":29, "Followers":127, "Photo":"friend_thumbnail_55.jpg" }, { "Name": "Cristina Maciel", "City": "HOBART", "Department":"Mobile Dev.", "Age":32, "Followers":80, "Photo":"friend_thumbnail_31.jpg" }, { "Name": "Simon Deuva", "City": "MELBOURNE", "Department":"Media", "Age":58, "Followers":420, "Photo":"friend_thumbnail_34.jpg" } ] }

As you see, the file contains a set of sample data, in json format, that will be associated to each page (MyPeopleTemplate.xaml and MyPeople.xaml in this case) ideally simulating the same data that the associated ViewModel will provide at runtime. in the docs you’ll find alternative design time solutions like using a Json data class or a Plain object.

While in beta, the product is already very stable and a total life saver if you do Xamarin Forms development so I encourage you to give it a try and help the team fixing all issues so that we can get an official v 1.0 soon.

Issues can be filed here.

Happy Gorilla rendering! Smile

Adding a splash screen to Xamarin Forms apps

Every Xamarin Forms app should ship with a splash screen, it is the first thing a user see and it contributes to reduce the perceived application boot time.

Adding one is quite easy, let’s go from simpler to harder.

The simpler: Windows Phone

Just replace SplashScreenImage.jpg (720×1280 pixels) with your own app launch image in the Windows Phone project and you’re done.

image

The harder: iOS

If you follow iOS documentation you’ll know that adding your own launch screen is just a matter of adding the proper images to the project via info.pList options.

image

unfortunately once you do that you’ll still see the blue background with Xamarin Logo at startup, to fix it delete the content of Launch Storyboard option into info.pList and you’re done (no idea why template adds that storyboard inside Resources folder)

image

The hardest: Android

Adding a splash screen requires following steps:

image

1-Add the splash screen image into Resources\drawable folder (and all the variants you want to support) in previous screenshot file is named splash.png

2-Create a new folder under Resources and name it values

3-Add an xml file into values folder (name is not important, in my case I named it Styles.xml)

4-Add this content to xml file

<?xml version="1.0" encoding="utf-8" ?>
<resources>
    <style name="Theme.Splash" parent="android:Theme">
        <item name="android:windowBackground">@drawable/splash</item>
        <item name="android:windowNoTitle">true</item>
    </style>
</resources>

5-Add a new activity to the project and add this code (of course you can safely remove the delay before StartActivity method)

[Activity(Theme = "@style/Theme.Splash", //Indicates the theme to use for this activity
             MainLauncher = true, //Set it as boot activity
             NoHistory = true)] //Doesn't place it in back stack
    public class SplashActivity : Activity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            System.Threading.Thread.Sleep(3000); //Let's wait awhile...
            this.StartActivity(typeof(MainActivity));
        }
    }

6-Remove the MainLauncher=true from original activity since this is the new activity that will be launched at startup.

Hope this helps…

Get device unique identifier in Xamarin Forms

Last week I introduced some ISV to the wonderful world of Xamarin and while discussing Xamarin Forms a few of them asked how to get an identifier that uniquely identifies a device.

I had the same issue in the past with a Windows Phone application so I know how retrieve it on this platform and I remember speaking with the guy that was working on the same app for iOS that he told me that Apple changed the policy so the API that was used in the past was no longer available and he had to find a workaround, more on this later.

The answer to the original question is quite easy from the architectural side: Just use a Dependency Service and you’re done, here are the steps:

Let’s create a IDevice interface in the common/shared project and let’s add a GetIdentifier method

public interface IDevice
 {
  string GetIdentifier();  
 }

Once done you can easily get device unique identifier within shared code using this snippet:

IDevice device = DependencyService.Get<IDevice>();
string deviceIdentifier = device.GetIdentifier();

Let’s now implement device specific code, starting from Windows Phone, add this class to Windows Phone project and add ID_CAP_IDENTITY_DEVICE capability.

[assembly: Xamarin.Forms.Dependency(typeof(WinPhoneDevice))]
namespace XFUniqueIdentifier.WinPhone
{
 public class WinPhoneDevice : IDevice
 {
  public string GetIdentifier()
  {
   byte[] myDeviceId = (byte[])Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("DeviceUniqueId");
   return Convert.ToBase64String(myDeviceId);
  }
 }
}

Now add following class to Android project:

[assembly: Xamarin.Forms.Dependency(typeof(AndroidDevice))]
namespace XFUniqueIdentifier.Droid
{
 public class AndroidDevice : IDevice
 {
  public string GetIdentifier()
  {
   return Settings.Secure.GetString(Forms.Context.ContentResolver, Settings.Secure.AndroidId);
  }
 }
}

And now the hardest part: iOS developer used to get device identifier using Device UniqueIdentifier api but this has deprecated by Apple so an alternative has to be found.

After some investigations (also considered generating unique id at startup but this would fail if app is reinstalled) I found this post on Xamarin forums so kudos goes to the original author.

It’s now time to add a new class to iOS project with following code:

[assembly: Xamarin.Forms.Dependency(typeof(IOSDevice))]
namespace XFUniqueIdentifier.iOS
{
 using System.IO;
 using System.Runtime.InteropServices;

 public class IOSDevice : IDevice
 {
  [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
  private static extern uint IOServiceGetMatchingService(uint masterPort, IntPtr matching);

  [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
  private static extern IntPtr IOServiceMatching(string s);

  [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
  private static extern IntPtr IORegistryEntryCreateCFProperty(uint entry, IntPtr key, IntPtr allocator, uint options);

  [DllImport("/System/Library/Frameworks/IOKit.framework/IOKit")]
  private static extern int IOObjectRelease(uint o);

  public string GetIdentifier()
  {
   string serial = string.Empty;
   uint platformExpert = IOServiceGetMatchingService(0, IOServiceMatching("IOPlatformExpertDevice"));
   if (platformExpert != 0)
   {
    NSString key = (NSString) "IOPlatformSerialNumber";
    IntPtr serialNumber = IORegistryEntryCreateCFProperty(platformExpert, key.Handle, IntPtr.Zero, 0);
    if (serialNumber != IntPtr.Zero)
    {
     serial = NSString.FromHandle(serialNumber);
    }

    IOObjectRelease(platformExpert);
   }

   return serial;
  }  
}

And you’re done, have fun and make a good use of device unique id. Smile

TranslateTo issue with Xamarin Forms 1.2.3

This Xamarin Forms snippets shifts a button left when clicked and restores it back when dialog is dismissed.

public static Page CreateMainPage3()
  {
   StackLayout container = new StackLayout() { Orientation = StackOrientation.Vertical };
   Button btn = new Button() { Text = "Ok" };
   btn.Clicked += async (s, e) =>
   {
    await btn.TranslateTo(-btn.Width, 0, 500);
    await MainPage.DisplayAlert("Test", "Hello", "Ok", "Cancel");
    await btn.TranslateTo(0, 0, 500);
   };

   container.Children.Add(btn);
   
   return MainPage = new ContentPage()
   {
    Content = container,
    Padding = new Thickness(10, 20, 10, 20)
   };
  }

Easy right? unfortunately it doesn’t work on Android (it is ok on Windows Phone and iOS) with Xamarin Forms version 1.2.3

The workaround is quite easy: use LayoutTo instead of TranslateTo, following code works on all platforms.

...
btn.Clicked += async (s, e) =>
   {
    Rectangle defaultRect = btn.Bounds;
    await btn.LayoutTo(new Rectangle(-btn.Width, btn.Y, btn.Width, btn.Height), 500);
    await MainPage.DisplayAlert("Test", "Hello", "Ok", "Cancel");
    await btn.LayoutTo(defaultRect, 500);
   };
 ...