Embedding Native Controls into Xamarin.Forms

James Montemagno

There are several ways to extend Xamarin.Forms to finely tune your apps’ user interfaces, including the use of custom renderers and, more recently, effects. Sometimes, though, you just want to take a native control and place it directly into your Xamarin.Forms application without any of the ceremony and code around these two other approaches. This is where the newly announced Native Embedding (Xamarin.Forms 2.2.0+) feature comes in, enabling you to easily add a native control to any Xamarin.Forms layout.

Native Embedding

Set Up for Embedding Native Controls

It’s easier and recommended to use Shared Projects for native embedding since the feature is exposed as platform extension methods on a Xamarin.Forms layout control, but it can also be accomplished by exposing the layout in a portable class library. Since we’ll use a shared project, we can use conditional compilation for each platform we wish to add the native control too. For this blog, we’ll take a look at how to embed an Android and iOS control onto a Xamarin.Forms app that has a ListView on it.

Currently, the code is a simple ListView inside of an AbsoluteLayout:

var list = new ListView();
list.ItemsSource = new[] { "Hello", "World", "This", "Is", "Native", "Embedding" };

// Main page layout
var pageLayout = new StackLayout
{
  Children = { list }
};

var absolute = new AbsoluteLayout()
{
  VerticalOptions = LayoutOptions.FillAndExpand,
  HorizontalOptions = LayoutOptions.FillAndExpand
};

// Position the pageLayout to fill the entire screen.
// Manage positioning of child elements on the page by editing the pageLayout.
AbsoluteLayout.SetLayoutFlags(pageLayout, AbsoluteLayoutFlags.All);
AbsoluteLayout.SetLayoutBounds(pageLayout, new Rectangle(0f, 0f, 1f, 1f));
absolute.Children.Add(pageLayout);

var stack = new StackLayout
{
    Padding = 8,
    HorizontalOptions = LayoutOptions.Center,
};


//Embed Native Controls here to add to StackLayout above


// The root page of your application
var content = new ContentPage
{
  Title = "Native Embedding",
  Content = absolute
};

MainPage = new NavigationPage(content);

Android Floating Action Button

At Xamarin Evolve Jérémie and I gave a talk on Material Design for Android applications where Jérémie showed off an amazing vector drawable animation in a FAB. Let’s leverage the hard work Jérémie did for his traditional Android app and bring it over to a Xamarin.Forms application. To get this working, we’ll copy over Jérémie’s CheckedFab code and resources from his Buzzeroid application.

At the top of this page, we’ll bring in a few Android specific namespaces

#if __ANDROID__
using Xamarin.Forms.Platform.Android;
using NativeTest.Droid; //Your Namespace
using Android.Views;
#endif

To add the native FAB all we need to do is create it with the Xamarin.Forms context and set a few properties and events:

#if __ANDROID__
var fab = new CheckableFab(Forms.Context)
{
  UseCompatPadding = true
};
           
fab.SetImageResource(Droid.Resource.Drawable.ic_fancy_fab_icon);
fab.Click += async (sender, e) =>
{
  await Task.Delay(3000);
  await MainPage.DisplayAlert("Native FAB Clicked", 
                                            "Whoa!!!!!!", "OK");
};
            
stack.Children.Add(fab);
absolute.Children.Add(stack);

// Overlay the FAB in the bottom-right corner
AbsoluteLayout.SetLayoutFlags(stack, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(stack, new Rectangle(1f, 1f, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
#endif

Now we can run the application and see our FAB working with full animations!

FAB Embedding

iOS Native Controls

So far, we’ve spiced up the Android page with a control that only exists on Android platforms, and the same can be done for iOS with a segmented control that is used to filter content in the list. This time, instead of adding Android namespaces to the top of the page, we’ll add iOS specific namespaces:

#if __IOS__
using Xamarin.Forms.Platform.iOS;
using UIKit;
using CoreGraphics;
#endif

Then simply create the iOS control and insert it into the top of the StackLayout:

#if __IOS__
var segmentControl = new UISegmentedControl();
segmentControl.Frame = new CGRect(20, 20, 280, 40);
segmentControl.InsertSegment("One", 0, false);
segmentControl.InsertSegment("Two", 1, false);
segmentControl.SelectedSegment = 1;
segmentControl.ValueChanged += async (sender, e) =>
{
  var selectedSegmentId = (sender as UISegmentedControl).SelectedSegment;
  await MainPage.DisplayAlert($"Native Segmented Control Clicked {selectedSegmentId}",
                                            "Whoa!!!!!!", "OK");
};
stack.Children.Add(segmentControl);
 pageLayout.Children.Insert(0, stack);
#endif

NativeTest

Start Embedding with Native Controls

There you have it! With just a few lines of code in our shared project, we’ve embedded two completely different controls in our iOS and Android projects. Building your app in XAML and portable class libraries? Check out the next evolution of native embedding with the next series in this blog post.

This is just the beginning, as native embedding opens up a world of possibilities. Be sure to read through our entire native embedding documentation for more great examples and download this sample from my GitHub page.

0 comments

Discussion is closed.

Feedback usabilla icon