Xamarin.Control – Xamarin.Forms MaterialEntry

Back by popular demand, bringing more Material Design controls to you Xamarin.Forms app! This time we will look at implementing the standards in Material Design’s text fields by building a MaterialEntry control. You can find the source code and example app here: https://github.com/SuavePirate/MaterialEntry but you can build your own by following this post.

Let’s build our Xamarin.Forms control to work the same on not only Android where Material Design is baked in, but also to run on iOS AND UWP. In the end, we should be able to use our floating label, set an accent color that expands on the label and underline when focused while being able to bind these properties through MVVM.

Simulator Screen Shot Jul 14, 2017, 3.42.03 PM

The first thing we need to do is create a BorderlessEntry that removes the border from our entry on all 3 platforms. I’ve done this in a previous blog post here: Xamarin.Forms Borderless Entry, so we won’t be implementing it here. This code is also in the GitHub link above.

With our BorderlessEntry we can now create our custom control WITHOUT ANY MORE CUSTOM RENDERERS!

Let’s set up the layout structure in our XAML file, and then wire up the animation logic in our code behind.

MaterialEntry.xaml

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"               xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"              xmlns:local="clr-namespace:SuaveControls.MaterialEntry"              x:Class="SuaveControls.MaterialEntry.MaterialEntry">
  <ContentView.Content>
        <Grid ColumnSpacing="16" Margin="0,8">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="1"/>
            </Grid.RowDefinitions>
            <Label x:Name="HiddenLabel" FontSize="10" IsVisible="False" Margin="0"/>
            <local:BorderlessEntry x:Name="EntryField" Text="{Binding Text, Mode=TwoWay}" Margin="0,12,0,0"/>
            <BoxView x:Name="BottomBorder" BackgroundColor="Gray"  Grid.Row="1" HeightRequest="1" Margin="0" HorizontalOptions="FillAndExpand"/>
            <BoxView x:Name="HiddenBottomBorder" BackgroundColor="Gray" Grid.Row="1" HeightRequest="1" Margin="0" WidthRequest="0" HorizontalOptions="Center"/>
        </Grid>
    </ContentView.Content>
</ContentView>

We set up our BorderlessEntry that will act as our formal point for entering text. We also add a label that is initially hidden and laid out on top of the BorderlessEntry. This is the label we will be using to animate the floating action that Material Design uses based while we fade out the placeholder text. The last bit is two BoxViews that act as the bottom line below the Entry. One is the unfocused which has a standard gray color, while the other has a width of 0 and will have a background color of our selected AccentColor. This will have an animated width expansion when the BorderlessEntry is focused.

Now let’s look at the animation and bindings in the code behind:

MaterialEntry.xaml.cs

