Xamarin.Forms with Xamarin Native


Isn't it fun,

to instantly listen to a blog on the go? PLAY !

 
 

Xamarin.Forms_with_Xamarin_Native

Whenever one tends to go with developing Xamarin application, the first thought he might get is whether to use Xamarin Forms or Xamarin native. With Xamarin Forms, we can develop any kind of application and it’s efficient because it has easy XAML designs and immense community forums.

Depending on the complexity and native functions, we sometimes choose Xamarin Native.

At this time, we can merge Xamarin.Forms with Xamarin Native. It has some steps to be followed while doing this and th-ey are:

Table of Content

  1. Firstly, add NuGet package- Xamarin.Forms in the Xamarin Native project.
  2. Next, add the ContentPage that is derived page and if any dependency is needed to the Xamarin Native project.
  3. Now, call the Forms.Init method in the startup file of the Xamarin Native project
  4. Now, make an instance of ContentPage and after that convert that instance into Xamarin Native type using the appropriate extension method according to the project.
  5. Then, navigate it to the native type using Xamarin Native navigation API.

The NativeForms never contains any Xamarin.Forms projects, rather it only contains Xamarin.Android, Xamarin.iOS, and Xamarin.UWP project.

Adding the Xamarin.Forms into Xamarin.Android project

As the first step, we convert the ContentPage into the Fragment using Fragment Manager.

For this, we add an XML page in the Resource>>Layout folder of the Android project.

Main.xml



    
    


The content of the Activity is set in the layout resource. Here, the layout used is LinearLayout containing the Toolbar and FrameLayout that generates a fragment container.

Nextly, consume the ContentPage in the MainActivity file.

   

Tasks performed by OnCreate function:

using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.OS;
using App2.Droid.Views;
using Xamarin.Forms;
using Android.Widget;
using System.IO;
using Xamarin.Forms.Platform.Android;
using App2.Droid.Models;
using AndroidX.AppCompat.App;
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;

namespace App2.Droid
{
    [Activity(Label = "App2", Icon = "@drawable/icon", Theme = "@style/MainTheme", 
MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | 
ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | 
ConfigChanges.SmallestScreenSize )]
    public class MainActivity : AppCompatActivity
    {
        public static string FldrPath { get; private set; }

        public static MainActivity Instance;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            Forms.Init(this, savedInstanceState); 

            Xamarin.Forms.Application.Current = new Xamarin.Forms.Application();
            Xamarin.Forms.Application.Current.Resources = new MyDictionary();

            Instance = this;
            SetContentView(Resource.Layout.Main);
            var toolbar = FindViewById(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);
            SupportActionBar.Title = "Notes";

            
FldrPath = 
Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.
LocalApplicationData));

            NotesPage notesPage = new NotesPage()
            {
                Parent = Xamarin.Forms.Application.Current
            };
            AndroidX.Fragment.App.Fragment notesPageFragment = 
notesPage.CreateSupportFragment(this);

            SupportFragmentManager
                .BeginTransaction()
                .Replace(Resource.Id.fragment_frame_layout, notesPageFragment)
                .Commit();

            SupportFragmentManager.BackStackChanged += (sender, e) =>
            {
                bool hasBack = SupportFragmentManager.BackStackEntryCount > 0;
                SupportActionBar.SetHomeButtonEnabled(hasBack);
                SupportActionBar.SetDisplayHomeAsUpEnabled(hasBack);
                SupportActionBar.Title = hasBack ? "Notes Entry" : "Notes";
            };
            notesPage.Parent = null;
        }
        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, 
[GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, 
grantResults);
            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
        public override bool OnOptionsItemSelected(Android.Views.IMenuItem item)
        {
            if (item.ItemId == global::Android.Resource.Id.Home && 
SupportFragmentManager.BackStackEntryCount > 0)
            {
                SupportFragmentManager.PopBackStack();
                return true;
            }
            return base.OnOptionsItemSelected(item);
        }

        public void NavigateToNotesEntry(Note note)
        {
            NotesEntry NotesEntry = new NotesEntry
            {
                BindingContext = note,
                Parent = Xamarin.Forms.Application.Current
            };

            AndroidX.Fragment.App.Fragment noteEntryFragment = 
NotesEntry.CreateSupportFragment(this);
            SupportFragmentManager
                .BeginTransaction()
                .AddToBackStack(null)
                .Replace(Resource.Id.fragment_frame_layout, noteEntryFragment)
                .Commit();

            NotesEntry.Parent = null;
        }

        public void NavigateBack()
        {
            SupportFragmentManager.PopBackStack();
        }
    }
}

