Introduciendo Xamarin.Forms en Xamarin nativo

Cuando nos planteamos un nuevo proyecto siempre surge la misma pregunta:

¿Usamos Xamarin.Forms o Xamarin nativo? 

Xamarin Forms permite crear las pantallas una vez y utilizarlas en todas las plataformas, mientras que con Xamarin nativo es necesario crear las pantallas de manera independiente.

 

No obstante, el rendimiento de Xamarin nativo es mucho más alto que el de Forms y podría ser imprescindible en apps con mucho consumo de recursos, o para aquellas que necesitan funcionar lo más rápido posible.

Por esto surge Xamarin.Forms 3.0, el cual incluye la capacidad de utilizar pantallas de Xamarin.Forms en Xamarin nativo. Esto nos proporciona muchas de las ventajas de la reutilización de Xamarin.Forms sin perder el rendimiento de Xamarin nativo.

Implementación en Android

  1. Primero crearemos un proyecto Xamarin nativo usando el template y agregaremos la versión 3.0 de Xamarin.Forms desde nuget
  2. En la PCL crearemos un ContentPage.xaml con su correspondiente fichero de código (Para el ejemplo haremos un sencillo lector RSS)
  3. Crearemos un layout con una lista para mostrar las entradas:
    <?xml version=»1.0″ encoding=»utf-8″ ?>           xmlns:x=»http://schemas.microsoft.com/winfx/2009/xaml»           x:Class=»App1.MainPage»>           BackgroundColor=»White»           ItemsSource=»{Binding Items}»>           <DataTemplate>                   <StackLayout Orientation=»Vertical»>                   </StackLayout>           </DataTemplate>   </ListView>
  4. </ContentPage>
  5.        </ListView.ItemTemplate>
  6.                </ViewCell>
  7.                        <Label Text=»{Binding Title}» FontSize=»Medium» TextColor=»Black» LineBreakMode=»NoWrap» Margin=»10,10,10,10″/>
  8.                <ViewCell>
  9.        <ListView.ItemTemplate>
  10.            ItemTapped=»listView_ItemTapped»
  11.    <ListView
  12.            BackgroundColor=»White»
  13. <ContentPage xmlns=»http://xamarin.com/schemas/2014/forms»
  14. Y después, añadiremos el código de nuestro lector RSS al código asociado al XAML que acabamos de crear:
    public partial class MainPage : ContentPage       private ObservableCollection<RssItem> _items;       public ObservableCollection<RssItem> Items           get { return _items; }                   _items = value;               }        {this.BindingContext = this;        }       private async void GetFeed()Items = new ObservableCollection<RssItem>(await GetItems(«https://stackoverflow.com/feeds/tag/xamarin-forms»));        {               {                   var doc = XDocument.Parse(xmlFeed);                                   select new RssItem                                     Title = item.Element(dc + «title»).Value,                                 });               var resultList = new List<RssItem>(items);               return resultList;       }       private void listView_ItemTapped(object sender, ItemTappedEventArgs e)           Device.OpenUri(new Uri(((RssItem)e.Item).Link));   }Además, también hemos implementado el click en los elementos que nos lanzarán al navegador para ver el post completo.
  15.       }
  16.        {
  17.                }
  18.                                      Link = item.Element(dc + «id»).Value
  19.                                  {
  20.                    var items = (from item in rawItems
  21.                    var rawItems = new List<XElement>(doc.Descendants(dc + «entry»));
  22.                    XNamespace dc = «http://www.w3.org/2005/Atom»;
  23.                    var xmlFeed = await client.GetStringAsync(feedUrl);
  24.                using (var client = new HttpClient())
  25.        public async Task<IEnumerable<RssItem>> GetItems(string feedUrl)
  26.        }
  27.        {
  28.            GetFeed();
  29.            this.Title = «StackOverflow Feed»;
  30.            InitializeComponent();
  31.        public MainPage()
  32.        }
  33.                    OnPropertyChanged(«Items»);
  34.            set {
  35.        {
  36.    {
  37. En este caso hemos utilzado un Binding para enlazar con los datos de la lista, al utilizar un ObservableCollection y OnPropertyChanged, conseguimos que la lista refleje automáticamente los cambios.
  38. A continuación, para poder ver el fragment dentro de la activity, necesitamos un contenedor. Lo añadiremos al layout que usaremos en la Activity de Android:
    <LinearLayout xmlns:android=»http://schemas.android.com/apk/res/android»   android:layout_width=»fill_parent»   > <FrameLayout     android:layout_height=»fill_parent»</LinearLayout>
  39.      android:id=»@+id/fragment_frame_layout»/>
  40.      android:layout_width=»fill_parent»
  41.    android:layout_height=»fill_parent»
  42.    android:orientation=»vertical»
  43. Una vez tenemos el layout de la activity preparado para mostrar el fragment creado por la página de Xamarin.Forms, solo nos quedan dos pasos:
  44. Iniciamos Xamarin.Forms llamando a Init()
  45. Instanciamos la página previamente creada en la PCL y utilizamos el método CreateFragment() que nos devuelve un fragment estándar de Android.
  46. Posteriormente, añadiremos el fragment al contenedor de la forma estándar de Android:
    public class MainActivity : Activity             protected override void OnCreate (Bundle bundle)                    base.OnCreate (bundle);                    SetContentView (Resource.Layout.Main);           Forms.Init(this,bundle);           var fragment = new MainPage().CreateFragment(this);            ft.Commit();       }
  47.        }
  48.            ft.Replace(Resource.Id.fragment_frame_layout, fragment, «main»);
  49.            var ft = FragmentManager.BeginTransaction();
  50.              {
  51.        {

¡Y listo!

Si lo ejecutamos podremos ver cómo aparece una pantalla simple con nuestro label y el texto que le hemos asignado en la página de Xamarin.Forms:

Implementación en iOS

Partiendo del proyecto anterior, puesto que ya tenemos creada la página de Xamarin.Forms, vamos directamente al proyecto de iOS.

El proceso es el mismo, con la única diferencia de que en lugar de un Fragment Forms, nos crea un UIViewController que es más similar al Activity en Android.

Un buen lugar para inicializar Xamarin.Forms en iOS es el método FinishedLaunching de AppDelegate , de esta manera vamos a mostrar nuestro XAML como pantalla principal:

public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)

{

Forms.Init();

 

var page = new MainPage();

 

var controller = page.CreateViewController();

 

this.Window = new UIWindow(UIScreen.MainScreen.Bounds);

 

this.Window.RootViewController = controller;

 

this.Window.MakeKeyAndVisible();

 

return true;

}

También podríamos mostrar nuestra página navegando de forma normal desde un NavigationController:

var page = new MainPage();

var controller = page.CreateViewController();

NavigationController.PushViewController(controller, true);

 

 

¡Y listo!

Ya podemos ejecutarlo:

 

 

¿Y la cabecera?

Como podéis observar, no tenemos cabecera.

Nuestro XAML ocupa totalmente la pantalla. Recordamos que en Android utilizamos un fragment que luego colocábamos en un activity que contiene una cabecera por defecto.

En el caso de iOS utilizamos un UIViewController, el cual se muestra directamente.

Teniendo en cuenta esto, tenemos varias opciones para adaptar las UI a cada plataforma. Podríamos utilizar las cabeceras nativas de cada plataforma, y el resto del contenido compartirlo, o bien hacerlo totalmente en XAML.

Además de la UI de Xamarin.Forms, actualmente también están disponibles DependencyService y MessagingCenter para utilizar en proyectos nativos.

 

¡Hasta aquí todo por hoy!

Espero que os haya servido de ayuda este post.

Y ya sabéis, si tenéis alguna duda, dejadnos un comentario abajo 😉

¡Nos vemos!