public partial class MaterialEntry : ContentView
    {
        public static void Init() { }
        public static BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(MaterialEntry), defaultBindingMode: BindingMode.TwoWay);
        public static BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(MaterialEntry), defaultBindingMode: BindingMode.TwoWay, propertyChanged: (bindable, oldVal, newval) =>
        {
            var matEntry = (MaterialEntry)bindable;
            matEntry.EntryField.Placeholder = (string)newval;
            matEntry.HiddenLabel.Text = (string)newval;
        });

        public static BindableProperty IsPasswordProperty = BindableProperty.Create(nameof(IsPassword), typeof(bool), typeof(MaterialEntry), defaultValue: false, propertyChanged: (bindable, oldVal, newVal) =>
        {
            var matEntry = (MaterialEntry)bindable;
            matEntry.EntryField.IsPassword = (bool)newVal;
        });
        public static BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(MaterialEntry), defaultValue: Keyboard.Default, propertyChanged: (bindable, oldVal, newVal) =>
        {
            var matEntry = (MaterialEntry)bindable;
            matEntry.EntryField.Keyboard = (Keyboard)newVal;
        });
        public static BindableProperty AccentColorProperty = BindableProperty.Create(nameof(AccentColor), typeof(Color), typeof(MaterialEntry), defaultValue: Color.Accent);
        public Color AccentColor
        {
            get
            {
                return (Color)GetValue(AccentColorProperty);
            }
            set
            {
                SetValue(AccentColorProperty, value);
            }
        }
        public Keyboard Keyboard
        {
            get
            {
                return (Keyboard)GetValue(KeyboardProperty);
            }
            set
            {
                SetValue(KeyboardProperty, value);
            }
        }

        public bool IsPassword
        {
            get
            {
                return (bool)GetValue(IsPasswordProperty);
            }
            set
            {
                SetValue(IsPasswordProperty, value);
            }
        }

        public string Text
        {
            get
            {
                return (string)GetValue(TextProperty);
            }
            set
            {
                SetValue(TextProperty, value);
            }
        }
        public string Placeholder
        {
            get
            {
                return (string)GetValue(PlaceholderProperty);
            }
            set
            {
                SetValue(PlaceholderProperty, value);
            }
        }
        public MaterialEntry()
        {
            InitializeComponent();
            EntryField.BindingContext = this;
            EntryField.Focused += async (s, a) =>
            {
                HiddenBottomBorder.BackgroundColor = AccentColor;
                HiddenLabel.TextColor = AccentColor;
                HiddenLabel.IsVisible = true;
                if (string.IsNullOrEmpty(EntryField.Text))
                {
                    // animate both at the same time
                    await Task.WhenAll(
                        HiddenBottomBorder.LayoutTo(new Rectangle(BottomBorder.X, BottomBorder.Y, BottomBorder.Width, BottomBorder.Height), 200),
                        HiddenLabel.FadeTo(1, 60),
                        HiddenLabel.TranslateTo(HiddenLabel.TranslationX, EntryField.Y - EntryField.Height + 4, 200, Easing.BounceIn)
                     );
                    EntryField.Placeholder = null;
                }
                else
                {
                    await HiddenBottomBorder.LayoutTo(new Rectangle(BottomBorder.X, BottomBorder.Y, BottomBorder.Width, BottomBorder.Height), 200);
                }
            };
            EntryField.Unfocused += async (s, a) =>
            {
                HiddenLabel.TextColor = Color.Gray;
                if (string.IsNullOrEmpty(EntryField.Text))
                {
                    // animate both at the same time
                    await Task.WhenAll(
                        HiddenBottomBorder.LayoutTo(new Rectangle(BottomBorder.X, BottomBorder.Y, 0, BottomBorder.Height), 200),
                        HiddenLabel.FadeTo(0, 180),
                        HiddenLabel.TranslateTo(HiddenLabel.TranslationX, EntryField.Y, 200, Easing.BounceIn)
                     );
                    EntryField.Placeholder = Placeholder;
                }
                else
                {
                    await HiddenBottomBorder.LayoutTo(new Rectangle(BottomBorder.X, BottomBorder.Y, 0, BottomBorder.Height), 200);
                }
            };
        }
    }

We first set up the BindableProperties and public properties to enable the binding of the AccentColor, Text, Placeholder, and Keyboard. These BindableProperties also handle their own PropertyChanged events to update the view elements dynamically.

After that, we handle our constructor and wire up our Focused and Unfocused events on our BorderlessEntry. In the Focused event, we set the colors of the hidden bar, and the floating label to the accent color. We then start the animations of expanding the hidden bar, and the fade in and float up of the floating label.

On the Unfocused event, we do the inverse of setting the floating label color back to the unfocused color, check if there is text, if there is not – float the label back down, and then animate the collapse of the colored bar.

With all these things together, we get a nicely animated text field that has a floating label and expanding bottom bar with a given accent color!

ios_Material_Entry2

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Advertisements

Xamarin.Basics – Ad Hoc iOS Builds, Part 2a: Publishing in HockeyApp

Before Getting Started

Before learning how to upload your iOS builds to HockeyApp, be sure to check out Part 1 of this series: Xamarin.Basics – Ad Hoc iOS Builds, Part1: Certificates and Profiles to learn about the requirements for producing Ad Hoc builds that will be distributed in HockeyApp.

Quick Intro

Up to this point, we should have everything we need to build our iOS application in Release/Ad Hoc mode to produce an .ipa file. This output .ipa is what we will be uploading to HockeyApp and other distribution channels such as Mobile Center. It’s important to note that HockeyApp is actually on its way out the door and being booted by the new Visual Studio Mobile Center produced by Microsoft after acquiring HockeyApp and their team. At this point, Mobile Center is still in Preview, so if you’re looking for a production ready solution for the time being, stay here. If not, follow my next blog post (to be posted here) on doing this in Mobile Center.