- Here, overriding the OnCreate is typically performing tasks related to application startup.

- Tasks performed by OnCreate function:

  1. By calling the Forms.Init method Xamarin.Forms are initialized.
  2. A new object of Xamarin.Forms.Application is created and then its resource dictionary of application-level is defined in a XAML file.
  3. A reference of the MainActivity class is stored in the static Instance field and provides a tool for calling methods that are defined in the MainActivity class for other classes.
  4. Wherever the data of the notes will be kept, that path is set in the FolderPath property.
  5. The NotesPage’s object is converted to a Fragment by the use of the CreateSupportFragment extension method.
  6. Creating and committing a transaction that replaces the instance of FrameLayout with the Fragment for the NotesPage class is done by SupportFragmentManager class.
  7. To not leaking the memory, the property Parent of the NotesPage is set to NULL.

All the derived ContentPages can consume the resources defined in the ResourceDictionary at Application-level and it provides the parent property of the page set to the Application object.

The MainActivity.NavigateToNotesEntry method to be invoked is enabled by the static MainActivity.Instance field.

The NavigateToNoteEntry function is converting the derived ContentPage of Xamarin.Forms into a Fragment along with the CreateSupportFragment extension method.

After that, it adds the fragment back to the fragment back stack.

When we click the back button on the NoteEntry page, it will display the fragment for the NoteEntry from the back stack of the fragment, and returns the user to the NotesPage class.

 

NotesPage.xaml


<?xml encoding="utf-8" version="1.0">
<contentpage x:class="App2.Droid.Views.NotesPage" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <contentpage.content>
        <stacklayout margin="20"><button clicked="OnNoteAddedClicked" fontsize="Large" horizontaloptions="End" text="+">
            
<listview itemselected="OnListViewItemSelected" x:name="listView">
                <listview.itemtemplate>
                    <datatemplate>
                        <textcell detail="{Binding dt}" text="{Binding txt}" />
                    </datatemplate>
                </listview.itemtemplate>
            </listview></button></stacklayout>
    </contentpage.content>
</contentpage>
</?xml>
 

NotesEntry.xaml

<?xml encoding="utf-8" version="1.0">
<?xml encoding="utf-8" version="1.0">
<contentpage x:class="App2.Droid.Views.NotesEntry" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
   
 <contentpage.content>
        <stacklayout margin="20">
            <editor heightrequest="100" placeholder="Enter your note" text="{Binding txt}" />
            
<grid>
                <grid.columndefinitions>
                    <columndefinition width="*" />
                    <columndefinition width="*" />
                </grid.columndefinitions><button clicked="OnSaveButtonClicked" text="Save"></button><button clicked="OnDeleteButtonClicked" grid.column="1" text="Delete"></button><button clicked="OnSaveButtonClicked" text="Save"></button></grid>
        </stacklayout>
    </contentpage.content>
</contentpage>


</?xml></?xml>

- The Model here is used to get and set the data retrieved.

Note.cs

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System;	
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace App2.Droid.Models
{
    public class Note
    {
        public string Filename { get; set; }
        public string txt { get; set; }
        public DateTime dt { get; set; }
    }
}

- The ResourceDictionary is used to set the background color of the buttons of the whole application.

 

Planning to Hire Xamarin App Development Company ?

Your Search ends here.

 

MyDictionary.xaml

<?xml encoding="utf-8" version="1.0"><?xml encoding="utf-8" version="1.0">
<?xml encoding="utf-8" version="1.0">
<resourcedictionary x:class="App2.Droid.MyDictionary" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"><style targettype="Button" type="text/css"><Setter Property="BackgroundColor" Value="LightGray"/></style>
</resourcedictionary>
</?xml></?xml></?xml>

Multiple Activities

The derived ContentPages can be merged with each activity when any application has multiple activities.

In this situation, the method Forms.Init should be called in only the OnCreate override method of the first activity that is merging with the Xamarin.Forms page.

But, it will have some impacts as:

  1. The Activity that called the Forms.Init method will give the Xamarin.Forms.Color.Accent value.
  2. And, it will be also associated with the value of Xamarin.Forms.Application.Current.
Output

Conclusion

From this blog, we can learn how to add multiple activities to the App and merge the Xamarin Forms with Native Application. As Xamarin Native is not just that easy as the Xamarin.Forms, we can use it sometimes when the complexity is more and the native functions are to be mandatorily used.

Xamarin.Forms with Xamarin Native

Xamarin.Forms_with_Xamarin_Native

Whenever one tends to go with developing Xamarin application, the first thought he might get is whether to use Xamarin Forms or Xamarin native. With Xamarin Forms, we can develop any kind of application and it’s efficient because it has easy XAML designs and immense community forums.

Depending on the complexity and native functions, we sometimes choose Xamarin Native.

At this time, we can merge Xamarin.Forms with Xamarin Native. It has some steps to be followed while doing this and th-ey are:

Table of Content

  1. Firstly, add NuGet package- Xamarin.Forms in the Xamarin Native project.
  2. Next, add the ContentPage that is derived page and if any dependency is needed to the Xamarin Native project.
  3. Now, call the Forms.Init method in the startup file of the Xamarin Native project
  4. Now, make an instance of ContentPage and after that convert that instance into Xamarin Native type using the appropriate extension method according to the project.
  5. Then, navigate it to the native type using Xamarin Native navigation API.

The NativeForms never contains any Xamarin.Forms projects, rather it only contains Xamarin.Android, Xamarin.iOS, and Xamarin.UWP project.

Adding the Xamarin.Forms into Xamarin.Android project

As the first step, we convert the ContentPage into the Fragment using Fragment Manager.

For this, we add an XML page in the Resource>>Layout folder of the Android project.

Main.xml



    
    


The content of the Activity is set in the layout resource. Here, the layout used is LinearLayout containing the Toolbar and FrameLayout that generates a fragment container.

Nextly, consume the ContentPage in the MainActivity file.

   

Tasks performed by OnCreate function:

using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.OS;
using App2.Droid.Views;
using Xamarin.Forms;
using Android.Widget;
using System.IO;
using Xamarin.Forms.Platform.Android;
using App2.Droid.Models;
using AndroidX.AppCompat.App;
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;

namespace App2.Droid
{
    [Activity(Label = "App2", Icon = "@drawable/icon", Theme = "@style/MainTheme", 
MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | 
ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | 
ConfigChanges.SmallestScreenSize )]
    public class MainActivity : AppCompatActivity
    {
        public static string FldrPath { get; private set; }

        public static MainActivity Instance;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            Forms.Init(this, savedInstanceState); 

            Xamarin.Forms.Application.Current = new Xamarin.Forms.Application();
            Xamarin.Forms.Application.Current.Resources = new MyDictionary();

            Instance = this;
            SetContentView(Resource.Layout.Main);
            var toolbar = FindViewById(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);
            SupportActionBar.Title = "Notes";

            
FldrPath = 
Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.
LocalApplicationData));

            NotesPage notesPage = new NotesPage()
            {
                Parent = Xamarin.Forms.Application.Current
            };
            AndroidX.Fragment.App.Fragment notesPageFragment = 
notesPage.CreateSupportFragment(this);

            SupportFragmentManager
                .BeginTransaction()
                .Replace(Resource.Id.fragment_frame_layout, notesPageFragment)
                .Commit();

            SupportFragmentManager.BackStackChanged += (sender, e) =>
            {
                bool hasBack = SupportFragmentManager.BackStackEntryCount > 0;
                SupportActionBar.SetHomeButtonEnabled(hasBack);
                SupportActionBar.SetDisplayHomeAsUpEnabled(hasBack);
                SupportActionBar.Title = hasBack ? "Notes Entry" : "Notes";
            };
            notesPage.Parent = null;
        }
        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, 
[GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, 
grantResults);
            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
        public override bool OnOptionsItemSelected(Android.Views.IMenuItem item)
        {
            if (item.ItemId == global::Android.Resource.Id.Home && 
SupportFragmentManager.BackStackEntryCount > 0)
            {
                SupportFragmentManager.PopBackStack();
                return true;
            }
            return base.OnOptionsItemSelected(item);
        }

        public void NavigateToNotesEntry(Note note)
        {
            NotesEntry NotesEntry = new NotesEntry
            {
                BindingContext = note,
                Parent = Xamarin.Forms.Application.Current
            };

            AndroidX.Fragment.App.Fragment noteEntryFragment = 
NotesEntry.CreateSupportFragment(this);
            SupportFragmentManager
                .BeginTransaction()
                .AddToBackStack(null)
                .Replace(Resource.Id.fragment_frame_layout, noteEntryFragment)
                .Commit();

            NotesEntry.Parent = null;
        }

        public void NavigateBack()
        {
            SupportFragmentManager.PopBackStack();
        }
    }
}