Building

Now that we have our Distribution Certificate and Ad Hoc Provisioning Profile created in the Apple Developer Portal and downloaded on our Mac, we can move into Visual Studio and build our Application for Ad Hoc Release. The screenshots you’ll see below will be from Visual Studio 2017 on Windows, but the same principles apply to Visual Studio for Mac.

Ensure your Bundle Identifiers Match

In the Apple Developer portal, we created an App ID and in this definition, we set a Bundle Identifier. This ID needs to match the ID of our actual application. You can set the Bundle Identifier in the Info.plist file of your iOS project in Visual Studio.

Screen Shot 2017-07-12 at 1.54.00 PM

Set Build Configuration to Release – iPhone

Screen Shot 2017-07-12 at 2.07.06 PM

In order to build for iOS Ad Hoc distribution, you’ll need to build against an actual iOS device. Building for simulators does some things differently behind the scenes that makes it faster to install in a simulator. Since our app needs to run against devices, we need to build against a real device. We also need to build in Release mode since we shouldn’t be debugging an Ad Hoc build.

Double Check Your Bundle Signing

Before building, double check that your app is going to use the proper Signing Identity and Provisioning Profile. You can do this by opening the Properties (“Options” if your in VS for Mac) and go to the Bundle Signing tab. Here you can explicitly set a Profile and Certificate to use or let it automatically choose the profile and hope it works out.

Screen Shot 2017-07-12 at 2.12.12 PM.png

Build and Deploy

Now simply build and deploy your app by right clicking the project in the Solution Explorer and clicking the Deploy option.

Screen Shot 2017-07-12 at 2.21.49 PM

This will now create the .ipa file in your bin. Locate your .ipa at YOUR_IOS_PROJECT\bin\Ad-Hoc\YOUR_BUNDLE.ipa. This .ipa is what will be uploaded to HockeyApp and distributed.

Using HockeyApp

HockeyApp has some great getting started documentation for creating your app and also viewing crash reports etc. You can find that here: https://support.hockeyapp.net/kb.

We will focus on uploading a new build using the .ipa file we created. In order to do this, you will need to have created an account with HockeyApp and created an iOS Alpha or Beta application slot.

From here you can click on the Add Version button which will then prompt you to upload your .ipa file.

Screen Shot 2017-07-12 at 2.39.05 PMScreen Shot 2017-07-12 at 2.39.12 PM

Now you’ll be able to add some release notes to your version that is being uploaded. Then enable the people who are allowed to install your app and send them notifications.

Once this is done, your users whose devices are registered by their UDID to the Apple Developer Portal and the Provisioning Profile used will be able to download and install it through the HockeyApp mobile website!

With your users having their hands on the app, you’ll be able to view crash reports, respond to feedback and more through the HockeyApp portal!

Next Steps

Now that we’ve been able to manually upload builds to HockeyApp, we’ll be able to look at using Continuous Integration and Deployment to distribute our new versions as we commit our changes in the source code. James Montemagno has a great blog post in the official Xamarin blog here: https://blog.xamarin.com/continuous-integration-for-ios-apps-with-visual-studio-team-services/.

In a following post, we will look at the future of deploying our iOS applications internally by using the new Visual Studio Mobile Center.

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Android – Comparing Models in Kotlin, Java, and C# for Xamarin

Models are an obvious important part of our applications we develop. It’s how we define our data and because of that, we can grow our models to be quite large in number. This post will look at comparing the definition of models between Java, C# (for Xamarin), and Kotlin.

Our example model will be a simple Person that has a Name and Description along with an ID. Let’s look at how we can define our Person model with these fields as well as the ability to access these fields publicly.

Using Java

Java is going to be our largest and most annoying to develop. We need to define our class, private fields, and then public functions/methods to get and set the value of each of the fields. We also need to be able to instantiate a Person with all these properties set in the constructor.

Person.java

public class Person{
    private int id;
    private String name;
    private String description;

    public Person(int id, string name, string description){
        this.id = id;
        this.name = name;
        this.description = description;
    }

    public void setID(int id){
        this.id = id;
    }
    public int getID(){
        return this.id;
    }
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }
    public void setDescription(String description){
        this.description = description;
    }
    public String getDescription(){
        return this.description;
    }
}

That’s exhausting…

Now we can instantiate it and update properties like this:

...
Person bob = new Person(1, "Bob", "He writes code and stuff");
bob.setDescription("He doesn't actually write code");
...

Using C# for Xamarin Applications

C# makes our lives a lot easier with the get and set mechanism built into properties.

Person.cs

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public Person(int id, string name, string description)
    {
        ID = id;
        Name = name;
        Description = description;
    }
}

Nice and neat!

Now we can instantiate it and update properties like this:

...
var bob = new Person(1, "Bob", "He writes code and stuff");
bob.Description = "He doesn't actually write code";
...

Using Kotlin

Kotlin has some cool tricks that allow us to define and set properties directly in our constructor without having to define and set them separately. This gives us the quickest way to create simple POCO definitions and speed up that development time.

Person.kt

class Person(var id: Int, var name: String, var description: String);

One line.

Now we can instantiate it and update properties like this:

...
val bob = Person(1, "Bob", "He writes code and stuff");
bob.description = "He doesn't actually write code";
...

Conclusion

Each language has their nuances, but I think we can all agree that defining models in Java is just a headache that other languages have solved with better solutions.

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Tip – PCL Profile Problems

New to Xamarin now that Microsoft is pushing it harder with Visual Studio 2017 and Visual Studio for Mac? Can’t create a new PCL and reference it in your Out of the Box Xamarin.Forms project? This post is for you, and I assure you – you are not alone.

 

The Problem

The core of the problem is this shift within the Microsoft Stack from many different versions of the .NET framework and tools into a “standard” – .NET Standard. However, certain parts of Xamarin aren’t quite there. These are things that worked in Visual Studio 2015, but are now new problems for VS 2017 and VS for Mac, especially if you’re working on a team that uses a mix of these.

There are multiple types of Profiles available for a Portable Class Library. Here’s a quick matrix of the different Profiles and where they compare to .NET Standard versions and supported profiles:

PCL Profile .NET Standard PCL Platforms
Profile7 1.1 .NET Framework 4.5, Windows 8
Profile31 1.0 Windows 8.1, Windows Phone Silverlight 8.1
Profile32 1.2 Windows 8.1, Windows Phone 8.1
Profile44 1.2 .NET Framework 4.5.1, Windows 8.1
Profile49 1.0 .NET Framework 4.5, Windows Phone Silverlight 8
Profile78 1.0 .NET Framework 4.5, Windows 8, Windows Phone Silverlight 8
Profile84 1.0 Windows Phone 8.1, Windows Phone Silverlight 8.1
Profile111 1.1 .NET Framework 4.5, Windows 8, Windows Phone 8.1
Profile151 1.2 .NET Framework 4.5.1, Windows 8.1, Windows Phone 8.1
Profile157 1.0 Windows 8.1, Windows Phone 8.1, Windows Phone Silverlight 8.1
Profile259 1.0 .NET Framework 4.5, Windows 8, Windows Phone 8.1, Windows Phone Silverlight 8

Now we can look at the different .NET Standard versions and their supported platforms:

 

.NET Standard 1.0 1.1 1.2 1.3 1.4 1.5 1.6 2.0
.NET Core 1.0 1.0 1.0 1.0 1.0 1.0 1.0 2.0
.NET Framework (with tooling 1.0) 4.5 4.5 4.5.1 4.6 4.6.1 4.6.2
.NET Framework (with tooling 2.0 preview) 4.5 4.5 4.5.1 4.6 4.6.1 4.6.1 4.6.1 4.6.1
Mono 4.6 4.6 4.6 4.6 4.6 4.6 4.6 vNext
Xamarin.iOS 10.0 10.0 10.0 10.0 10.0 10.0 10.0 vNext
Xamarin.Android 7.0 7.0 7.0 7.0 7.0 7.0 7.0 vNext
Universal Windows Platform 10.0 10.0 10.0 10.0 10.0 vNext vNext vNext
Windows 8.0 8.0 8.1
Windows Phone 8.1 8.1 8.1
Windows Phone Silverlight 8.0

 