- Here, overriding the OnCreate is typically performing tasks related to application startup.

- Tasks performed by OnCreate function:

  1. By calling the Forms.Init method Xamarin.Forms are initialized.
  2. A new object of Xamarin.Forms.Application is created and then its resource dictionary of application-level is defined in a XAML file.
  3. A reference of the MainActivity class is stored in the static Instance field and provides a tool for calling methods that are defined in the MainActivity class for other classes.
  4. Wherever the data of the notes will be kept, that path is set in the FolderPath property.
  5. The NotesPage’s object is converted to a Fragment by the use of the CreateSupportFragment extension method.
  6. Creating and committing a transaction that replaces the instance of FrameLayout with the Fragment for the NotesPage class is done by SupportFragmentManager class.
  7. To not leaking the memory, the property Parent of the NotesPage is set to NULL.

All the derived ContentPages can consume the resources defined in the ResourceDictionary at Application-level and it provides the parent property of the page set to the Application object.

The MainActivity.NavigateToNotesEntry method to be invoked is enabled by the static MainActivity.Instance field.

The NavigateToNoteEntry function is converting the derived ContentPage of Xamarin.Forms into a Fragment along with the CreateSupportFragment extension method.

After that, it adds the fragment back to the fragment back stack.

When we click the back button on the NoteEntry page, it will display the fragment for the NoteEntry from the back stack of the fragment, and returns the user to the NotesPage class.

 

NotesPage.xaml


<?xml encoding="utf-8" version="1.0">
<contentpage x:class="App2.Droid.Views.NotesPage" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <contentpage.content>
        <stacklayout margin="20"><button clicked="OnNoteAddedClicked" fontsize="Large" horizontaloptions="End" text="+">
            
<listview itemselected="OnListViewItemSelected" x:name="listView">
                <listview.itemtemplate>
                    <datatemplate>
                        <textcell detail="{Binding dt}" text="{Binding txt}" />
                    </datatemplate>
                </listview.itemtemplate>
            </listview></button></stacklayout>
    </contentpage.content>
</contentpage>
</?xml>
 

NotesEntry.xaml

<?xml encoding="utf-8" version="1.0">
<?xml encoding="utf-8" version="1.0">
<contentpage x:class="App2.Droid.Views.NotesEntry" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
   
 <contentpage.content>
        <stacklayout margin="20">
            <editor heightrequest="100" placeholder="Enter your note" text="{Binding txt}" />
            
<grid>
                <grid.columndefinitions>
                    <columndefinition width="*" />
                    <columndefinition width="*" />
                </grid.columndefinitions><button clicked="OnSaveButtonClicked" text="Save"></button><button clicked="OnDeleteButtonClicked" grid.column="1" text="Delete"></button><button clicked="OnSaveButtonClicked" text="Save"></button></grid>
        </stacklayout>
    </contentpage.content>
</contentpage>


</?xml></?xml>

- The Model here is used to get and set the data retrieved.

Note.cs

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System;	
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace App2.Droid.Models
{
    public class Note
    {
        public string Filename { get; set; }
        public string txt { get; set; }
        public DateTime dt { get; set; }
    }
}

- The ResourceDictionary is used to set the background color of the buttons of the whole application.

 

Planning to Hire Xamarin App Development Company ?

Your Search ends here.

 

MyDictionary.xaml

<?xml encoding="utf-8" version="1.0"><?xml encoding="utf-8" version="1.0">
<?xml encoding="utf-8" version="1.0">
<resourcedictionary x:class="App2.Droid.MyDictionary" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"><style targettype="Button" type="text/css"><Setter Property="BackgroundColor" Value="LightGray"/></style>
</resourcedictionary>
</?xml></?xml></?xml>

Multiple Activities

The derived ContentPages can be merged with each activity when any application has multiple activities.

In this situation, the method Forms.Init should be called in only the OnCreate override method of the first activity that is merging with the Xamarin.Forms page.

But, it will have some impacts as:

  1. The Activity that called the Forms.Init method will give the Xamarin.Forms.Color.Accent value.
  2. And, it will be also associated with the value of Xamarin.Forms.Application.Current.
Output

Conclusion

From this blog, we can learn how to add multiple activities to the App and merge the Xamarin Forms with Native Application. As Xamarin Native is not just that easy as the Xamarin.Forms, we can use it sometimes when the complexity is more and the native functions are to be mandatorily used.