Xamarin.Forms is created to support everything from Windows Silverlight 8.0 and up. This means that Xamarin.Forms projects are created using a Profile 259 PCL. This is fine, however, Profile 259 is on it’s way out the door, and therefore can’t be created in Visual Studio 2017! When you create a new PCL in VS 2017, it is created with the latest version of .NET Standard that supports .NET Core, UWP, and Xamarin (as of now this is default to Profile7. However, this is incompatible with Profile 259 and therefore cannot be referenced by your newly created Xamarin.Forms project. There’s no way in the IDE or properties to get it to 259, so if you do still want to support Windows Phone and Windows 8 with your Xamarin Projects in Visual Studio 2017, read below. If you don’t, update your Xamarin.Forms project to remove support for Windows 8 and Windows phone and your profiles will be matching again.

Here’s what the default Xamarin.Forms project targets are:
Screen Shot 2017-07-03 at 11.42.45 AM

And here is what a newly created PCL project targets are with everything selected:

Screen Shot 2017-07-03 at 11.42.58 AM

 

The Solution

We need to get our newly created PCLs to Profile 259 in order to reference them in our Xamarin.Forms project. We can’t do this in the IDE, so we need to dive into the .csproj file itself and make some changes:

NewPCL.csproj

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import ... />
  <PropertyGroup>
    <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{4a6a9117-1715-47ea-a6c7-6b0fd5b31bdb}</ProjectGuid>
    <OutputType>Library</OutputType>
    <RootNamespace>NewPCL</RootNamespace>
    <AssemblyName>NewPCL</AssemblyName>
    <DefaultLanguage>en-US</DefaultLanguage>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

    <!-- THIS IS WHAT NEEDS TO CHANGE -->
    <TargetFrameworkProfile>Profile7</TargetFrameworkProfile>


    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
  </PropertyGroup>
...
</Project>

Take that line of Profile7 and update it to Profile259 so that it looks like this all together:

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import ... />
  <PropertyGroup>
    <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{4a6a9117-1715-47ea-a6c7-6b0fd5b31bdb}</ProjectGuid>
    <OutputType>Library</OutputType>
    <RootNamespace>NewPCL</RootNamespace>
    <AssemblyName>NewPCL</AssemblyName>
    <DefaultLanguage>en-US</DefaultLanguage>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

    <!-- THIS IS WHAT HAS CHANGED -->
    <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>


    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
  </PropertyGroup>
...
</Project>

 
Now you’ll be able to add this project as a reference in your Xamarin.Forms PCL project and continue on.

I know this is pretty annoying to do on large projects that contain many different project files. Take a look at my Onion Architecture project as an example…

This is something that is happening because of this weird in-between state we are at with .NET tooling and the move to .NET Standard. Going forward, Xamarin.Forms will be dropping support for Windows Phone Silverlight which will no longer require Profile259 in order to build our applications in Xamarin.Forms. However, for now, this is the fix for new projects!

Still Broken?

Still having issues with your project structures? Leave a comment and I’ll try to help resolve it.

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Tip – Fixing the VS for Mac Xamarin.Forms Template Android Issues

Here’s another quick resolution to one of the most annoying issues I’ve faced in working with Visual Studio for Mac…

The Problem

When creating a brand new, out of the box, Xamarin.Forms project, it didn’t work. This has been a common trend for Xamarin/Microsoft over the last year or so as they roll out Xamarin + Visual Studio updates. The latest culprit was that the Android project was never able to actually install the Xamarin.Forms package from nuget. This was not obvious during the actual build, since the project DID load successfully, and the build errors were along the lines of not being able to find Android Support library resources in the styles.xml. This also caused an issue where source files were not loading with intellisense or highlighting, so the error was even less obvious (see Xamarin.Tip – Fixing the Highlighting Drop In Your Xamarin.Android Projects).

When going into the nuget package manager and trying to manually add the Xamarin.Forms package, I was hit with this error:

Could not install package 'Xamarin.Android.Support.v4 23.3.0'. You are trying to install this package into a project that targets 'MonoAndroid,Version=v2.3'
...

The Solution

My first instinct was to check the Android target version in the project options to make sure that they were within the supported SDK range, and they were:
Screen Shot 2017-06-21 at 4.05.17 PM

Unlike Visual Studio 2017 (or any Windows VS with Xamarin), there was no “Compile using Android Version” picker. THIS field is what is really determines the projects target framework level, but VS for Mac doesn’t have it like it should (hope you’re reading this Microsoft!).

Let’s fix it manually:

  1. Unload your Android project by right clicking it in the Solution explorer and clicking “Unload”
  2. Open the Android project .csproj in the editor by right clicking > Tools > Edit.
  3. For each build configuration, add an explicit TargetFrameworkVersion that’s compatible. In my case that was v4.4
  4. Your .csproj should look like this:
    <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    ... 
      <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
        <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
        <ProjectGuid>{2BC9AAD5-D311-499E-8B06-A63CCB65C633}</ProjectGuid>
        <ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
        <OutputType>Library</OutputType>
        <RootNamespace>AppName.Droid</RootNamespace>
        <AssemblyName>AppName.Droid</AssemblyName>
        <AndroidApplication>True</AndroidApplication>
        <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
        <AndroidResgenClass>Resource</AndroidResgenClass>
        <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
        <MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
        <MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
        <AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
        <TargetFrameworkVersion>v4.4</TargetFrameworkVersion> <!-- THIS IS WHAT YOU NEED TO ADD OR CHANGE -->
      </PropertyGroup>
      <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
        <DebugSymbols>true</DebugSymbols>
        <DebugType>full</DebugType>
        <Optimize>false</Optimize>
        <OutputPath>bin\Debug</OutputPath>
        <DefineConstants>DEBUG;</DefineConstants>
        <ErrorReport>prompt</ErrorReport>
        <WarningLevel>4</WarningLevel>
        <AndroidLinkMode>None</AndroidLinkMode>
        <TargetFrameworkVersion>v4.4</TargetFrameworkVersion><!-- THIS IS WHAT YOU NEED TO ADD OR CHANGE -->
      </PropertyGroup>
      <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
        <DebugSymbols>true</DebugSymbols>
        <DebugType>pdbonly</DebugType>
        <Optimize>true</Optimize>
        <OutputPath>bin\Release</OutputPath>
        <ErrorReport>prompt</ErrorReport>
        <WarningLevel>4</WarningLevel>
        <AndroidManagedSymbols>true</AndroidManagedSymbols>
        <AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
        <TargetFrameworkVersion>v4.4</TargetFrameworkVersion><!-- THIS IS WHAT YOU NEED TO ADD OR CHANGE -->
      </PropertyGroup>
    
    ...
    </Project>
    
  5. Close the .csproj editor
  6. Reload the project by right clicking in the Solution Explorer and selecting Reload
  7. Retry adding the Xamarin.Forms nuget package to the project

Now you should be good to go. Did this not work for you? Leave a comment below and I’d be happy to help you fix this annoying issue as well!

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Xamarin.Tip – Mvvm Light and Dependency Injection

Inversion of Control and Dependency Injection are some design principles that help make our applications more flexible and scalable. They both help us separate our implementations and make it easy to substitute drastic changes to our implemented data or business logic whether it be for writing unit tests or product improvement.

Xamarin is a platform where IoC and DI fit extremely well. I’ve talked about this concept a few other times in both my blogs and videos about the Onion Architecture in Xamarin as well as how to call Platform Specific code from a Portable Class Library. You can find those posts and videos here:

  1. Onionizing Xamarin Part 6
  2. [VIDEO] Xamarin.Tips: Calling Platform-Specific Code from a PCL (Dependency Injection)

In this post, I want to talk about using DI with Mvvm Light at a VERY basic level.

First, let’s define an interface for a service we might use:

IUserService.cs

public interface IUserService
{
    Task<User> GetCurrentUserAsync();
}

Now let’s create two different implementations. One that will be the service used in the application and the other that will be used for testing.

UserService.cs

public class UserService : IUserService
{
    // makes a call to a web api to get a user
    public async Task<User> GetCurrentUserAsync()
    {
        using (var client = new HttpClient())
        {
            var response = await client.GetAsync("https://mywebapi.mydomain/api/currentuser");
            var content = await response.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<User>(content);
        }
    }
}

TestUserServices.cs

public class TestUserService : IUserService
{
    public Task<User> GetCurrentUserAsync()
    {
        return Task.FromResult(new User { Name = "Test User" });
    }
}

Now we need a ViewModel that will use this service. We define a private readonly IUserService and then inject the implementation that we want in the constructor of the ViewModel.

CurrentUserViewModel.cs

public class CurrentUserViewModel : ViewModelBase
{
    // use the interface as the service and inject the implementation in the constructur
    private readonly IUserService _userService;
    private User _user;

    public User User
    {
        get
        {
            return _user;
        }
        set
        {
            Set(ref _user, value);
        }
    }

    public CurrentUserViewModel(IUserService userService)
    {
        _userService = userService;
    }

    public async Task UpdateUserAsync()
    {
        User = await _userService.GetCurrentUserAsync();
    }
}

Now let’s define an IoCConfig that handles registering dependencies and implementations.

IoCConfig.cs

public class IoCConfig
{
    public IoCConfig()
    {
        // use SimpleIoc from MvvmLight as our locator provider
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
    }

    // register the real implementation
    public void RegisterServices()
    {
        SimpleIoc.Default.Register<IUserService, UserService>();
    }

    // register the test implementation
    public void RegisterTestServices()
    {
        SimpleIoc.Default.Register<IUserService, TestUserService>();
    }

    // register the view model
    public void RegisterViewModels()
    {
        SimpleIoc.Default.Register<CurrentUserViewModel>();
    }
}

Now that we can register our Services as well as our ViewModels, the dependency resolver from SimpleIoc can retrieve an instance of CurrentUserViewModel with whichever version of IUserService is registered depending on whether we call RegisterServices or RegisterTestServices.

Now we can retrieve our instance of the CurrentUserViewModel by calling

var currentUserViewModel = ServiceLocator.Current.GetInstance<CurrentUserViewModel>();

MvvmLight recommends using a ViewModelLocator to get the instance of your ViewModels:

ViewModelLocator.cs

public class ViewModelLocator
{
    private readonly IoCConfig _iocConfig;
    public CurrentUserViewModel CurrentUser
    {
        get
        {
            return ServiceLocator.Current.GetInstance<CurrentUserViewModel>();
        }
    }

    public ViewModelLocator()
    {
        _iocConfig = new IoCConfig();
        _iocConfig.RegisterServices();
        //_iocConfig.RegisterTestServices();
        _iocConfig.RegisterViewModels();
    }

}

It’s recommended to either create your ViewModelLocator at the app start up, or if you’re using Xamarin.Forms, register it as a Resource in your App.xaml

<Application ...     xmlns:locator="clr-namespace:YOUR_LOCATOR_LOCATION">
    <Application.Resources>
        <ResourceDictionary>
            <locator:ViewModelLocator x:Key="Locator"/>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Now in your XAML pages, you can automatically wire up your view model.

MainPage.xaml

<ContentPage ...     BindingContext="{Binding Source={StaticResource Locator}, Path=CurrentUser}"     Title="{Binding User.Name}">
...
</ContentPage>

In order to change to your testing data, you can just switch which call to your IoCConfig is made for registering your dependency without having to make any changes to any of your other layers or UI!

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Unity.Tip – Create a Rotating Sun

Changing pace from the usual mobile app development, let’s talk about Unity!

Here’s a quick tip on adding a rotating sun to your Scenes to give your game a feeling of Day and Night.

First, add a light source or use the default light from a new scene, then Add a new Component .

Select Create new script and call it LightController. This script will have a public property for the length of the day you wish your sun to rotate, then handle the rotation speed calculation.

LightController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LightController : MonoBehaviour {
	public float DayLength;
	private float _rotationSpeed;

	void Update(){
		_rotationSpeed = Time.deltaTime / DayLength;
		transform.Rotate (0, _rotationSpeed, 0);
	}
}

Back in Unity, set your DayLength to a desired speed, and run your game.

Screen Shot 2017-05-30 at 5.02.35 PM
You’ll notice your sun/light moving around your scene and giving your area a sense of day and night.

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.