Xamarin Forms Es PDF
Xamarin Forms Es PDF
Xamarin Forms Es PDF
Forms
#xamarin.fo
rms
Tabla de contenido
Acerca de 1
Observaciones 2
Versiones 2
Examples 3
Xamarin.Formas 4
Examples 8
Observaciones 10
Examples 10
Observaciones 12
Examples 12
Implementación de iOS 13
Implementación de Android 14
Ajustes de idioma 19
Ajustes de plataforma 19
Usando estilos 20
Examples 22
Acerca de Akavache 22
Ejemplo simple 22
Manejo de errores 23
Examples 24
Observaciones 26
Examples 26
Observaciones 27
Examples 27
Importar CarouselView 27
Los basicos 28
Plantillas de datos 28
Examples 30
Compartir Plugin 30
Mapas externos 30
Plugin Geolocator 31
Plugin de medios 33
Complemento de mensajería 36
Complemento de permisos 38
Observaciones 42
Examples 42
Examples 45
Introducción 51
Examples 51
Examples 59
Observaciones 61
Examples 61
Interfaz 61
implementación de iOS 61
Código compartido 62
Implementación de Android 63
Examples 65
ContentPresenter 65
ContentView 65
Cuadro 66
ScrollView 67
Vista Templated 69
AbsoluteLayout 69
Cuadrícula 72
Disposición relativa 74
StackLayout 75
Uso en XAML 76
Uso en codigo 76
Examples 79
Multi Triggers 80
Observaciones 82
Examples 82
Introducción 87
Examples 87
Observaciones 92
Posibles excepciones 92
Examples 93
Examples 95
Requisitos de negocio 95
Clases comunes 96
Servicios 96
Pruebas 98
Pruebas de escritura 99
Observaciones 102
Examples 102
Examples 105
Examples 106
Examples 109
Haga que una imagen pueda ser ejecutada agregando un TapGestureRecognizer 109
Examples 112
Introducción 115
Examples 115
Examples 117
DisplayAlert 117
Examples 119
Page1.xaml 122
Page1.xaml.cs 122
Page2.xaml 122
Page2.xaml.cs 122
Page3.xaml 123
Page3.xaml.cs 123
Observaciones 126
Examples 126
Observaciones 130
Examples 130
Observaciones 138
Examples 138
Examples 140
Examples 142
Etiqueta redondeada con un renderizador personalizado para Frame (partes PCL e iOS) 148
Observaciones 152
Examples 152
contact_picker.cs 152
MyPage.cs 152
ChooseContactPicker.cs 153
ChooseContactActivity.cs 153
MainActivity.cs 155
ChooseContactRenderer.cs 155
Observaciones 158
Examples 158
Observaciones 159
Examples 159
Examples 172
Trabajar con bases de datos locales utilizando xamarin.forms en visual studio 2015 174
Observaciones 185
Examples 185
Sencillo flujo de especificaciones para probar los comandos y la navegación con NUnit Test 185
Uso: 185
Introducción 189
Examples 189
Examples 190
EntryCell 190
SwitchCell 190
TextCell 191
ImageCell 192
ViewCell 193
Examples 195
Botón 195
Entrada 197
Editor 198
Imagen 199
Etiqueta 200
Examples 202
TabbedPage 202
MasterDetailPage 204
Creditos 206
Acerca de
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: xamarin-forms
It is an unofficial and free Xamarin.Forms ebook created for educational purposes. All the content
is extracted from Stack Overflow Documentation, which is written by many hardworking individuals
at Stack Overflow. It is neither affiliated with Stack Overflow nor official Xamarin.Forms.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/es/home 1
Capítulo 1: Empezando con Xamarin.Forms
Observaciones
Xamarin.Forms permite crear aplicaciones de iOS, Android y Windows con grandes cantidades de
código compartido, incluido el código UI o el marcado XAML UI. Las páginas y vistas de la
aplicación se asignan a controles nativos en cada plataforma, pero se pueden personalizar para
proporcionar una IU específica de la plataforma o para acceder a funciones específicas de la
plataforma.
Versiones
2.3.1 2016-08-03
2.3.0-hotfix1 2016-06-29
2.3.0 2016-06-16
2.2.0-hotfix1 2016-05-30
2.2.0 2016-04-27
2.1.0 2016-03-13
2.0.1 2016-01-20
2.0.0 2015-11-17
1.5.1 2016-10-20
1.5.0 2016-09-25
1.4.4 2015-07-27
1.4.3 2015-06-30
1.4.2 2015-04-21
1.4.1 2015-03-30
1.4.0 2015-03-09
1.3.5 2015-03-02
1.3.4 2015-02-17
https://riptutorial.com/es/home 2
Versión Fecha de lanzamiento
1.3.3 2015-02-09
1.3.2 2015-02-03
1.3.1 2015-01-04
1.3.0 2014-12-24
1.2.3 2014-10-02
1.2.2 2014-07-30
1.2.1 2014-07-14
1.2.0 2014-07-11
1.1.1 2014-06-19
1.1.0 2014-06-12
1.0.1 2014-06-04
Examples
Instalación (Visual Studio)
Si ya tiene instalada la última versión de Visual Studio, vaya a Panel de control> Programas y
características, haga clic con el botón derecho en Visual Studio y haga clic en Cambiar. Cuando
se abra el instalador, haga clic en Modificar y seleccione las herramientas de desarrollo móvil
multiplataforma:
https://riptutorial.com/es/home 3
También puede seleccionar instalar el SDK de Android:
Desmarque si ya tiene instalado el SDK. Podrá configurar Xamarin para usar el SDK de Android
existente más adelante.
Xamarin.Formas
Xamarin.Forms es un conjunto de bibliotecas para su biblioteca de Clase portátil y ensamblajes
nativos. La biblioteca Xamarin.Forms en sí está disponible como un paquete NuGet. Para
agregarlo a su proyecto, simplemente use el comando regular Install-Package de la consola del
Administrador de paquetes:
Install-Package Xamarin.Forms
para todos sus ensamblajes iniciales (por ejemplo, MyProject, MyProject.Droid y MyProject.iOS).
La forma más fácil de comenzar con Xamarin.Forms es crear un proyecto vacío en Visual Studio:
https://riptutorial.com/es/home 4
Como puede ver, hay 2 opciones disponibles para crear la aplicación en blanco: portátil y
compartida. Te recomiendo que comiences con Portable one porque es el más usado en el
mundo real (se agregarán diferencias y más explicaciones).
Si bien las plantillas de Visual Studio Xamarin.Forms crearán un proyecto de plataforma iOS para
usted, deberá conectar Xamarin a un host de compilación Mac para poder ejecutar estos
proyectos en el simulador de iOS o en dispositivos físicos.
Después de instalar con éxito Xamarin como se describe en el primer ejemplo, es hora de iniciar
la primera aplicación de ejemplo.
https://riptutorial.com/es/home 5
Nombre la aplicación "Hello World" y seleccione la ubicación para crear el proyecto y haga clic en
Aceptar. Esto creará una solución para usted que contiene tres proyectos:
1. HelloWorld (aquí es donde se colocan su lógica y sus vistas, es decir, el proyecto portátil)
2. HelloWorld.Droid (el proyecto de Android)
3. HelloWorld.iOS (el proyecto iOS)
https://riptutorial.com/es/home 6
using Xamarin.Forms;
namespace Hello_World
{
public class App : Application
{
public App()
{
// The root page of your application
MainPage = new ContentPage
{
Content = new StackLayout
{
VerticalOptions = LayoutOptions.Center,
Children = {
new Label {
HorizontalTextAlignment = TextAlignment.Center,
Text = "Welcome to Xamarin Forms!"
}
}
}
};
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
https://riptutorial.com/es/home 7
Capítulo 2: ¿Ciclo de vida de la aplicación
Xamarin.Forms genérico? Dependiente de la
plataforma!
Examples
El ciclo de vida de Xamarin.Forms no es el ciclo de vida real de la aplicación,
sino una representación multiplataforma de la misma.
Veamos los métodos de ciclo de vida de las aplicaciones nativas para diferentes plataformas.
Androide.
iOS
Windows
https://riptutorial.com/es/home 8
//Windows.UI.Xaml.Window lifecycle methods:
public event WindowActivatedEventHandler Activated;
public event WindowClosedEventHandler Closed;
public event WindowVisibilityChangedEventHandler VisibilityChanged;
Lo que se puede ver fácilmente con solo observar las listas, la perspectiva del ciclo de vida de la
aplicación multiplataforma Xamarin.Forms se simplifica enormemente. Le da la pista genérica
sobre el estado de su aplicación, pero en la mayoría de los casos de producción tendrá que
construir alguna lógica dependiente de la plataforma.
https://riptutorial.com/es/home 9
Capítulo 3: ¿Por qué Xamarin se forma y
cuándo usar Xamarin?
Observaciones
Puede consultar la documentación oficial de Xamarin Forms para explorar más:
https://www.xamarin.com/forms
Examples
¿Por qué Xamarin se forma y cuándo usar Xamarin?
Xamarin se está volviendo más y más popular: es difícil decidir cuándo usar Xamarin.Forms y
cuándo Xamarin.Platform (por lo tanto, Xamarin.iOS y Xamarin.Android).
En primer lugar, debe saber para qué tipo de aplicaciones puede utilizar Xamarin.Forms:
2. Aplicaciones que no requieren una funcionalidad específica de la plataforma (como las API),
pero aquí, tenga en cuenta que Xamarin está trabajando para proporcionar la mayor
compatibilidad posible entre plataformas.
3. Aplicaciones donde compartir código es crucial, más importante que la interfaz de usuario.
4. Aplicaciones donde los datos mostrados son más importantes que la funcionalidad
avanzada
1. Quién será responsable del desarrollo de la aplicación: si su equipo está formado por
desarrolladores móviles con experiencia, podrán manejar Xamarin.Forms fácilmente. Pero si
tiene un desarrollador por plataforma (desarrollo nativo), los formularios pueden ser un
desafío mayor.
2. Tenga en cuenta que con Xamarin.Forms todavía puede encontrar algunos problemas: la
plataforma Xamarin.Forms aún se está mejorando.
3. El desarrollo rápido a veces es muy importante: para reducir los costos y el tiempo, puede
decidir utilizar los Formularios.
https://riptutorial.com/es/home 10
No debes usar Xamarin.Forms cuando:
1. Tienes que crear una funcionalidad personalizada y acceder a las API específicas de la
plataforma.
2. Tienes que crear una interfaz de usuario personalizada para la aplicación móvil
https://riptutorial.com/es/home 11
Capítulo 4: Acceso a funciones nativas con
DependencyService
Observaciones
Si no desea que su código se rompa cuando no se encuentra ninguna implementación, primero
verifique que DependencyService tiene una implementación disponible.
if (speaker != null)
{
speaker.Speak("Ready for action!");
}
Examples
Implementando texto a voz
Un buen ejemplo de una característica que solicita código específico de plataforma es cuando
desea implementar texto a voz (tts). Este ejemplo asume que está trabajando con código
compartido en una biblioteca PCL.
Una vista general esquemática de nuestra solución se vería como la imagen de abajo.
https://riptutorial.com/es/home 12
En nuestro código compartido definimos una interfaz que está registrada con DependencyService .
Aquí es donde haremos nuestros llamamientos. Definir una interfaz como la de abajo.
Ahora, en cada plataforma específica, necesitamos crear una implementación de esta interfaz.
Vamos a empezar con la implementación de iOS.
Implementación de iOS
using AVFoundation;
https://riptutorial.com/es/home 13
public TextToSpeechImplementation () {}
speechSynthesizer.SpeakUtterance (speechUtterance);
}
}
En el ejemplo de código anterior, observa que hay un código específico para iOS. Me gusta tipos
como AVSpeechSynthesizer . Estos no funcionarían en código compartido.
Para registrar esta implementación con el Servicio de DependencyService Xamarin, agregue este
atributo encima de la declaración de espacio de nombres.
using AVFoundation;
using DependencyServiceSample.iOS;//enables registration outside of namespace
Ahora, cuando realiza una llamada como esta en su código compartido, se inyecta la
implementación correcta para la plataforma en la que está ejecutando su aplicación.
Implementación de Android
La implementación de Android de este código se vería debajo.
using Android.Speech.Tts;
using Xamarin.Forms;
using System.Collections.Generic;
using DependencyServiceSample.Droid;
public TextToSpeechImplementation () {}
https://riptutorial.com/es/home 14
{
var ctx = Forms.Context; // useful for many Android SDK features
toSpeak = text;
if (speaker == null) {
speaker = new TextToSpeech (ctx, this);
} else {
var p = new Dictionary<string,string> ();
speaker.Speak (toSpeak, QueueMode.Flush, p);
}
}
using Android.Speech.Tts;
using Xamarin.Forms;
using System.Collections.Generic;
using DependencyServiceSample.Droid;
mediaElement.SetSource(stream, stream.ContentType);
mediaElement.Play();
await synth.SynthesizeTextToStreamAsync(text);
}
}
https://riptutorial.com/es/home 15
Y una vez más no te olvides de registrarlo.
using Windows.Media.SpeechSynthesis;
using Windows.UI.Xaml.Controls;
using DependencyServiceSample.WinPhone;//enables registration outside of namespace
En este código, verá una página que podría estar en un proyecto de Xamarin Forms. Crea un
botón que invoca el método Speak() usando el servicio DependencyService .
public MainPage ()
{
var speak = new Button {
Text = "Hello, Forms !",
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
speak.Clicked += (sender, e) => {
DependencyService.Get<ITextToSpeech>().Speak("Hello from Xamarin Forms");
};
Content = speak;
}
El resultado será que cuando se ejecute la aplicación y se haga clic en el botón, se pronunciará el
texto proporcionado.
Todo esto sin tener que hacer cosas difíciles como sugerencias del compilador y demás. Ahora
tiene una forma uniforme de acceder a la funcionalidad específica de la plataforma a través del
código independiente de la plataforma.
https://riptutorial.com/es/home 16
/// On iOS, gets the <c>CFBundleVersion</c> number and on Android, gets the
<c>PackageInfo</c>'s <c>VersionName</c>, both of which are specified in their respective
project properties.
/// </summary>
/// <returns><c>string</c>, containing the build number.</returns>
string GetAppVersion();
/// <summary>
/// On iOS, gets the <c>UIDevice.CurrentDevice.SystemVersion</c> number and on Android,
gets the <c>Build.VERSION.Release</c>.
/// </summary>
/// <returns><c>string</c>, containing the OS version number.</returns>
string GetOsVersion();
}
Androide:
[assembly: Dependency(typeof(NativeHelper_Android))]
namespace YourNamespace.Droid{
public class NativeHelper_Android : INativeHelper {
/// <summary>
/// See interface summary.
/// </summary>
public string GetAppVersion() {
Context context = Forms.Context;
return context.PackageManager.GetPackageInfo(context.PackageName, 0).VersionName;
}
/// <summary>
/// See interface summary.
/// </summary>
public string GetOsVersion() { return Build.VERSION.Release; }
}
}
iOS:
[assembly: Dependency(typeof(NativeHelper_iOS))]
namespace YourNamespace.iOS {
public class NativeHelper_iOS : INativeHelper {
/// <summary>
/// See interface summary.
/// </summary>
public string GetAppVersion() { return
Foundation.NSBundle.MainBundle.InfoDictionary[new
Foundation.NSString("CFBundleVersion")].ToString(); }
/// <summary>
/// See interface summary.
/// </summary>
public string GetOsVersion() { return UIDevice.CurrentDevice.SystemVersion; }
}
https://riptutorial.com/es/home 17
}
if(helper != null) {
string osVersion = helper.GetOsVersion();
string appVersion = helper.GetBuildNumber()
}
}
https://riptutorial.com/es/home 18
Capítulo 5: Ajustes visuales específicos de la
plataforma.
Examples
Ajustes de idioma
Se pueden realizar ajustes específicos del idioma a partir del código C #, por ejemplo, para
cambiar la orientación del diseño, ya sea que se muestre la vista o un teléfono o una tableta.
if (Device.Idiom == TargetIdiom.Phone)
{
this.panel.Orientation = StackOrientation.Vertical;
}
else
{
this.panel.Orientation = StackOrientation.Horizontal;
}
<StackLayout x:Name="panel">
<StackLayout.Orientation>
<OnIdiom x:TypeArguments="StackOrientation">
<OnIdiom.Phone>Vertical</OnIdiom.Phone>
<OnIdiom.Tablet>Horizontal</OnIdiom.Tablet>
</OnIdiom>
</StackLayout.Orientation>
</StackLayout>
Ajustes de plataforma
Se pueden hacer ajustes para plataformas específicas desde el código C #, por ejemplo, para
cambiar el relleno de todas las plataformas específicas.
if (Device.OS == TargetPlatform.iOS)
{
panel.Padding = new Thickness (10);
}
else
{
panel.Padding = new Thickness (20);
}
https://riptutorial.com/es/home 19
Esas funcionalidades también están disponibles directamente desde el código XAML:
<StackLayout x:Name="panel">
<StackLayout.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="10"
Android="20" />
</StackLayout.Padding>
</StackLayout>
Usando estilos
Al trabajar con XAML, el uso de un Style centralizado le permite actualizar un conjunto de vistas
con Style desde un solo lugar. Todos los ajustes de idioma y plataforma también se pueden
integrar a sus estilos.
<Style TargetType="StackLayout">
<Setter Property="Padding">
<Setter.Value>
<OnPlatform x:TypeArguments="Thickness"
iOS="10"
Android="20"/>
</Setter.Value>
</Setter>
</Style>
Puede crear vistas personalizadas que se pueden integrar en su página gracias a esas
herramientas de ajuste.
Seleccione File > New > File... > Forms > Forms ContentView (Xaml) y cree una vista para cada
diseño específico: TabletHome.xaml y PhoneHome.xaml .
Luego seleccione File > New > File... > Forms > Forms ContentPage HomePage.cs contenido de File
> New > File... > Forms > Forms ContentPage y cree un HomePage.cs que contenga:
using Xamarin.Forms;
}
}
https://riptutorial.com/es/home 20
Ahora tiene una página de HomePage que crea una jerarquía de vista diferente para los idiomas de
Phone y Tablet .
https://riptutorial.com/es/home 21
Capítulo 6: Almacenamiento en caché
Examples
Almacenamiento en caché utilizando Akavache
Acerca de Akavache
Akavache es una biblioteca increíblemente útil que proporciona una funcionalidad de alcance para
el almacenamiento en caché de sus datos. Akavache proporciona una interfaz de
almacenamiento de valor clave y funciona en la parte superior de SQLite3. No necesita mantener
su esquema sincronizado, ya que en realidad es una solución No-SQL que lo hace perfecto para
la mayoría de las aplicaciones móviles, especialmente si necesita que su aplicación se actualice a
menudo sin pérdida de datos.
• Necesita su aplicación para almacenar en caché los datos durante un período de tiempo
determinado (puede configurar el tiempo de espera de caducidad para cada entidad que se
está guardando;
• Quieres que tu aplicación funcione sin conexión;
• Es difícil determinar y congelar el esquema de sus datos. Por ejemplo, tienes listas que
contienen diferentes objetos escritos;
• Es suficiente para que tenga un simple acceso de valor clave a los datos y no necesita
hacer consultas complejas.
Akavache no es una "bala de plata" para el almacenamiento de datos, así que piense dos veces
antes de usarlo en los siguientes casos:
En realidad, puede migrar manualmente sus datos con solo leerlos y escribirlos con
campos actualizados.
https://riptutorial.com/es/home 22
Ejemplo simple
La interacción con Akavache se realiza principalmente a través de un objeto llamado BlobCache .
La mayoría de los métodos de Akavache devuelven observables reactivos, pero también puede
esperarlos gracias a los métodos de extensión.
// Make sure you set the application name before doing any inserts or gets
BlobCache.ApplicationName = "AkavacheExperiment";
//
// ...later, in another part of town...
//
// Using async/await
var toaster = await BlobCache.UserAccount.GetObject<Toaster>("toaster");
// or without async/await
Toaster toaster;
BlobCache.UserAccount.GetObject<Toaster>("toaster")
.Subscribe(x => toaster = x, ex => Console.WriteLine("No Key!"));
Manejo de errores
Toaster toaster;
try {
toaster = await BlobCache.UserAccount.GetObjectAsync("toaster");
} catch (KeyNotFoundException ex) {
toaster = new Toaster();
}
// Or without async/await:
toaster = await BlobCache.UserAccount.GetObjectAsync<Toaster>("toaster")
.Catch(Observable.Return(new Toaster()));
https://riptutorial.com/es/home 23
Capítulo 7: AppSettings Reader en
Xamarin.Forms
Examples
Leyendo el archivo app.config en un proyecto Xamarin.Forms Xaml
Si bien cada plataforma móvil ofrece su propia API de administración de configuraciones, no hay
formas integradas de leer configuraciones desde un buen archivo antiguo de .NET estilo
app.config xml; Esto se debe a una serie de buenas razones, en particular la api de
administración de configuración de .net framework en el lado pesado, y cada plataforma tiene su
propia api de sistema de archivos.
Así que construimos una biblioteca PCLAppConfig simple, bien empaquetada en nuget para su
consumo inmediato.
En este ejemplo, se supone que está desarrollando un proyecto Xamarin.Forms Xaml, en el que
tendría que acceder a la configuración desde su modelo de vista compartido.
iOS (AppDelegate.cs)
global::Xamarin.Forms.Forms.Init();
ConfigurationManager.Initialise(PCLAppConfig.FileSystemStream.PortableStream.Current);
LoadApplication(new App());
Android (MainActivity.cs)
global::Xamarin.Forms.Forms.Init(this, bundle);
ConfigurationManager.Initialise(PCLAppConfig.FileSystemStream.PortableStream.Current);
LoadApplication(new App());
Xamarin.Forms.Forms.Init(e);
ConfigurationManager.Initialise(PCLAppConfig.FileSystemStream.PortableStream.Current);
<configuration>
<appSettings>
https://riptutorial.com/es/home 24
<add key="config.text" value="hello from app.settings!" />
</appSettings>
</configuration>
3. Agregue este archivo PCL app.config como un archivo vinculado en todos sus proyectos
de plataforma. Para Android, asegúrese de configurar la acción de compilación en
'AndroidAsset' , para UWP configure la acción de compilación en 'Contenido'
https://riptutorial.com/es/home 25
Capítulo 8: Base de datos SQL y API en
Xamarin Forms.
Observaciones
Crea tu propia api con la base de datos Microsoft SQL y implícalos en la aplicación de formularios
Xamarin.
Examples
Crear API utilizando la base de datos SQL e implementar en formularios
Xamarin,
https://riptutorial.com/es/home 26
Capítulo 9: CarouselView - Versión de
prelanzamiento
Observaciones
CarouselView es un control de Xamarin que puede contener cualquier tipo de vista. Este control
previo al lanzamiento solo se puede usar en proyectos de Xamarin Forms.
En este momento, CarouselView no está integrado en Xamarin.Forms. Para usar esto en su (s)
proyecto (s), tendrá que agregar el paquete NuGet (vea el ejemplo anterior).
Examples
Importar CarouselView
https://riptutorial.com/es/home 27
https://riptutorial.com/es/home 28
https://riptutorial.com/es/xamarin-forms/topic/6094/carouselview---version-de-prelanzamiento
https://riptutorial.com/es/home 29
Capítulo 10: Complemento Xamarin
Examples
Compartir Plugin
Una forma sencilla de compartir un mensaje o enlace, copiar texto al portapapeles o abrir un
navegador en cualquier aplicación de Xamarin o Windows.
XAML
</StackLayout>
DO#
Mapas externos
Complemento de mapas externos Abra los mapas externos para navegar a una geolocalización o
dirección específica. Opción para iniciar con la opción de navegación en iOS también.
XAML
https://riptutorial.com/es/home 30
<Button x:Name="navigateAddress" Text="Navigate to Address"/>
<Button x:Name="navigateLatLong" Text="Navigate to Lat|Long"/>
<Label Text=""/>
</StackLayout>
Código
namespace PluginDemo
{
public partial class ExternalMaps : ContentPage
{
public ExternalMaps()
{
InitializeComponent();
navigateLatLong.Clicked += (sender, args) =>
{
CrossExternalMaps.Current.NavigateTo("Space Needle", 47.6204, -122.3491);
};
Plugin Geolocator
XAML
</StackLayout>
Código
namespace PluginDemo
{
public partial class GeolocatorPage : ContentPage
{
public GeolocatorPage()
{
InitializeComponent();
buttonGetGPS.Clicked += async (sender, args) =>
https://riptutorial.com/es/home 31
{
try
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 1000;
labelGPS.Text = "Getting gps";
if (position == null)
{
labelGPS.Text = "null gps :(";
return;
}
labelGPS.Text = string.Format("Time: {0} \nLat: {1} \nLong: {2}
\nAltitude: {3} \nAltitude Accuracy: {4} \nAccuracy: {5} \nHeading: {6} \nSpeed: {7}",
position.Timestamp, position.Latitude, position.Longitude,
position.Altitude, position.AltitudeAccuracy, position.Accuracy,
position.Heading, position.Speed);
}
catch //(Exception ex)
{
// Xamarin.Insights.Report(ex);
// await DisplayAlert("Uh oh", "Something went wrong, but don't worry we
captured it in Xamarin Insights! Thanks.", "OK");
}
};
https://riptutorial.com/es/home 32
{
CrossGeolocator.Current.PositionChanged +=
CrossGeolocator_Current_PositionChanged;
CrossGeolocator.Current.PositionError +=
CrossGeolocator_Current_PositionError;
}
catch
{
}
}
Plugin de medios
XAML
https://riptutorial.com/es/home 33
<Button x:Name="pickPhoto" Text="Pick Photo"/>
<Button x:Name="takeVideo" Text="Take Video"/>
<Button x:Name="pickVideo" Text="Pick Video"/>
<Label Text="Save to Gallery"/>
<Switch x:Name="saveToGallery" IsToggled="false" HorizontalOptions="Center"/>
<Label Text="Image will show here"/>
<Image x:Name="image"/>
<Label Text=""/>
</StackLayout>
Código
namespace PluginDemo
{
public partial class MediaPage : ContentPage
{
public MediaPage()
{
InitializeComponent();
takePhoto.Clicked += async (sender, args) =>
{
if (!CrossMedia.Current.IsCameraAvailable ||
!CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("No Camera", ":( No camera avaialble.", "OK");
return;
}
try
{
var file = await CrossMedia.Current.TakePhotoAsync(new
Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "Sample",
Name = "test.jpg",
SaveToAlbum = saveToGallery.IsToggled
});
if (file == null)
return;
https://riptutorial.com/es/home 34
pickPhoto.Clicked += async (sender, args) =>
{
if (!CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert("Photos Not Supported", ":( Permission not granted to
photos.", "OK");
return;
}
try
{
Stream stream = null;
var file = await CrossMedia.Current.PickPhotoAsync().ConfigureAwait(true);
if (file == null)
return;
stream = file.GetStream();
file.Dispose();
}
catch //(Exception ex)
{
// Xamarin.Insights.Report(ex);
// await DisplayAlert("Uh oh", "Something went wrong, but don't worry we
captured it in Xamarin Insights! Thanks.", "OK");
}
};
try
{
var file = await CrossMedia.Current.TakeVideoAsync(new
Plugin.Media.Abstractions.StoreVideoOptions
{
Name = "video.mp4",
Directory = "DefaultVideos",
SaveToAlbum = saveToGallery.IsToggled
});
if (file == null)
return;
file.Dispose();
}
catch //(Exception ex)
{
https://riptutorial.com/es/home 35
// Xamarin.Insights.Report(ex);
// await DisplayAlert("Uh oh", "Something went wrong, but don't worry we
captured it in Xamarin Insights! Thanks.", "OK");
}
};
if (file == null)
return;
}
catch //(Exception ex)
{
//Xamarin.Insights.Report(ex);
//await DisplayAlert("Uh oh", "Something went wrong, but don't worry we
captured it in Xamarin Insights! Thanks.", "OK");
}
};
}
}
}
Complemento de mensajería
Complemento de mensajería para Xamarin y Windows para hacer una llamada telefónica, enviar
un SMS o enviar un correo electrónico utilizando las aplicaciones de mensajería predeterminadas
en las diferentes plataformas móviles.
XAML
</StackLayout>
Código
https://riptutorial.com/es/home 36
namespace PluginDemo
{
public partial class MessagingPage : ContentPage
{
public MessagingPage()
{
InitializeComponent();
buttonCall.Clicked += async (sender, e) =>
{
try
{
// Make Phone Call
var phoneCallTask = MessagingPlugin.PhoneDialer;
if (phoneCallTask.CanMakePhoneCall)
phoneCallTask.MakePhoneCall(phone.Text);
else
await DisplayAlert("Error", "This device can't place calls", "OK");
}
catch
{
// await DisplayAlert("Error", "Unable to perform action", "OK");
}
};
https://riptutorial.com/es/home 37
Complemento de permisos
Compruebe si sus usuarios han otorgado o denegado permisos para grupos de permisos
comunes en iOS y Android.
Además, puede solicitar permisos con una simple API async / awaitified multiplataforma.
XAML
</StackLayout>
Código
bool busy;
async void ButtonPermission_OnClicked(object sender, EventArgs e)
{
if (busy)
return;
busy = true;
((Button)sender).IsEnabled = false;
https://riptutorial.com/es/home 38
CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Contacts);
break;
case "Microphone":
status = await
CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Microphone);
break;
case "Phone":
status = await
CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Phone);
break;
case "Photos":
status = await
CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Photos);
break;
case "Reminders":
status = await
CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Reminders);
break;
case "Sensors":
status = await
CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Sensors);
break;
case "Sms":
status = await
CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Sms);
break;
case "Storage":
status = await
CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
break;
}
if (status != PermissionStatus.Granted)
{
switch (((Button)sender).StyleId)
{
case "Calendar":
status = (await
CrossPermissions.Current.RequestPermissionsAsync(Permission.Calendar))[Permission.Calendar];
break;
case "Camera":
status = (await
CrossPermissions.Current.RequestPermissionsAsync(Permission.Camera))[Permission.Camera];
break;
case "Contacts":
status = (await
CrossPermissions.Current.RequestPermissionsAsync(Permission.Contacts))[Permission.Contacts];
break;
case "Microphone":
status = (await
CrossPermissions.Current.RequestPermissionsAsync(Permission.Microphone))[Permission.Microphone];
break;
case "Phone":
status = (await
CrossPermissions.Current.RequestPermissionsAsync(Permission.Phone))[Permission.Phone];
break;
case "Photos":
status = (await
https://riptutorial.com/es/home 39
CrossPermissions.Current.RequestPermissionsAsync(Permission.Photos))[Permission.Photos];
break;
case "Reminders":
status = (await
CrossPermissions.Current.RequestPermissionsAsync(Permission.Reminders))[Permission.Reminders];
break;
case "Sensors":
status = (await
CrossPermissions.Current.RequestPermissionsAsync(Permission.Sensors))[Permission.Sensors];
break;
case "Sms":
status = (await
CrossPermissions.Current.RequestPermissionsAsync(Permission.Sms))[Permission.Sms];
break;
case "Storage":
status = (await
CrossPermissions.Current.RequestPermissionsAsync(Permission.Storage))[Permission.Storage];
break;
}
busy = false;
((Button)sender).IsEnabled = true;
}
busy = true;
((Button)sender).IsEnabled = false;
try
{
var status = await
CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Location);
if (status != PermissionStatus.Granted)
{
if (await
CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Location))
{
await DisplayAlert("Need location", "Gunna need that location", "OK");
}
if (status == PermissionStatus.Granted)
{
var results = await CrossGeolocator.Current.GetPositionAsync(10000);
LabelGeolocation.Text = "Lat: " + results.Latitude + " Long: " +
results.Longitude;
}
else if (status != PermissionStatus.Unknown)
{
https://riptutorial.com/es/home 40
await DisplayAlert("Location Denied", "Can not continue, try again.",
"OK");
}
}
catch (Exception ex)
{
((Button)sender).IsEnabled = true;
busy = false;
}
https://riptutorial.com/es/home 41
Capítulo 11: Comportamiento específico de la
plataforma
Observaciones
Plataformas de destino
if(Device.OS == TargetPlatform.Android)
{
}
else if (Device.OS == TargetPlatform.iOS)
{
}
else if (Device.OS == TargetPlatform.WinPhone)
{
}
else if (Device.OS == TargetPlatform.Windows)
{
}
else if (Device.OS == TargetPlatform.Other)
{
Examples
Eliminando el icono en el encabezado de navegación en Anroid
https://riptutorial.com/es/home 42
Usando una pequeña imagen transparente llamada empty.png
https://riptutorial.com/es/home 43
label.FontSize = label.FontSize - 2;
}
https://riptutorial.com/es/home 44
Capítulo 12: Creando controles
personalizados
Examples
Cree un control de entrada personalizado de Xamarin Forms (no se requiere
nativo)
El control personalizado es un ContentView con una Label , Entry y un BoxView dentro de él, que se
mantiene en su lugar utilizando 2 StackLayout s. También definimos múltiples propiedades
TextChanged así como un evento TextChanged .
#region Properties
/// <summary>
/// Attached to the <c>InputFieldContentView</c>'s <c>ExtendedEntryOnTextChanged()</c>
event, but returns the <c>sender</c> as <c>InputFieldContentView</c>.
/// </summary>
public event System.EventHandler<TextChangedEventArgs> OnContentViewTextChangedEvent; //In
OnContentViewTextChangedEvent() we return our custom InputFieldContentView control as the
sender but we could have returned the Entry itself as the sender if we wanted to do that
instead.
https://riptutorial.com/es/home 45
get { return (Color)GetValue(LabelColorProperty); }
set { SetValue(LabelColorProperty, value); }
}
#endregion
public InputFieldContentView() {
BackgroundColor = Color.Transparent;
HorizontalOptions = LayoutOptions.FillAndExpand;
https://riptutorial.com/es/home 46
entry.SetBinding(Entry.TextProperty, (InputFieldContentView view) => view.EntryText,
BindingMode.TwoWay);
entry.TextChanged += OnTextChangedEvent;
Y aquí hay una imagen del producto final en iOS (la imagen muestra cómo se ve cuando se usa
un renderizador personalizado para la Label y Entry que se usa para eliminar el borde en iOS y
para especificar una fuente personalizada para ambos elementos):
https://riptutorial.com/es/home 47
Etiqueta con colección enlazable de Spans
Creé una etiqueta personalizada con una envoltura alrededor de la propiedad FormattedText :
public MultiComponentLabel()
{
var components = new ObservableCollection<TextComponent>();
components.CollectionChanged += OnComponentsChanged;
Components = components;
}
FormattedText = formattedString;
}
}
https://riptutorial.com/es/home 48
componentes separados, reconstruyo la propiedad FormattedText de la Label base.
<ContentPage x:Name="Page"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:SuperForms.Controls;assembly=SuperForms.Controls"
x:Class="SuperForms.Samples.MultiComponentLabelPage">
<controls:MultiComponentLabel Margin="0,20,0,0">
<controls:MultiComponentLabel.Components>
<controls:TextComponent Text="Time"/>
<controls:TextComponent Text=": "/>
<controls:TextComponent Text="{Binding CurrentTime, Source={x:Reference Page}}"/>
</controls:MultiComponentLabel.Components>
</controls:MultiComponentLabel>
</ContentPage>
Código de página:
public MultiComponentLabelPage()
{
InitializeComponent();
BindingContext = this;
}
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
CurrentTime = DateTime.Now.ToString("hh : mm : ss");
return true;
});
}
}
El control de Entry formularios Xamarin no tiene una propiedad MaxLength . Para lograr esto, puede
extender la Entry como se muestra a continuación, agregando una propiedad de Bindable
MaxLength . Luego, solo debe suscribirse al evento TextChanged en la Entry y validar la longitud del
https://riptutorial.com/es/home 49
Text cuando se llame:
if (string.IsNullOrEmpty(val))
return;
e.Text = val;
}
}
Uso en XAML:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:customControls="clr-namespace:CustomControls;assembly=CustomControls"
x:Class="Views.TestView">
<ContentView.Content>
<customControls:CustomEntry MaxLength="10" />
</ContentView.Content>
https://riptutorial.com/es/home 50
Capítulo 13: Creando controles
personalizados
Introducción
Cada vista de Xamarin.Forms tiene un renderizador que acompaña a cada plataforma que crea una
instancia de un control nativo. Cuando una Vista se representa en la plataforma específica, se
ViewRenderer una instancia de la clase ViewRenderer .
Examples
Implementando un Control CheckBox
En este ejemplo, implementaremos una casilla de verificación personalizada para Android e iOS.
namespace CheckBoxCustomRendererExample
{
public class Checkbox : View
{
public static readonly BindableProperty IsCheckedProperty =
BindableProperty.Create<Checkbox, bool>(p => p.IsChecked, true, propertyChanged: (s, o, n) =>
{ (s as Checkbox).OnChecked(new EventArgs()); });
public static readonly BindableProperty ColorProperty =
BindableProperty.Create<Checkbox, Color>(p => p.Color, Color.Default);
https://riptutorial.com/es/home 51
get
{
return (Color)GetValue(ColorProperty);
}
set
{
SetValue(ColorProperty, value);
}
}
• Necesitamos marcar la parte superior de nuestra clase con el atributo ExportRenderer para
que el renderizador se registre con Xamarin.Forms . De esta manera, Xamarin.Forms usará este
renderizador cuando intente crear nuestro objeto Checkbox en Android .
• Estamos haciendo la mayor parte de nuestro trabajo en el método OnElementChanged , donde
instanciamos y configuramos nuestro control nativo.
https://riptutorial.com/es/home 52
Xamarin.Forms correspondiente.
3. Agregue un atributo ExportRenderer a la clase de renderizador personalizado para especificar
que se usará para renderizar el control personalizado Xamarin.Forms . Este atributo se utiliza
para registrar el renderizador personalizado con Xamarin.Forms .
}
}
https://riptutorial.com/es/home 53
base.OnElementPropertyChanged(sender, e);
CheckboxPropertyChanged((Checkbox)sender, e.PropertyName);
}
}
La vista CheckBox:
namespace CheckBoxCustomRendererExample.iOS
{
[Register("CheckBoxView")]
public class CheckBoxView : UIButton
{
public CheckBoxView()
{
Initialize();
}
https://riptutorial.com/es/home 54
{
set
{
SetTitle(value, UIControlState.Normal);
}
}
void Initialize()
{
ApplyStyle();
void ApplyStyle()
{
SetImage(UIImage.FromBundle("Images/checked_checkbox.png"),
UIControlState.Selected);
SetImage(UIImage.FromBundle("Images/unchecked_checkbox.png"),
UIControlState.Normal);
}
}
}
/// <summary>
/// Handles the Element Changed event
/// </summary>
/// <param name="e">The e.</param>
protected override void OnElementChanged(ElementChangedEventArgs<Checkbox> e)
{
base.OnElementChanged(e);
if (Element == null)
return;
BackgroundColor = Element.BackgroundColor.ToUIColor();
if (e.NewElement != null)
{
if (Control == null)
{
var checkBox = new CheckBoxView(Bounds);
checkBox.TouchUpInside += (s, args) => Element.IsChecked =
Control.Checked;
https://riptutorial.com/es/home 55
SetNativeControl(checkBox);
}
Control.Checked = e.NewElement.IsChecked;
}
Control.Frame = Frame;
Control.Bounds = Bounds;
/// <summary>
/// Handles the <see cref="E:ElementPropertyChanged" /> event.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the
event data.</param>
protected override void OnElementPropertyChanged(object sender,
PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName.Equals("Checked"))
{
Control.Checked = Element.IsChecked;
}
}
}
}
Resultado:
https://riptutorial.com/es/home 56
https://riptutorial.com/es/home 57
Lea Creando controles personalizados en línea: https://riptutorial.com/es/xamarin-
forms/topic/5975/creando-controles-personalizados
https://riptutorial.com/es/home 58
Capítulo 14: Creando controles
personalizados
Examples
Creando un botón personalizado
/// <summary>
/// Button with some additional options
/// </summary>
public class TurboButton : Button
{
public static readonly BindableProperty StringDataProperty = BindableProperty.Create(
propertyName: "StringData",
returnType: typeof(string),
declaringType: typeof(ButtonWithStorage),
defaultValue: default(string));
/// <summary>
/// You can put here some string data
/// </summary>
public string StringData
{
get { return (string)GetValue(StringDataProperty); }
set { SetValue(StringDataProperty, value); }
}
/// <summary>
/// You can put here some int data
/// </summary>
public int IntData
{
get { return (int)GetValue(IntDataProperty); }
set { SetValue(IntDataProperty, value); }
}
public TurboButton()
{
PropertyChanged += CheckIfPropertyLoaded;
}
/// <summary>
/// Called when one of properties is changed
/// </summary>
private void CheckIfPropertyLoaded(object sender, PropertyChangedEventArgs e)
{
//example of using PropertyChanged
if(e.PropertyName == "IntData")
{
https://riptutorial.com/es/home 59
//IntData is now changed, you can operate on updated value
}
}
}
Uso en XAML:
exampleControl.IntData
Tenga en cuenta que debe especificar dónde se ubica su clase TurboButton en su proyecto. Lo
he hecho en esta línea:
xmlns:customControls="clr-namespace:SomeApp.CustomControls;assembly=SomeApp"
Puedes cambiar libremente "customControls" a otro nombre. Depende de usted cómo lo llamará.
https://riptutorial.com/es/home 60
Capítulo 15: DependenciaServicio
Observaciones
Cuando usa DependencyService , normalmente necesita 3 partes:
Al utilizar DependencyService , debe proporcionar una implementación para cada plataforma que
elija. Cuando no se proporciona una implementación, la aplicación fallará en el tiempo de
ejecución.
Examples
Interfaz
Como definimos nuestra interfaz, podemos codificar contra ella desde nuestro código compartido.
Nota: Las clases que implementan la interfaz deben tener un constructor sin parámetros para
trabajar con DependencyService .
implementación de iOS
La interfaz que definió debe implementarse en cada plataforma específica. Para iOS esto se hace
a través del marco AVFoundation . La siguiente implementación de la interfaz ITextToSpeech maneja
hablar un texto dado en inglés.
using AVFoundation;
https://riptutorial.com/es/home 61
public void Speak (string whatToSay)
{
var speechSynthesizer = new AVSpeechSynthesizer ();
speechSynthesizer.SpeakUtterance (speechUtterance);
}
}
Cuando haya creado su clase, debe permitir que DependencyService descubra en tiempo de
ejecución. Esto se hace agregando un atributo [assembly] encima de la definición de clase y fuera
de cualquier definición de espacio de nombres.
using AVFoundation;
using DependencyServiceSample.iOS;
Este atributo registra la clase con DependencyService para que pueda usarse cuando se necesita
una instancia de la interfaz ITextToSpeech .
Código compartido
Una vez que haya creado y registrado sus clases específicas de la plataforma, puede comenzar a
conectarlas a su código compartido. La siguiente página contiene un botón que activa la
funcionalidad de texto a voz usando una oración predefinida. Utiliza DependencyService para
recuperar una implementación específica de la ITextToSpeech de ITextToSpeech en tiempo de
ejecución utilizando los SDK nativos.
public MainPage ()
{
var speakButton = new Button {
Text = "Talk to me baby!",
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
Content = speakButton;
}
https://riptutorial.com/es/home 62
Cuando ejecute esta aplicación en un dispositivo iOS o Android y toque el botón, escuchará que
la aplicación dice la oración dada.
Implementación de Android
using Android.Speech.Tts;
using Xamarin.Forms;
using System.Collections.Generic;
using DependencyServiceSample.Droid;
public TextToSpeechAndroid () {}
if (_speaker == null)
{
_speaker = new TextToSpeech (ctx, this);
}
else
{
var p = new Dictionary<string,string> ();
_speaker.Speak (whatToSay, QueueMode.Flush, p);
}
}
#endregion
}
Cuando haya creado su clase, debe permitir que DependencyService descubra en tiempo de
ejecución. Esto se hace agregando un atributo [assembly] encima de la definición de clase y fuera
de cualquier definición de espacio de nombres.
https://riptutorial.com/es/home 63
using Android.Speech.Tts;
using Xamarin.Forms;
using System.Collections.Generic;
using DependencyServiceSample.Droid;
Este atributo registra la clase con DependencyService para que pueda usarse cuando se necesita
una instancia de la interfaz ITextToSpeech .
https://riptutorial.com/es/home 64
Capítulo 16: Diseños de formas de Xamarin
Examples
ContentPresenter
Un gestor de diseño para vistas templadas. Se utiliza dentro de un ControlTemplate para marcar
donde aparece el contenido que se presentará.
ContentView
Un elemento con un solo contenido. ContentView tiene muy poco uso propio. Su propósito es
servir como una clase base para vistas compuestas definidas por el usuario.
https://riptutorial.com/es/home 65
XAML
<ContentView>
<Label Text="Hi, I'm a simple Label inside of a simple ContentView"
HorizontalOptions="Center"
VerticalOptions="Center"/>
</ContentView>
Código
Cuadro
Un elemento que contiene un solo hijo, con algunas opciones de encuadre. Frame tiene un
Xamarin.Forms.Layout.Padding predeterminado de 20.
https://riptutorial.com/es/home 66
XAML
<Frame>
<Label Text="I've been framed!"
HorizontalOptions="Center"
VerticalOptions="Center" />
</Frame>
Código
ScrollView
https://riptutorial.com/es/home 67
cuando se muestra el teclado.
Nota: ScrollViews no debe estar anidado. Además, ScrollViews no debe estar anidado con otros
controles que proporcionen desplazamiento, como ListView y WebView .
<ContentPage.Content>
<ScrollView>
<StackLayout>
<BoxView BackgroundColor="Red" HeightRequest="600" WidthRequest="150" />
<Entry />
</StackLayout>
</ScrollView>
</ContentPage.Content>
https://riptutorial.com/es/home 68
Vista Templated
Un elemento que muestra contenido con una plantilla de control y la clase base para ContentView .
AbsoluteLayout
https://riptutorial.com/es/home 69
Una definición de un AbsoluteLayout en XAML se ve así:
<AbsoluteLayout>
<Label Text="I'm centered on iPhone 4 but no other device"
AbsoluteLayout.LayoutBounds="115,150,100,100" LineBreakMode="WordWrap" />
<Label Text="I'm bottom center on every device."
AbsoluteLayout.LayoutBounds=".5,1,.5,.1" AbsoluteLayout.LayoutFlags="All"
LineBreakMode="WordWrap" />
<BoxView Color="Olive" AbsoluteLayout.LayoutBounds="1,.5, 25, 100"
AbsoluteLayout.LayoutFlags="PositionProportional" />
<BoxView Color="Red" AbsoluteLayout.LayoutBounds="0,.5,25,100"
AbsoluteLayout.LayoutFlags="PositionProportional" />
<BoxView Color="Blue" AbsoluteLayout.LayoutBounds=".5,0,100,25"
AbsoluteLayout.LayoutFlags="PositionProportional" />
<BoxView Color="Blue" AbsoluteLayout.LayoutBounds=".5,0,1,25"
AbsoluteLayout.LayoutFlags="PositionProportional, WidthProportional" />
</AbsoluteLayout>
https://riptutorial.com/es/home 70
AbsoluteLayout.SetLayoutBounds (centerLabel, new Rectangle (115, 159, 100, 100));
// No need to set layout flags, absolute positioning is the default
var bottomLabel = new Label { Text = "I'm bottom center on every device.", LineBreakMode =
LineBreakMode.WordWrap };
AbsoluteLayout.SetLayoutBounds (bottomLabel, new Rectangle (.5, 1, .5, .1));
AbsoluteLayout.SetLayoutFlags (bottomLabel, AbsoluteLayoutFlags.All);
layout.Children.Add (bottomLabel);
layout.Children.Add (centerLabel);
layout.Children.Add (rightBox);
layout.Children.Add (leftBox);
layout.Children.Add (topBox);
Hay algunas maneras diferentes de establecer los límites de los elementos secundarios en
función de la enumeración AbsoluteLayoutFlags que se utilizan durante este proceso. La
enumeración AbsoluteLayoutFlags contiene los siguientes valores:
El proceso de trabajar con el diseño del contenedor AbsoluteLayout puede parecer un poco
contradictorio al principio, pero con un poco de uso se volverá familiar. Una vez que haya creado
los elementos secundarios, para establecerlos en una posición absoluta dentro del contenedor,
deberá seguir tres pasos. Deseará establecer los indicadores asignados a los elementos
utilizando el método AbsoluteLayout.SetLayoutFlags () . También querrá usar el método
AbsoluteLayout.SetLayoutBounds () para dar a los elementos sus límites. Finalmente, querrá
agregar los elementos secundarios a la colección Children. Como Xamarin.Forms es una capa de
https://riptutorial.com/es/home 71
abstracción entre Xamarin y las implementaciones específicas del dispositivo, los valores
posicionales pueden ser independientes de los píxeles del dispositivo. Aquí es donde las
banderas de diseño mencionadas anteriormente entran en juego. Puede elegir cómo el proceso
de diseño de los controles de Xamarin.Forms debe interpretar los valores que define.
Cuadrícula
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="*" />
<RowDefinition Height="200" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
https://riptutorial.com/es/home 72
<ContentView Grid.Row="0" Grid.Column="1"/>
<ContentView Grid.Row="1" Grid.Column="1"/>
<ContentView Grid.Row="2" Grid.Column="1"/>
</Grid>
<Grid>
<--DEFINITIONS...--!>
</Grid>
En el código C #:
https://riptutorial.com/es/home 73
Nota: Los valores de ancho de las columnas se establecen como Auto de forma predeterminada
en Xamarin.Forms, lo que significa que el ancho se determina a partir del tamaño de los
elementos secundarios. Tenga en cuenta que esto difiere de la implementación de XAML en las
plataformas de Microsoft, donde el ancho predeterminado es *, que llenará el espacio disponible.
Disposición relativa
RelativeLayout se usa para posicionar y ajustar el tamaño de las vistas en relación con las
propiedades del diseño o las vistas de hermanos. A diferencia de AbsoluteLayout , RelativeLayout
no tiene el concepto de ancla móvil y no tiene facilidades para posicionar elementos en relación
con los bordes inferior o derecho del diseño. RelativeLayout admite elementos de posicionamiento
fuera de sus propios límites.
<RelativeLayout>
<BoxView Color="Red" x:Name="redBox"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,Factor=.15,Constant=0}"
RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Width,Factor=1,Constant=0}"
RelativeLayout.HeightConstraint="{ConstraintExpression
https://riptutorial.com/es/home 74
Type=RelativeToParent,Property=Height,Factor=.8,Constant=0}" />
<BoxView Color="Blue"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToView,
ElementName=redBox,Property=Y,Factor=1,Constant=20}"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToView,
ElementName=redBox,Property=X,Factor=1,Constant=20}"
RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Width,Factor=.5,Constant=0}"
RelativeLayout.HeightConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Height,Factor=.5,Constant=0}" />
</RelativeLayout>
StackLayout
StackLayout organiza las vistas en una línea unidimensional ("stack"), ya sea horizontal o
verticalmente. Views en un StackLayout se pueden dimensionar según el espacio en el diseño
utilizando las opciones de diseño. El posicionamiento está determinado por el orden en que se
agregaron las vistas al diseño y las opciones de diseño de las vistas.
https://riptutorial.com/es/home 75
Uso en XAML
<StackLayout>
<Label Text="This will be on top" />
<Button Text="This will be on the bottom" />
</StackLayout>
Uso en codigo
StackLayout stackLayout = new StackLayout
{
Spacing = 0,
VerticalOptions = LayoutOptions.FillAndExpand,
Children =
{
new Label
{
Text = "StackLayout",
HorizontalOptions = LayoutOptions.Start
},
new Label
{
Text = "stacks its children",
https://riptutorial.com/es/home 76
HorizontalOptions = LayoutOptions.Center
},
new Label
{
Text = "vertically",
HorizontalOptions = LayoutOptions.End
},
new Label
{
Text = "by default,",
HorizontalOptions = LayoutOptions.Center
},
new Label
{
Text = "but horizontal placement",
HorizontalOptions = LayoutOptions.Start
},
new Label
{
Text = "can be controlled with",
HorizontalOptions = LayoutOptions.Center
},
new Label
{
Text = "the HorizontalOptions property.",
HorizontalOptions = LayoutOptions.End
},
new Label
{
Text = "An Expand option allows one or more children " +
"to occupy the an area within the remaining " +
"space of the StackLayout after it's been sized " +
"to the height of its parent.",
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.End
},
new StackLayout
{
Spacing = 0,
Orientation = StackOrientation.Horizontal,
Children =
{
new Label
{
Text = "Stacking",
},
new Label
{
Text = "can also be",
HorizontalOptions = LayoutOptions.CenterAndExpand
},
new Label
{
Text = "horizontal.",
},
}
}
}
};
https://riptutorial.com/es/home 77
forms/topic/6273/disenos-de-formas-de-xamarin
https://riptutorial.com/es/home 78
Capítulo 17: Disparadores y
comportamientos
Examples
Ejemplo de Trigger de Formas Xamarin
Trigger son una forma fácil de agregar cierta capacidad de respuesta de UX a su aplicación. Una
manera fácil de hacer esto es agregar un Trigger que cambie el TextColor del TextColor una Label
en función de si su Entry relacionada tiene texto ingresado o no.
El uso de un Trigger para esto permite que Label.TextColor cambie de gris (cuando no se ingresa
texto) a negro (tan pronto como los usuarios ingresan texto):
Convertidor (a cada convertidor se le asigna una variable de Instance que se usa en el enlace
para que no se cree una nueva instancia de la clase cada vez que se usa):
/// <summary>
/// Used in a XAML trigger to return <c>true</c> or <c>false</c> based on the length of
<c>value</c>.
/// </summary>
public class LengthTriggerConverter : Xamarin.Forms.IValueConverter {
/// <summary>
/// Used so that a new instance is not created every time this converter is used in the
XAML code.
/// </summary>
public static LengthTriggerConverter Instance = new LengthTriggerConverter();
/// <summary>
/// If a `ConverterParameter` is passed in, a check to see if <c>value</c> is greater than
<c>parameter</c> is made. Otherwise, a check to see if <c>value</c> is over 0 is made.
/// </summary>
/// <param name="value">The length of the text from an Entry/Label/etc.</param>
/// <param name="targetType">The Type of object/control that the text/value is coming
from.</param>
/// <param name="parameter">Optional, specify what length to test against (example: for 3
Letter Name, we would choose 2, since the 3 Letter Name Entry needs to be over 2 characters),
if not specified, defaults to 0.</param>
/// <param name="culture">The current culture set in the device.</param>
/// <returns><c>object</c>, which is a <c>bool</c> (<c>true</c> if <c>value</c> is greater
than 0 (or is greater than the parameter), <c>false</c> if not).</returns>
public object Convert(object value, System.Type targetType, object parameter, CultureInfo
culture) { return DoWork(value, parameter); }
public object ConvertBack(object value, System.Type targetType, object parameter,
CultureInfo culture) { return DoWork(value, parameter); }
if(parameter != null) { //If param was specified, convert and use it, otherwise, 0 is
used
https://riptutorial.com/es/home 79
string parameterString = (string)parameter;
XAML (el código XAML usa x:Name de la Entry para averiguar en la propiedad Entry.Text tiene más
de 3 caracteres de longitud):
<StackLayout>
<Label Text="3 Letter Name">
<Label.Triggers>
<DataTrigger TargetType="Label"
Binding="{Binding Source={x:Reference NameEntry},
Path=Text.Length,
Converter={x:Static
helpers:LengthTriggerConverter.Instance},
ConverterParameter=2}"
Value="False">
<Setter Property="TextColor"
Value="Gray"/>
</DataTrigger>
</Label.Triggers>
</Label>
<Entry x:Name="NameEntry"
Text="{Binding MealAmount}"
HorizontalOptions="StartAndExpand"/>
</StackLayout>
Multi Triggers
MultiTrigger no se necesita con frecuencia, pero hay algunas situaciones en las que es muy útil.
MultiTrigger se comporta de manera similar a Trigger o Data Trigger pero tiene múltiples
condiciones. Todas las condiciones deben ser ciertas para que un Setter dispare. Aquí hay un
ejemplo simple:
<!-- Text field needs to be initialized in order for the trigger to work at start -->
<Entry x:Name="email" Placeholder="Email" Text="" />
<Entry x:Name="phone" Placeholder="Phone" Text="" />
<Button Text="Submit">
<Button.Triggers>
<MultiTrigger TargetType="Button">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference email},
Path=Text.Length}" Value="0" />
<BindingCondition Binding="{Binding Source={x:Reference phone},
Path=Text.Length}" Value="0" />
</MultiTrigger.Conditions>
<Setter Property="IsEnabled" Value="False" />
</MultiTrigger>
</Button.Triggers>
</Button>
https://riptutorial.com/es/home 80
El ejemplo tiene dos entradas diferentes, teléfono y correo electrónico, y una de ellas debe
completarse. El MultiTrigger desactiva el botón de envío cuando ambos campos están vacíos.
https://riptutorial.com/es/home 81
Capítulo 18: Disposición relativa de Xamarin
Observaciones
El uso de ForceLayout en este caso.
Las etiquetas y el tamaño de los botones cambian de acuerdo con el texto dentro de ellos. Por lo
tanto, cuando los niños se agregan al diseño, su tamaño permanece en 0 tanto en ancho como en
alto. Por ejemplo:
relativeLayout.Children.Add(label,
Constraint.RelativeToParent(parent => label.Width));
La expresión anterior devolverá 0 porque el ancho es 0 en este momento. Para solucionar esto,
necesitamos escuchar el evento SizeChanged y cuando el tamaño cambie, debemos forzar el
diseño para volver a dibujarlo.
Para una vista como BoxView esto es innecesario. Porque podemos definir sus tamaños en la
instanciación. Lo otro es que, en ambos casos, podemos definir su ancho y alto como una
restricción cuando los estamos agregando al diseño. Por ejemplo:
relativeLayout.Children.Add(label,
Constraint.Constant(0),
Constraint.Constant(0),
//Width constraint
Constraint.Constant(30),
//Height constraint
Constraint.Constant(40));
Esto agregará la etiqueta al punto 0, 0. El ancho y el alto de la etiqueta serán 30 y 40. Sin
embargo, si el texto es demasiado largo, es posible que parte de la misma no se muestre. Si su
etiqueta tiene o podría tener una altura alta, puede usar la propiedad LineBreakMode de la
etiqueta. Que puede envolver el texto. Hay muchas opciones en LineBreakMode enum .
Examples
Página con una etiqueta simple en el medio.
https://riptutorial.com/es/home 82
public class MyPage : ContentPage
{
RelativeLayout _layout;
Label MiddleText;
public MyPage()
{
_layout = new RelativeLayout();
_layout.Children.Add(MiddleText
Constraint.RelativeToParent(parent => parent.Width / 2 - MiddleText.Width / 2),
Constraint.RelativeToParent(parent => parent.Height / 2 - MiddleText.Height / 2));
Content = _layout;
}
}
https://riptutorial.com/es/home 83
Caja tras caja
BoxView centerBox;
BoxView rightBox;
BoxView leftBox;
BoxView topBox;
BoxView bottomBox;
public MyPage()
{
_layout = new RelativeLayout();
https://riptutorial.com/es/home 84
WidthRequest = boxSize,
HeightRequest = boxSize
};
//First adding center box since other boxes will be relative to center box
_layout.Children.Add(centerBox,
//Constraint for X, centering it horizontally
//We give the expression as a paramater, parent is our layout in this case
Constraint.RelativeToParent(parent => parent.Width / 2 - boxSize / 2),
//Constraint for Y, centering it vertically
Constraint.RelativeToParent(parent => parent.Height / 2 - boxSize / 2),
//Constraint for Width
Constraint.Constant(boxSize),
//Constraint for Height
Constraint.Constant(boxSize));
_layout.Children.Add(leftBox,
//The x constraint will relate on some level to centerBox
//Which is the first parameter in this case
//We both need to have parent and centerBox, which will be called sibling,
//in our expression paramters
//This expression will be our second paramater
Constraint.RelativeToView(centerBox, (parent, sibling) => sibling.X - spacing -
boxSize),
//Since we only need to move it left,
//it's Y constraint will be centerBox' position at Y axis
Constraint.RelativeToView(centerBox, (parent, sibling) => sibling.Y)
//No need to define the size constraints
//Since we initialize them during instantiation
);
_layout.Children.Add(rightBox,
//The only difference hear is adding spacing and boxSize instead of substracting
them
Constraint.RelativeToView(centerBox, (parent, sibling) => sibling.X + spacing +
boxSize),
Constraint.RelativeToView(centerBox, (parent, sibling) => sibling.Y)
);
_layout.Children.Add(topBox,
https://riptutorial.com/es/home 85
//Since we are going to move it vertically this thime
//We need to do the math on Y Constraint
//In this case, X constraint will be centerBox' position at X axis
Constraint.RelativeToView(centerBox, (parent, sibling) => sibling.X),
//We will do the math on Y axis this time
Constraint.RelativeToView(centerBox, (parent, sibling) => sibling.Y - spacing -
boxSize)
);
_layout.Children.Add(bottomBox,
Constraint.RelativeToView(centerBox, (parent, sibling) => sibling.X),
Constraint.RelativeToView(centerBox, (parent, sibling) => sibling.Y + spacing +
boxSize)
);
Content = _layout;
}
}
https://riptutorial.com/es/home 86
Capítulo 19: Efectos
Introducción
Efectos simplifica las personalizaciones específicas de la plataforma. Cuando es necesario
modificar las propiedades de un control de formularios de Xamarin, se pueden usar los efectos.
Cuando es necesario anular los métodos de Xamarin Forms Control, se pueden usar
renderizadores personalizados
Examples
Agregar efecto específico de plataforma para un control de entrada
1. Cree una nueva aplicación Xamarin Forms utilizando el archivo PCL -> Nueva solución ->
Aplicación multiplataforma -> Xamarin Forms -> Aplicación Forms; Nombra el proyecto
como EffectsDemo
2. Bajo el proyecto iOS, agregue una nueva clase de Effect que herede de la clase
PlatformEffect y anule los métodos OnAttached , OnDetached y OnElementPropertyChanged
Observe los dos atributos ResolutionGroupName y ExportEffect , estos son necesarios para
consumir este efecto del PCL / proyecto compartido.
using System;
using EffectsDemo.iOS;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ResolutionGroupName("xhackers")]
[assembly: ExportEffect(typeof(FocusEffect), "FocusEffect")]
namespace EffectsDemo.iOS
{
public class FocusEffect : PlatformEffect
{
public FocusEffect()
{
}
UIColor backgroundColor;
protected override void OnAttached()
{
try
https://riptutorial.com/es/home 87
{
Control.BackgroundColor = backgroundColor = UIColor.Red;
}
catch (Exception ex)
{
Console.WriteLine("Cannot set attacked property" + ex.Message);
}
}
try
{
if (args.PropertyName == "IsFocused")
{
if (Control.BackgroundColor == backgroundColor)
{
Control.BackgroundColor = UIColor.Blue;
}
else
{
Control.BackgroundColor = backgroundColor;
}
}
}
catch (Exception ex)
{
Console.WriteLine("Cannot set property " + ex.Message);
}
}
}}
3. Para consumir este efecto en la aplicación, en el proyecto PCL , cree una nueva clase
llamada FocusEffect que herede de RoutingEffect . Esto es esencial para que el PCL
ejemplifique la implementación específica del efecto en la plataforma. Código de muestra a
continuación:
using Xamarin.Forms;
namespace EffectsDemo
{
public class FocusEffect : RoutingEffect
{
public FocusEffect() : base("xhackers.FocusEffect")
{
}
}
}
https://riptutorial.com/es/home 88
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-
namespace:EffectsDemo" x:Class="EffectsDemo.EffectsDemoPage">
<StackLayout Orientation="Horizontal" HorizontalOptions="Center"
VerticalOptions="Center">
<Label Text="Effects Demo" HorizontalOptions="StartAndExpand" VerticalOptions="Center"
></Label>
<Entry Text="Controlled by effects" HorizontalOptions="FillAndExpand"
VerticalOptions="Center">
<Entry.Effects>
<local:FocusEffect>
</local:FocusEffect>
</Entry.Effects>
</Entry>
</StackLayout>
</ContentPage>
https://riptutorial.com/es/home 89
https://riptutorial.com/es/home 90
Dado que el efecto se implementó solo en la versión de iOS, cuando la aplicación se ejecuta en el
iOS Simulator al enfocar los cambios de color de fondo de la Entry y no sucede nada en el Android
Emulator ya que el Effect no se creó en el proyecto Droid
https://riptutorial.com/es/home 91
Capítulo 20: El enlace de datos
Observaciones
Posibles excepciones
System.ArrayTypeMismatchException: se intentó acceder a
un elemento como un tipo incompatible con la matriz.
Esta excepción puede ocurrir cuando se intenta vincular una colección a una propiedad no
vinculable cuando está habilitada la precompilación XAML. Un ejemplo común es intentar enlazar
con Picker.Items . Vea abajo.
https://riptutorial.com/es/home 92
BindablePicker del paquete con una propiedad de ItemsSource está disponible:
Examples
Enlace básico a ViewModel
EntryPage.xaml:
MyViewModel.cs:
using System;
using System.ComponentModel;
namespace MyAssembly.ViewModel
{
public class MyViewModel : INotifyPropertyChanged
{
private string _name = String.Empty;
private string _phone = String.Empty;
https://riptutorial.com/es/home 93
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
}
public MyViewModel()
{
SaveCommand = new Command(SaveCommandExecute);
}
https://riptutorial.com/es/home 94
Capítulo 21: Examen de la unidad
Examples
Probando los modelos de vista.
Requisitos de negocio
Digamos que tenemos la siguiente funcionalidad para implementar:
As an unauthorized user
I want to log into the app
So that I will access the authorized features
https://riptutorial.com/es/home 95
When the user enters ' ' as username
And the user enters 'pass' as password
And the user taps the Login button
Then the app shows an error message saying 'Please, enter correct username and password'
And the app doesn't make an API call for authentication
Nos quedaremos solo con estos dos escenarios. Por supuesto, debería haber muchos más casos
y debería definirlos todos antes de la codificación real, pero ahora es suficiente para que nos
familiaricemos con las pruebas unitarias de los modelos de vista.
Sigamos el enfoque clásico de TDD y comencemos escribiendo una clase vacía que se está
probando. Luego, escribiremos pruebas y las haremos verdes implementando la funcionalidad
empresarial.
Clases comunes
public abstract class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
Servicios
¿Recuerda que nuestro modelo de vista no debe utilizar las clases de UI y HTTP directamente?
Debe definirlos como abstracciones en lugar de depender de los detalles de la implementación .
/// <summary>
/// Provides authentication functionality.
/// </summary>
public interface IAuthenticationService
{
/// <summary>
/// Tries to authenticate the user with the given credentials.
/// </summary>
/// <param name="userName">UserName</param>
/// <param name="password">User's password</param>
/// <returns>true if the user has been successfully authenticated</returns>
Task<bool> Login(string userName, string password);
}
/// <summary>
/// UI-specific service providing abilities to show alert messages.
/// </summary>
public interface IAlertService
{
/// <summary>
/// Show an alert message to the user.
https://riptutorial.com/es/home 96
/// </summary>
/// <param name="title">Alert message title</param>
/// <param name="message">Alert message text</param>
Task ShowAlert(string title, string message);
}
https://riptutorial.com/es/home 97
}
}
}
Pruebas
Ahora vamos a escribir algunas pruebas de acuerdo con los casos de uso mencionados
anteriormente. En primer lugar, debe crear un nuevo conjunto (solo una biblioteca de clases o
seleccionar un proyecto de prueba especial si desea usar las herramientas de prueba de unidad
de Microsoft). Asígnele un nombre similar a ProjectName.Tests y agregue una referencia a su
proyecto PCL original.
https://riptutorial.com/es/home 98
En este ejemplo voy a usar NUnit y Moq, pero puede continuar con las libs de prueba que desee.
No habrá nada especial con ellos.
[TestFixture]
public class LoginPageViewModelTest
{
}
Pruebas de escritura
Aquí están los métodos de prueba para los dos primeros escenarios. Intente mantener 1 método
de prueba por 1 resultado esperado y no verifique todo en una prueba. Eso le ayudará a recibir
informes más claros sobre lo que ha fallado en el código.
[TestFixture]
public class LoginPageViewModelTest
{
private readonly Mock<IAuthenticationService> authenticationServiceMock =
new Mock<IAuthenticationService>();
private readonly Mock<IAlertService> alertServiceMock =
new Mock<IAlertService>();
[TestCase("user", "pass")]
public void LogInWithValidCreds_LoadingIndicatorShown(string userName, string password)
{
LoginPageViewModel model = CreateViewModelAndLogin(userName, password);
Assert.IsTrue(model.IsLoading);
}
[TestCase("user", "pass")]
public void LogInWithValidCreds_AuthenticationRequested(string userName, string password)
{
CreateViewModelAndLogin(userName, password);
[TestCase("", "pass")]
[TestCase(" ", "pass")]
[TestCase(null, "pass")]
public void LogInWithEmptyuserName_AuthenticationNotRequested(string userName, string
password)
{
CreateViewModelAndLogin(userName, password);
https://riptutorial.com/es/home 99
string message)
{
CreateViewModelAndLogin(userName, password);
model.UserName = userName;
model.Password = password;
model.LoginCommand.Execute(null);
return model;
}
}
Y aquí vamos:
https://riptutorial.com/es/home 100
}
}
Ahora puede seguir cubriendo su código con nuevas pruebas, lo que lo hace más estable y
seguro para la regresión.
https://riptutorial.com/es/home 101
Capítulo 22: Fuentes personalizadas en
estilos
Observaciones
Recursos para mirar:
• Estilos de Xamarin
• Uso de fuentes personalizadas en iOS y Android con Xamarin.Forms
• Renderizadores personalizados
• Diccionarios de recursos
• Propiedades adjuntas
Examples
Acceso a fuentes personalizadas en Syles
En el mundo móvil, su aplicación debe ser bonita y sobresalir de las demás aplicaciones. Uno de
estos caracteres son las fuentes personalizadas utilizadas en la aplicación.
Con la potencia de XAML Styling en Xamarin.Forms acaba de crear un estilo base para todas las
etiquetas con sus fuentes personalizadas.
Para incluir fuentes personalizadas en su proyecto iOS y Android, siga la guía en Uso de fuentes
personalizadas en iOS y Android con Xamarin.Forms publicado por Gerald.
Declare Style en la sección de recursos del archivo App.xaml. Esto hace que todos los estilos
sean visibles globalmente.
Desde la publicación de Gerald anterior, necesitamos usar la propiedad StyleId pero no es una
propiedad vinculable, así que para usarla en Style Setter necesitamos crear una propiedad
adjuntada para ella:
https://riptutorial.com/es/home 102
(String)bindable.GetValue(StyleIdProperty);
<Application.Resources>
<ResourceDictionary>
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="FontFamily" Value="Metric Bold" />
<Setter Property="h:FontHelper.StyleId" Value="Metric-Bold" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
https://riptutorial.com/es/home 103
Ahora puedes obtener el estilo en el marcado de tu página:
O aplique el estilo a todas las etiquetas en la página creando Estilo Basado en LabesStyle
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Label" BasedOn={StaticResource LabelStyle}>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
</ContentPage>
https://riptutorial.com/es/home 104
Capítulo 23: Gesto de Xamarin
Examples
Toque gesto
Con el gesto de toque, puede hacer que se pueda hacer clic en cualquier elemento de la interfaz
de usuario (imágenes, botones, apilamientos, ...):
<Image Source="tapped.jpg">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapGestureRecognizerTapped" Command="{Binding
TapCommand"} />
</Image.GestureRecognizers>
</Image>
https://riptutorial.com/es/home 105
Capítulo 24: Gesto de Xamarin
Examples
Evento gestual
Cuando el usuario desea reemplazar el botón con la etiqueta, le damos el evento para la etiqueta.
Como se muestra abajo:
XAML
DO#
La pantalla de abajo muestra el evento de etiqueta. Pantalla 1: La etiqueta "¿No tienes una
cuenta?" como se muestra en la parte inferior.
https://riptutorial.com/es/home 106
https://riptutorial.com/es/home 107
https://riptutorial.com/es/xamarin-forms/topic/8009/gesto-de-xamarin
https://riptutorial.com/es/home 108
Capítulo 25: Gestos
Examples
Haga que una imagen pueda ser ejecutada agregando un
TapGestureRecognizer
O en XAML:
<Image Source="tapped.jpg">
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding TappedCommand}"
NumberOfTapsRequired="2" />
</Image.GestureRecognizers>
</Image>
Aquí el comando se establece mediante el enlace de datos. Como puede ver, también puede
configurar NumberOfTapsRequired para habilitarlo para más toques antes de que actúe. El valor
predeterminado es 1 toque.
Para poder hacer que una Image (o cualquier otro elemento visual) pueda hacer zoom, debemos
agregarle un PinchGestureRecognizer . Aquí está cómo hacerlo en código:
image.GestureRecognizers.Add(pinchGesture);
https://riptutorial.com/es/home 109
Pero también se puede hacer desde XAML:
<Image Source="waterfront.jpg">
<Image.GestureRecognizers>
<PinchGestureRecognizer PinchUpdated="OnPinchUpdated" />
</Image.GestureRecognizers>
</Image>
Cuando tenga una Image ampliada (u otro contenido) puede arrastrarla alrededor de la Image para
mostrar todo su contenido en el estado ampliado.
image.GestureRecognizers.Add(panGesture);
<Image Source="MonoMonkey.jpg">
<Image.GestureRecognizers>
<PanGestureRecognizer PanUpdated="OnPanUpdated" />
</Image.GestureRecognizers>
</Image>
En el evento de código subyacente ahora puede manejar el panorama en consecuencia. Use esta
firma de método para manejarlo:
https://riptutorial.com/es/home 110
Los Xamarins incorporados en los reconocedores de gestos proporcionan un manejo táctil muy
básico. Por ejemplo, no hay forma de obtener la posición de un dedo que toca. MR.Gestures es
un componente que agrega 14 eventos diferentes de manejo táctil. La posición de los dedos que
tocan es parte de los EventArgs pasados a todos los eventos de MR.Gestures.
Si desea colocar un pin en cualquier lugar de la pantalla, la forma más sencilla es usar un
MR.Gestures.AbsoluteLayout que controla el evento Tapping .
Como puede ver, el Tapping="OnTapping" también se parece más a .NET que a la sintaxis de
Xamarins con los GestureRecognizers anidados. Esa sintaxis fue copiada de iOS y huele un poco a
los desarrolladores de .NET.
En lugar del evento Tapping , también puede usar TappingCommand y enlazar con su ViewModel, pero
eso complicaría las cosas en este sencillo ejemplo.
https://riptutorial.com/es/home 111
Capítulo 26: Manejo de excepciones
Examples
Una forma de informar acerca de las excepciones en iOS
Vaya al archivo Main.cs en el proyecto iOS y cambie el código existente, como se presenta a
continuación:
ILittleWatson interfaz ILittleWatson , utilizada en código portátil, podría tener este aspecto:
[assembly: Xamarin.Forms.Dependency(typeof(LittleWatson))]
namespace SomeNamespace
{
public class LittleWatson : ILittleWatson
{
private const string FileName = "Report.txt";
static LittleWatson()
{
DocumentsFolder =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
FilePath = Path.Combine(DocumentsFolder, FileName);
}
https://riptutorial.com/es/home 112
public async Task<bool> SendReport()
{
_sendingTask = new TaskCompletionSource<bool>();
try
{
var text = File.ReadAllText(FilePath);
File.Delete(FilePath);
if (MFMailComposeViewController.CanSendMail)
{
var email = ""; // Put receiver email here.
var mailController = new MFMailComposeViewController();
mailController.SetToRecipients(new string[] { email });
mailController.SetSubject("iPhone error");
mailController.SetMessageBody(text, false);
mailController.Finished += (object s, MFComposeResultEventArgs args) =>
{
args.Controller.DismissViewController(true, null);
_sendingTask.TrySetResult(true);
};
ShowViewController(mailController);
}
}
catch (FileNotFoundException)
{
// No errors found.
_sendingTask.TrySetResult(false);
}
https://riptutorial.com/es/home 113
Lea Manejo de excepciones en línea: https://riptutorial.com/es/xamarin-forms/topic/6428/manejo-
de-excepciones
https://riptutorial.com/es/home 114
Capítulo 27: MessagingCenter
Introducción
Xamarin.Forms tiene un mecanismo de mensajería incorporado para promover el código
desacoplado. De esta manera, los modelos de visualización y otros componentes no necesitan
conocerse entre sí. Pueden comunicarse por un simple contrato de mensajería.
Suscribir escuche los mensajes con cierta firma (el contrato) y ejecute el código cuando reciba un
mensaje. Un mensaje puede tener múltiples suscriptores.
Examples
Ejemplo simple
public FooMessaging()
{
MessagingCenter.Subscribe<MainPage> (this, "Hi", (sender) => {
this.Greeting = "Hi there!";
});
}
}
Para enviar un mensaje que active esta funcionalidad, necesitamos tener una página llamada
MainPage e implementar un código como el de abajo.
https://riptutorial.com/es/home 115
En nuestra MainPage tenemos un botón con un controlador que envía un mensaje. this debería ser
una instancia de MainPage .
Pasando argumentos
Usaremos las clasificadas de nuestro ejemplo anterior y las ampliaremos. En la parte receptora,
justo detrás de la llamada al método Subscribe , agregue el tipo de argumento que espera.
Asegúrese también de declarar los argumentos en la firma del controlador.
public FooMessaging()
{
MessagingCenter.Subscribe<MainPage, string> (this, "Hi", (sender, arg) => {
this.Greeting = arg;
});
}
}
Al enviar un mensaje, asegúrese de incluir el valor del argumento. Además, aquí agrega el tipo
justo detrás del método de Send y agrega el valor del argumento.
En este ejemplo, se utiliza una cadena simple, pero también puede usar cualquier otro tipo de
objetos (complejos).
Darse de baja
Cuando ya no necesite recibir mensajes, simplemente puede darse de baja. Puedes hacerlo así:
Cuando está proporcionando argumentos, debe darse de baja de la firma completa, como esto:
https://riptutorial.com/es/home 116
Capítulo 28: Mostrar alerta
Examples
DisplayAlert
Un cuadro de alerta puede aparecer en una Xamarin.Forms Page por el método, DisplayAlert .
Podemos proporcionar un Título, Cuerpo (Texto para ser alertado) y uno / dos botones de acción.
Page ofrece dos anulaciones del método DisplayAlert .
Esta anulación presenta un cuadro de diálogo de alerta para el usuario de la aplicación con un
solo botón de cancelación. La alerta se muestra de manera modal y, una vez descartada, el
usuario continúa interactuando con la aplicación.
Ejemplo:
Esta anulación presenta un cuadro de diálogo de alerta para el usuario de la aplicación con los
https://riptutorial.com/es/home 117
botones Aceptar y Cancelar. Captura la respuesta de un usuario presentando dos botones y
devolviendo un valor boolean . Para obtener una respuesta de una alerta, suministre texto para
ambos botones y espere el método. Después de que el usuario seleccione una de las opciones, la
respuesta se devolverá al código.
Ejemplo:
var answer = await DisplayAlert ("Question?", "Would you like to play a game", "Yes", "No");
Debug.WriteLine ("Answer: " + (answer?"Yes":"No"));
https://riptutorial.com/es/home 118
Capítulo 29: Navegación en Xamarin. Formas
Examples
Flujo de navegación
using System;
using Xamarin.Forms;
namespace NavigationApp
{
public class App : Application
{
public App()
{
MainPage = new NavigationPage(new FirstPage());
}
}
public FirstPage()
{
Title = "First page";
Content = content;
}
public SecondPage()
{
Title = "Second page";
Content = SecondPageLabel;
https://riptutorial.com/es/home 119
}
}
}
using Xamrin.Forms
namespace NavigationApp
{
public partial class App : Application
{
public static INavigation GlobalNavigation { get; private set; }
public App()
{
InitializeComponent();
var rootPage = new NavigationPage(new FirstPage());
GlobalNavigation = rootPage.Navigation;
MainPage = rootPage;
}
}
}
Archivo FirstPage.xaml
En algunos casos, necesita abrir la nueva página no en la navegación actual sino en la global. Por
ejemplo, si su página actual contiene el menú inferior, será visible cuando presione la nueva
página en la navegación actual. Si necesita que la página se abra sobre todo el contenido visible
que oculta el menú inferior y el contenido de otra página actual, debe insertar la nueva página
como modal en la navegación global. Consulte la propiedad App.GlobalNavigation y el ejemplo a
https://riptutorial.com/es/home 120
continuación.
Archivo FirstPage.xaml.cs
using System;
using Xamarin.Forms;
namespace NavigationApp
{
public partial class FirstPage : ContentPage
{
public FirstPage()
{
InitializeComponent();
}
De forma predeterminada, el patrón de navegación funciona como una pila de páginas, y llama a
las páginas más recientes sobre las páginas anteriores. Necesitará usar el objeto NavigationPage
para esto.
...
public class App : Application
{
public App()
{
https://riptutorial.com/es/home 121
MainPage = new NavigationPage(new Page1());
}
}
...
Page1.xaml
...
<ContentPage.Content>
<StackLayout>
<Label Text="Page 1" />
<Button Text="Go to page 2" Clicked="GoToNextPage" />
</StackLayout>
</ContentPage.Content>
...
Page1.xaml.cs
...
public partial class Page1 : ContentPage
{
public Page1()
{
InitializeComponent();
}
Page2.xaml
...
<ContentPage.Content>
<StackLayout>
<Label Text="Page 2" />
<Button Text="Go to Page 3" Clicked="GoToNextPage" />
</StackLayout>
</ContentPage.Content>
...
Page2.xaml.cs
...
public partial class Page2 : ContentPage
{
public Page2()
{
InitializeComponent();
}
https://riptutorial.com/es/home 122
protected async void GoToNextPage(object sender, EventArgs e)
{
await Navigation.PushAsync(new Page3());
}
}
...
Saltando páginas
Normalmente, el usuario usa el botón Atrás para regresar páginas, pero a veces necesita
controlar esto programáticamente, por lo que debe llamar al método NavigationPage.PopAsync
() para regresar a la página anterior o NavigationPage.PopToRootAsync () para regresar al
principio, tales como ...
Page3.xaml
...
<ContentPage.Content>
<StackLayout>
<Label Text="Page 3" />
<Button Text="Go to previous page" Clicked="GoToPreviousPage" />
<Button Text="Go to beginning" Clicked="GoToStartPage" />
</StackLayout>
</ContentPage.Content>
...
Page3.xaml.cs
...
public partial class Page3 : ContentPage
{
public Page3()
{
InitializeComponent();
}
https://riptutorial.com/es/home 123
• Para Alertas y Notificaciones
• Para ActionSheets que son menús emergentes.
...
// to open
await Navigation.PushModalAsync(new ModalPage());
// to close
await Navigation.PopModalAsync();
...
...
// alert
await DisplayAlert("Alert title", "Alert text", "Ok button text");
// confirmation
var booleanAnswer = await DisplayAlert("Confirm?", "Confirmation text", "Yes", "No");
...
Hojas de acción
...
var selectedOption = await DisplayActionSheet("Options", "Cancel", "Destroy", "Option 1",
"Option 2", "Option 3");
...
public App ()
{
// The root page of your application
MainPage = new RootPage();
}
}
public class RootPage : MasterDetailPage
{
public RootPage()
{
var menuPage = new MenuPage();
menuPage.Menu.ItemSelected += (sender, e) => NavigateTo(e.SelectedItem as MenuItem);
Master = menuPage;
App.NavPage = new NavigationPage(new HomePage());
Detail = App.NavPage;
}
protected override async void OnAppearing()
{
https://riptutorial.com/es/home 124
base.OnAppearing();
}
void NavigateTo(MenuItem menuItem)
{
Page displayPage = (Page)Activator.CreateInstance(menuItem.TargetType);
Detail = new NavigationPage(displayPage);
IsPresented = false;
}
}
El siguiente código muestra cómo realizar una navegación asíncrona cuando la aplicación se
encuentra en un contexto MasterDetailPage.
await navigationPage.Navigation.PushAsync(page);
navigationPage.Navigation.RemovePage(navigationPage.Navigation.NavigationStack[navigationPage.Navigatio
- 2]);
masterDetail.IsPresented = false;
}
https://riptutorial.com/es/home 125
Capítulo 30: Navegación en Xamarin. Formas
Observaciones
La navegación en Xamarin.Forms se basa en dos patrones de navegación principales: jerárquico
y modal.
El patrón jerárquico permite al usuario moverse hacia abajo en una pila de páginas y regresar
presionando el botón "atrás" / "arriba".
El patrón modal es una página de interrupción que requiere una acción específica del usuario,
pero normalmente se puede cancelar presionando el botón de cancelar. Algunos ejemplos son
notificaciones, alertas, cuadros de diálogo y páginas de registro / edición.
Examples
Usando INavigation desde el modelo de vista
El primer paso es crear una interfaz de navegación que usaremos en el modelo de vista:
return typeSource;
}
https://riptutorial.com/es/home 126
public object GetAssociatedSource(Type typeSource)
{
object associatedSource;
_typeToAssociateDictionary.TryGetValue(typeSource, out associatedSource);
return associatedSource;
}
}
Archivo App.cs :
Implementación de IViewNavigationService :
[assembly: Dependency(typeof(ViewNavigationService))]
namespace SuperForms.Core.ViewNavigation
{
public class ViewNavigationService : IViewNavigationService
{
private INavigation _navigation;
private SuperMapper _navigationMapper;
https://riptutorial.com/es/home 127
_navigationMapper = navigationMapper;
}
if (type == null)
{
throw new InvalidOperationException(
"Can't find associated type for " + navigationSource.ToString());
}
ConstructorInfo constructor;
object[] parameters;
if (parameter == null)
{
constructor = type.GetTypeInfo()
.DeclaredConstructors
.FirstOrDefault(c => !c.GetParameters().Any());
if (constructor == null)
{
throw new InvalidOperationException(
"No suitable constructor found for page " + navigationSource.ToString());
}
await _navigation.PushAsync(page);
}
await _navigation.PopAsync();
}
https://riptutorial.com/es/home 128
throw new NullReferenceException("Call Initialize method first.");
}
}
}
Obtengo el tipo de página en la que el usuario desea navegar y crear su instancia utilizando la
reflexión.
https://riptutorial.com/es/home 129
Capítulo 31: Notificaciones push
Observaciones
No hay una manera uniforme de manejar las notificaciones push en Xamarin Forms, ya que la
implementación depende en gran medida de las características y eventos específicos de la
plataforma. Por lo tanto, siempre será necesario el código específico de la plataforma.
Sin embargo, al usar DependencyService puede compartir la mayor cantidad de código posible.
También hay un complemento diseñado para esto por rdelrosario, que se puede encontrar en su
GitHub .
El código y las capturas de pantalla se tomaron de una serie de blogs de Gerald Versluis que
explica el proceso con más detalle.
Examples
Notificaciones push para iOS con Azure
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
UIApplication.SharedApplication.RegisterForRemoteNotifications();
La ejecución de este código activará una alerta para avisar al usuario si acepta que la aplicación
puede enviarles notificaciones. ¡Así también implementar un escenario donde el usuario lo
niegue!
https://riptutorial.com/es/home 130
Estos son los eventos que necesitan implementación para implementar notificaciones push en
iOS. Puedes encontrarlos en el archivo AppDelegate.cs .
// We've successfully registered with the Apple notification service, or in our case Azure
public override void RegisteredForRemoteNotifications(UIApplication application, NSData
deviceToken)
{
// Modify device token for compatibility Azure
var token = deviceToken.Description;
https://riptutorial.com/es/home 131
token = token.Trim('<', '>').Replace(" ", "");
NSSet tags = null; // create tags if you want, not covered for now
hub.RegisterNativeAsync(deviceToken, tags, (errorCallback) =>
{
if (errorCallback != null)
{
var alert = new UIAlertView("ERROR!", errorCallback.ToString(), null, "OK", null);
alert.Show();
}
});
}
if (success)
{
var alert = new UIAlertView("Notification!", inAppMessage.ToString(), null, "OK",
null);
alert.Show();
}
}
alert.Show();
}
https://riptutorial.com/es/home 132
Notificaciones push para Android con Azure
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
}
using Android.App;
using Android.Content;
using Gcm.Client;
using Java.Lang;
using System;
using WindowsAzure.Messaging;
using XamarinNotifications.Helpers;
// These attributes are to register the right permissions for our app concerning push messages
[assembly: Permission(Name = "com.versluisit.xamarinnotifications.permission.C2D_MESSAGE")]
https://riptutorial.com/es/home 133
[assembly: UsesPermission(Name =
"com.versluisit.xamarinnotifications.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
namespace XamarinNotifications.Droid.PlatformSpecifics
{
// These attributes belong to the BroadcastReceiver, they register for the right intents
[BroadcastReceiver(Permission = Constants.PERMISSION_GCM_INTENTS)]
[IntentFilter(new[] { Constants.INTENT_FROM_GCM_MESSAGE },
Categories = new[] { "com.versluisit.xamarinnotifications" })]
[IntentFilter(new[] { Constants.INTENT_FROM_GCM_REGISTRATION_CALLBACK },
Categories = new[] { "com.versluisit.xamarinnotifications" })]
[IntentFilter(new[] { Constants.INTENT_FROM_GCM_LIBRARY_RETRY },
Categories = new[] { "com.versluisit.xamarinnotifications" })]
[Service] // Don't forget this one! This tells Xamarin that this class is a Android
Service
public class PushHandlerService : GcmServiceBase
{
// TODO add your own access key
private string _connectionString =
ConnectionString.CreateUsingSharedAccessKeyWithListenAccess(
new Java.Net.URI("sb://xamarinnotifications-ns.servicebus.windows.net/"), "<your
key here>");
if (intent.Extras.ContainsKey("title"))
title = intent.Extras.GetString("title");
if (!string.IsNullOrEmpty(messageText))
CreateNotification(title, messageText);
}
https://riptutorial.com/es/home 134
private void CreateNotification(string title, string desc)
{
// First we make sure our app will start when the notification is pressed
const int pendingIntentId = 0;
const int notificationId = 0;
stackBuilder.AddParentStack(Class.FromType(typeof(MainActivity)));
stackBuilder.AddNextIntent(startupIntent);
var pendingIntent =
stackBuilder.GetPendingIntent(pendingIntentId, PendingIntentFlags.OneShot);
// Here we start building our actual notification, this has some more
// interesting customization options!
var builder = new Notification.Builder(this)
.SetContentIntent(pendingIntent)
.SetContentTitle(title)
.SetContentText(desc)
.SetSmallIcon(Resource.Drawable.icon);
Settings.DeviceToken = registrationId;
// TODO set some tags here if you want and supply them to the Register method
var tags = new string[] { };
hub.Register(registrationId, tags);
}
https://riptutorial.com/es/home 135
hub.UnregisterAll(registrationId);
}
}
}
En Windows Phone, se debe implementar algo como el código que se encuentra debajo para
comenzar a trabajar con las notificaciones push. Esto se puede encontrar en el archivo
App.xaml.cs
https://riptutorial.com/es/home 136
Una muestra de notificación de inserción puede verse así:
https://riptutorial.com/es/home 137
Capítulo 32: Notificaciones push
Observaciones
GCM : Google Cloud Messaging es muy similar a APNS. Google es el único que puede enviar
directamente notificaciones push. Entonces, primero registramos nuestra aplicación en GCM y
entregamos nuestro token a AWS SNS. SNS maneja todas las cosas complejas relacionadas con
GCM y el envío de datos.
Examples
Ejemplo de iOS
//variable to set-up the style of notifications you want, iOS supports 3 types
https://riptutorial.com/es/home 138
null );
//both of these methods are in iOS, we have to override them and set them up
//to allow push notifications
// This contains the registered push notification token stored on the phone.
var deviceToken = token.Description.Replace("<", "").Replace(">", "").Replace(" ",
"");
if (!string.IsNullOrEmpty(deviceToken))
{
//register with SNS to create an endpoint ARN, this means AWS can message your
phone
var response = await snsClient.CreatePlatformEndpointAsync(
new CreatePlatformEndpointRequest
{
Token = deviceToken,
PlatformApplicationArn = "yourARNwouldgohere" /* insert your platform
application ARN here */
});
//AWS lets you create topics, so use subscribe your app to a topic, so you can
easily send out one push notification to all of your users
var subscribeResponse = await snsClient.SubscribeAsync(new SubscribeRequest
{
TopicArn = "YourTopicARN here",
Endpoint = endpoint,
Protocol = "application"
});
https://riptutorial.com/es/home 139
Capítulo 33: OAuth2
Examples
Autenticación utilizando el complemento
1. Primero, vaya a Herramientas > NuGet Package Manager > Package Manager Console .
https://riptutorial.com/es/home 140
3. Ahora todo el archivo se crea automáticamente.
https://riptutorial.com/es/home 141
Capítulo 34: Renderizadores personalizados
Examples
Procesador personalizado para ListView
En primer lugar, debemos crear un control personalizado en el proyecto PCL, que declarará
alguna propiedad enlazable requerida:
iOS:
Control.ScrollEnabled = superListView.IsScrollingEnable;
https://riptutorial.com/es/home 142
}
}
}
Y Android (la lista de Android no tiene desplazamiento si todos los elementos se colocan en la
pantalla, por lo que no deshabilitaremos el desplazamiento, pero aún podemos usar propiedades
nativas):
Element propiedad del Element del procesador es mi control SuperListView del proyecto PCL.
<ContentPage x:Name="Page"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:SuperForms.Controls;assembly=SuperForms.Controls"
x:Class="SuperForms.Samples.SuperListViewPage">
https://riptutorial.com/es/home 143
private ObservableCollection<string> _items;
public SuperListViewPage()
{
var list = new SuperListView();
InitializeComponent();
En primer lugar, debemos crear un control personalizado en el proyecto PCL, que declarará
alguna propiedad enlazable requerida:
namespace Mobile.Controls
{
public class ExtendedBoxView : BoxView
{
/// <summary>
/// Respresents the background color of the button.
/// </summary>
public static readonly BindableProperty BorderRadiusProperty =
BindableProperty.Create<ExtendedBoxView, double>(p => p.BorderRadius, 0);
https://riptutorial.com/es/home 144
get { return (Color)GetValue(StrokeProperty); }
set { SetValue(StrokeProperty, value); }
}
iOS:
Layer.MasksToBounds = true;
Layer.CornerRadius = (float)((ExtendedBoxView)this.Element).BorderRadius / 2.0f;
}
https://riptutorial.com/es/home 145
nfloat radius = (nfloat)roundedBoxView.BorderRadius;
radius = (nfloat)Math.Max(0, Math.Min(radius, Math.Max(rCorner.Height / 2,
rCorner.Width / 2)));
}
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
{
base.OnElementChanged(e);
SetWillNotDraw(false);
Invalidate();
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected override void OnElementPropertyChanged(object sender,
System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == ExtendedBoxView.BorderRadiusProperty.PropertyName)
{
Invalidate();
}
https://riptutorial.com/es/home 146
}
/// <summary>
///
/// </summary>
/// <param name="canvas"></param>
public override void Draw(Canvas canvas)
{
var box = Element as ExtendedBoxView;
base.Draw(canvas);
Paint myPaint = new Paint();
myPaint.SetStyle(Paint.Style.Stroke);
myPaint.StrokeWidth = (float)box.StrokeThickness;
myPaint.SetARGB(convertTo255ScaleColor(box.Color.A),
convertTo255ScaleColor(box.Color.R), convertTo255ScaleColor(box.Color.G),
convertTo255ScaleColor(box.Color.B));
myPaint.SetShadowLayer(20, 0, 5, Android.Graphics.Color.Argb(100, 0, 0, 0));
SetLayerType(Android.Views.LayerType.Software, myPaint);
/// <summary>
///
/// </summary>
/// <param name="color"></param>
/// <returns></returns>
private int convertTo255ScaleColor(double color)
{
return (int) Math.Ceiling(color * 255);
}
}
El XAML:
Primero hacemos referencia a nuestro control con el espacio de nombres que definimos
anteriormente.
xmlns:Controls="clr-namespace:Mobile.Controls"
Luego usamos el Control de la siguiente manera y usamos las propiedades definidas al principio:
<Controls:ExtendedBoxView
x:Name="search_boxview"
https://riptutorial.com/es/home 147
Color="#444"
BorderRadius="5"
HorizontalOptions="CenterAndExpand"
/>
if (renderer == null)
{
renderer = Platform.CreateRenderer(visualElement);
Platform.SetRenderer(visualElement, renderer);
}
using Xamarin.Forms;
namespace ProjectNamespace
{
public class ExtendedFrame : Frame
{
/// <summary>
/// The corner radius property.
/// </summary>
public static readonly BindableProperty CornerRadiusProperty =
BindableProperty.Create("CornerRadius", typeof(double), typeof(ExtendedFrame),
0.0);
/// <summary>
/// Gets or sets the corner radius.
/// </summary>
public double CornerRadius
{
get { return (double)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
}
}
using ProjectNamespace;
using ProjectNamespace.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
https://riptutorial.com/es/home 148
{
public class ExtendedFrameRenderer : FrameRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
if (Element != null)
{
Layer.MasksToBounds = true;
Layer.CornerRadius = (float)(Element as ExtendedFrame).CornerRadius;
}
}
if (e.PropertyName == ExtendedFrame.CornerRadiusProperty.PropertyName)
{
Layer.CornerRadius = (float)(Element as ExtendedFrame).CornerRadius;
}
}
}
}
xmlns:controls="clr-namespace:ProjectNamespace;assembly:ProjectNamespace"
después
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
<controls:ExtendedFrame
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
BackgroundColor="Gray"
CornerRadius="35.0">
<Frame.Content>
<Label
Text="MyText"
TextColor="Blue"/>
</Frame.Content>
</controls:ExtendedFrame>
https://riptutorial.com/es/home 149
public class RoundedBoxView : BoxView
{
public static readonly BindableProperty CornerRadiusProperty =
BindableProperty.Create("CornerRadius", typeof(double), typeof(RoundedEntry),
default(double));
https://riptutorial.com/es/home 150
var rect = new Rect();
var paint = new Paint
{
Color = Xamarin.Forms.Color.FromHex(box.FillColor).ToAndroid(),
AntiAlias = true,
};
GetDrawingRect(rect);
if (Element != null)
{
Layer.CornerRadius = (float)(Element as RoundedBoxView).CornerRadius;
Layer.BackgroundColor = Color.FromHex((Element as
RoundedBoxView).FillColor).ToCGColor();
}
}
if (Element != null)
{
Layer.CornerRadius = (float)(Element as RoundedBoxView).CornerRadius;
Layer.BackgroundColor = (Element as RoundedBoxView).FillColor.ToCGColor();
}
}
}
}
https://riptutorial.com/es/home 151
Capítulo 35: Selector de contactos - Formas
Xamarin (Android y iOS)
Observaciones
Contact Picker XF (Android y iOS)
Examples
contact_picker.cs
using System;
using Xamarin.Forms;
namespace contact_picker
{
public class App : Application
{
public App ()
{
// The root page of your application
MainPage = new MyPage();
}
MyPage.cs
using System;
using Xamarin.Forms;
namespace contact_picker
{
public class MyPage : ContentPage
https://riptutorial.com/es/home 152
{
Button button;
public MyPage ()
{
button = new Button {
Text = "choose contact"
};
if (Device.OS == TargetPlatform.iOS) {
await Navigation.PushModalAsync (new ChooseContactPage ());
}
else if (Device.OS == TargetPlatform.Android)
{
MessagingCenter.Send (this, "android_choose_contact", "number1");
}
};
}
}
}
ChooseContactPicker.cs
using System;
using Xamarin.Forms;
namespace contact_picker
{
public class ChooseContactPage : ContentPage
{
public ChooseContactPage ()
{
}
}
}
ChooseContactActivity.cs
https://riptutorial.com/es/home 153
using Android.App;
using Android.OS;
using Android.Content;
using Android.Database;
using Xamarin.Forms;
namespace contact_picker.Droid
{
base.OnCreate (savedInstanceState);
cursor.MoveToFirst();
string number =
cursor.GetString(cursor.GetColumnIndexOrThrow(Android.Provider.ContactsContract.CommonDataKinds.Phone.N
}
else if (resultCode == Result.Canceled)
{
Finish ();
}
}
}
}
}
https://riptutorial.com/es/home 154
MainActivity.cs
using System;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Xamarin.Forms;
namespace contact_picker.Droid
{
[Activity (Label = "contact_picker.Droid", Icon = "@drawable/icon", MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity :
global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
ChooseContactRenderer.cs
using UIKit;
using AddressBookUI;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using contact_picker;
using contact_picker.iOS;
namespace contact_picker.iOS
{
public partial class ChooseContactRenderer : PageRenderer
{
ABPeoplePickerNavigationController _contactController;
https://riptutorial.com/es/home 155
public string type_number;
_contactController.Cancelled += delegate {
Xamarin.Forms.Application.Current.MainPage.Navigation.PopModalAsync ();
this.DismissModalViewController (true); };
if (getphones == null)
{
number = "Nothing";
}
else if (getphones.Count > 1)
{
//il ya plus de 2 num de telephone
foreach(var t in getphones)
{
number = t.Value + "/" + number;
}
}
else if (getphones.Count == 1)
{
//il ya 1 num de telephone
foreach(var t in getphones)
{
number = t.Value;
}
}
Xamarin.Forms.Application.Current.MainPage.Navigation.PopModalAsync ();
https://riptutorial.com/es/home 156
var twopage_renderer = new MyPage();
MessagingCenter.Send<MyPage, string> (twopage_renderer, "num_select", number);
this.DismissModalViewController (true);
};
}
this.DismissModalViewController (true);
}
https://riptutorial.com/es/home 157
Capítulo 36: Servicios de dependencia
Observaciones
Acceda a la API específica de la plataforma desde PCL o proyecto compartido.
Examples
Acceso a la cámara y la galería.
https://riptutorial.com/es/home 158
Capítulo 37: Trabajando con Mapas
Observaciones
Si va a ejecutar su proyecto en otra computadora, tendrá que generar una nueva clave API para
él, porque las huellas dactilares SHA-1 no coincidirán con las diferentes máquinas de
compilación.
Examples
Añadiendo un mapa en Xamarin.Forms (Xamarin Studio)
Simplemente puede usar las API de mapas nativos en cada plataforma con Xamarin Forms. Todo
lo que necesita es descargar el paquete Xamarin.Forms.Maps de nuget e instalarlo en cada
proyecto (incluido el proyecto PCL).
Inicialización de mapas
En primer lugar, debe agregar este código a sus proyectos específicos de la plataforma. Para
hacer esto, debe agregar la Xamarin.FormsMaps.Init método Xamarin.FormsMaps.Init , como en los
ejemplos a continuación.
proyecto iOS
Archivo AppDelegate.cs
[Register("AppDelegate")]
public partial class AppDelegate : Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Xamarin.Forms.Forms.Init();
Xamarin.FormsMaps.Init();
LoadApplication(new App());
Proyecto de android
https://riptutorial.com/es/home 159
Archivo MainActivity.cs
base.OnCreate(bundle);
Xamarin.Forms.Forms.Init(this, bundle);
Xamarin.FormsMaps.Init(this, bundle);
LoadApplication(new App());
}
}
Configuración de la plataforma
Se requieren pasos de configuración adicionales en algunas plataformas antes de que se muestre
el mapa.
proyecto iOS
En el proyecto iOS, solo tiene que agregar 2 entradas a su archivo Info.plist :
https://riptutorial.com/es/home 160
Proyecto de android
Para usar Google Maps, debe generar una clave API y agregarla a su proyecto. Siga las
instrucciones a continuación para obtener esta clave:
cd /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands
https://riptutorial.com/es/home 161
Serial number: 4b5ac934
Valid from: Thu Jun 30 10:22:00 EEST 2016 until: Sat Jun 23 10:22:00 EEST 2046
Certificate fingerprints:
MD5: 4E:49:A7:14:99:D6:AB:9F:AA:C7:07:E2:6A:1A:1D:CA
SHA1: 57:A1:E5:23:CE:49:2F:17:8D:8A:EA:87:65:44:C1:DD:1C:DA:51:95
SHA256:
70:E1:F3:5B:95:69:36:4A:82:A9:62:F3:67:B6:73:A4:DD:92:95:51:44:E3:4C:3D:9E:ED:99:03:09:9F:90:3F
4. Todo lo que necesitamos en esta salida es la huella digital del certificado SHA1. En nuestro
caso es igual a esto:
57:A1:E5:23:CE:49:2F:17:8D:8A:EA:87:65:44:C1:DD:1C:DA:51:95
https://riptutorial.com/es/home 162
6. Google le pedirá que cree un proyecto para habilitar las API, siga este consejo y cree el
proyecto:
https://riptutorial.com/es/home 163
7. Habilite la API de Google Maps para su proyecto:
https://riptutorial.com/es/home 164
Después de habilitar la API, debe crear credenciales para su aplicación. Siga este consejo:
https://riptutorial.com/es/home 165
8. En la página siguiente, elija la plataforma Android, toque "¿Qué credenciales necesito?"
botón, cree un nombre para su clave API, toque "Agregar nombre de paquete y huella
digital", ingrese su nombre de paquete y su huella digital SHA1 en el paso 4 y finalmente
cree una clave API:
Para encontrar el nombre de su paquete en Xamarin Studio, vaya a su solución .Droid ->
AndroidManifest.xml:
https://riptutorial.com/es/home 166
9. Después de la creación, copie la nueva clave API (no olvide presionar el botón "Listo"
después) y péguela en su archivo AndroidManifest.xml :
https://riptutorial.com/es/home 167
Archivo AndroidManifest.xml
https://riptutorial.com/es/home 168
• Ubicación de acceso Comandos adicionales
• Acceso a la ubicación simulada
• Estado de la red de acceso
• Acceso Wifi Estado
• Internet
Aunque, los dos últimos permisos son necesarios para descargar datos de Maps. Lea
https://riptutorial.com/es/home 169
acerca de los permisos de Android para aprender más. Eso es todos los pasos para la
configuración de Android.
Añadiendo un mapa
Agregar una vista de mapa a su proyecto multiplataforma es bastante simple. Aquí hay un
ejemplo de cómo puede hacerlo (estoy usando el proyecto PCL sin XAML).
Proyecto PCL
Archivo MapExample.cs
MainPage = rootPage;
}
}
Eso es todo. Ahora, si ejecuta su aplicación en iOS o Android, le mostrará la vista del mapa:
https://riptutorial.com/es/home 170
Lea Trabajando con Mapas en línea: https://riptutorial.com/es/xamarin-
forms/topic/3917/trabajando-con-mapas
https://riptutorial.com/es/home 171
Capítulo 38: Trabajar con bases de datos
locales
Examples
Usando SQLite.NET en un proyecto compartido
SQLite.NET es una biblioteca de código abierto que permite agregar soporte de bases de datos
locales utilizando SQLite versión 3 en un proyecto Xamarin.Forms .
2. Cada tabla que se incluirá en la base de datos debe modelarse como una clase en el
Proyecto Compartido. Una tabla se define agregando al menos dos atributos en la clase:
Table (para la clase) y PrimaryKey (para una propiedad).
Para este ejemplo, se agrega una nueva clase llamada Song al proyecto compartido, que se define
de la siguiente manera:
using System;
using SQLite;
namespace SongsApp
{
[Table("Song")]
public class Song
{
[PrimaryKey]
public string ID { get; set; }
public string SongName { get; set; }
public string SingerName { get; set; }
}
}
3. A continuación, agregue una nueva clase llamada Database , que hereda de la clase
SQLiteConnection (incluida en SQLite.cs). En esta nueva clase, se define el código para el
acceso a la base de datos, la creación de tablas y las operaciones de CRUD para cada
tabla. El código de muestra se muestra a continuación:
using System;
using System.Linq;
using System.Collections.Generic;
using SQLite;
namespace SongsApp
{
https://riptutorial.com/es/home 172
public class BaseDatos : SQLiteConnection
{
public BaseDatos(string path) : base(path)
{
Initialize();
}
void Initialize()
{
CreateTable<Song>();
}
4. Como pudo ver en el paso anterior, el constructor de nuestra clase de Database de Database
incluye un parámetro de path , que representa la ubicación del archivo que almacena el
archivo de base de datos SQLite. Un objeto de Database estática se puede declarar en App.cs
El path es específico de la plataforma:
public App ()
{
string dbFile = "SongsDB.db3";
#if __ANDROID__
string docPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var dbPath = System.IO.Path.Combine(docPath, dbFile);
#else
#if __IOS__
string docPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string libPath = System.IO.Path.Combine(docPath, "..", "Library");
https://riptutorial.com/es/home 173
var dbPath = System.IO.Path.Combine(libPath, dbFile);
#else
var dbPath = System.IO.Path.Combine(ApplicationData.Current.LocalFolder.Path, dbFile);
#endif
#endif
DB = new Database(dbPath);
5. Ahora simplemente llame al objeto DB través de la clase de App cualquier momento que
necesite realizar una operación CRUD a la tabla de Songs . Por ejemplo, para insertar una
nueva Song después de que el usuario haya hecho clic en un botón, puede usar el siguiente
código:
App.DB.AddSong(song);
}
using SQLite.Net.Attributes;
namespace DatabaseEmployeeCreation.SqlLite
{
public class Employee
{
[PrimaryKey,AutoIncrement]
public int Eid { get; set; }
public string Ename { get; set; }
public string Address { get; set; }
public string phonenumber { get; set; }
public string email { get; set; }
}
https://riptutorial.com/es/home 174
}
using SQLite.Net;
//using SQLite.Net;
namespace DatabaseEmployeeCreation.SqlLite.ViewModel
{
public interface ISQLite
{
SQLiteConnection GetConnection();
}
}
4. Cree una clase para lógica de base de datos y siga los métodos a continuación.
public DatabaseLogic()
{
database = DependencyService.Get<ISQLite>().GetConnection();
// create the tables
database.CreateTable<Employee>();
}
https://riptutorial.com/es/home 175
database.Update(item);
return item.Eid;
}
else
{
return database.Insert(item);
}
}
}
</StackLayout>
</ContentPage>
EmployeeRegistration.cs
using DatabaseEmployeeCreation.SqlLite.ViewModel;
using DatabaseEmployeeCreation.SqlLite.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
https://riptutorial.com/es/home 176
using System.Threading.Tasks;
using Xamarin.Forms;
namespace DatabaseEmployeeCreation.SqlLite
{
public partial class EmployeeRegistration : ContentPage
{
private int empid;
private Employee obj;
public EmployeeRegistration()
{
InitializeComponent();
//AddressEntry.Text = obj.Address;
//emailEntry.Text = obj.email;
//nameEntry.Text = obj.Ename;
//phonenumberEntry.Text = obj.phonenumber;
https://riptutorial.com/es/home 177
nameEntry.Text = lst.Ename;
phonenumberEntry.Text = lst.phonenumber;
}
//void deleteClicked(object sender, EventArgs e)
//{
// var emp = (Employee)BindingContext;
// App.Database.DeleteItem(emp.Eid);
// this.Navigation.PopAsync();
//}
void DetailsClicked(object sender, EventArgs e)
{
var empcancel = (Employee)BindingContext;
this.Navigation.PushAsync(new EmployeeDetails());
}
// void speakClicked(object sender, EventArgs e)
// {
// var empspek = (Employee)BindingContext;
// //DependencyService.Get<ITextSpeak>().Speak(empspek.Address + " " +
empspek.Ename);
// }
}
}
using DatabaseEmployeeCreation;
using DatabaseEmployeeCreation.SqlLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace DatabaseEmployeeCreation.SqlLite.Views
{
public partial class EmployeeDetails : ContentPage
{
ListView lv = new ListView();
IEnumerable<Employee> lst;
https://riptutorial.com/es/home 178
public EmployeeDetails()
{
InitializeComponent();
displayemployee();
}
Text = "Details",
BackgroundColor = Color.Blue,
};
btn.Clicked += Btn_Clicked;
//IEnumerable<Employee> lst = App.Database.GetItems();
//IEnumerable<Employee> lst1 = App.Database.GetItemsNotDone();
//IEnumerable<Employee> lst2 = App.Database.GetItemsNotDone();
Content = new StackLayout()
{
Children = { btn },
};
}
lv.ItemsSource = lst;
lv.HasUnevenRows = true;
lv.ItemTemplate = new DataTemplate(typeof(OptionsViewCell));
}
}
int empid;
Button btnEdit;
public OptionsViewCell()
{
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
if (this.BindingContext == null)
return;
https://riptutorial.com/es/home 179
Text = obj.Ename,
};
https://riptutorial.com/es/home 180
{
BackgroundColor = Color.Gray,
Text = "Delete",
//WidthRequest = 15,
//HeightRequest = 20,
TextColor = Color.Red,
HorizontalOptions = LayoutOptions.EndAndExpand,
};
btnDelete.Clicked += BtnDelete_Clicked;
//btnDelete.PropertyChanged += BtnDelete_PropertyChanged;
https://riptutorial.com/es/home 181
await App.Current.MainPage.Navigation.PushModalAsync(new
EmployeeRegistration(empid));
}
}
// App.Database.DeleteItem(eid);
//}
}
using System;
using Xamarin.Forms;
using System.IO;
using DatabaseEmployeeCreation.Droid;
using DatabaseEmployeeCreation.SqlLite.ViewModel;
using SQLite;
using SQLite.Net;
[assembly: Dependency(typeof(SQLiteEmployee_Andriod))]
namespace DatabaseEmployeeCreation.Droid
{
public class SQLiteEmployee_Andriod : ISQLite
{
public SQLiteEmployee_Andriod()
{
}
https://riptutorial.com/es/home 182
//if (!File.Exists(path))
//{
// var s =
Forms.Context.Resources.OpenRawResource(Resource.Raw.EmployeeSQLite); // RESOURCE NAME ###
/// <summary>
/// helper method to get the database out of /raw/ and into the user filesystem
/// </summary>
void ReadWriteStream(Stream readStream, Stream writeStream)
{
int Length = 256;
Byte[] buffer = new Byte[Length];
int bytesRead = readStream.Read(buffer, 0, Length);
// write the required bytes
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = readStream.Read(buffer, 0, Length);
}
readStream.Close();
writeStream.Close();
}
}
}
https://riptutorial.com/es/home 183
Lea Trabajar con bases de datos locales en línea: https://riptutorial.com/es/xamarin-
forms/topic/5997/trabajar-con-bases-de-datos-locales
https://riptutorial.com/es/home 184
Capítulo 39: Unidad de Pruebas BDD en
Xamarin. Formas
Observaciones
• El contenedor / resolución DI que utilizamos internamente en esta biblioteca es Autofac.
• El marco de prueba es NUnit 3x.
• Debería poder usar esta biblioteca con cualquier framework Xamarin.Forms
• Fuente y proyecto de ejemplo disponible aquí.
Examples
Sencillo flujo de especificaciones para probar los comandos y la navegación
con NUnit Test Runner
Desarrollé una biblioteca que permite utilizar Specflow con Xamarin.Forms para implementar
fácilmente sus funciones desde las definiciones de Scenarios hasta ViewModel,
independientemente de cualquier marco MVVM utilizado para la aplicación (como XLabs ,
MVVMCross , Prism )
Uso:
• Si aún no lo tiene, instale la extensión de estudio visual de flujo de especificaciones desde
aquí (o desde su IDE de estudio visual):
https://visualstudiogallery.msdn.microsoft.com/c74211e7-cb6e-4dfa-855d-df0ad4a37dd6
https://riptutorial.com/es/home 185
• Agregue el paquete SpecFlow.Xamarin.Forms de nuget a sus proyectos de prueba.
• Agregue una clase a su proyecto de prueba que herede 'TestApp', y registre sus pares de
vistas / modelos de vista, así como agregue cualquier registro DI, como se muestra a
continuación:
• Agregue una clase de SetupHook a su proyecto de prueba, para agregar los enlaces de
Specflow. Deberá iniciar la aplicación de prueba como se indica a continuación,
proporcionando la clase que creó anteriormente y el modelo de vista inicial de su aplicación:
[Binding]
public class SetupHooks : TestSetupHooks
{
/// <summary>
/// The before scenario.
/// </summary>
[BeforeScenario]
public void BeforeScenario()
{
// bootstrap test app with your test app and your starting viewmodel
new TestAppBootstrap().RunApplication<DemoAppTest, MainViewModel>();
}
}
• Necesitará agregar un bloque catch a sus vistas xamarin.forms codebehind para ignorar el
marco de xamarin.forms forzándolo a ejecutar la aplicación ui (algo que no queremos
hacer):
public YourView()
{
try
{
InitializeComponent();
}
catch (InvalidOperationException soe)
{
if (!soe.Message.Contains("MUST"))
throw;
https://riptutorial.com/es/home 186
}
}
• Cree / genere una clase de paso que herede TestStepBase, pasando el parámetro
sceneryContext a la base.
• Utilice los servicios de navegación y los ayudantes para navegar, ejecutar comandos y
probar sus modelos de vista:
[Binding]
public class GeneralSteps : TestStepBase
{
public GeneralSteps(ScenarioContext scenarioContext)
: base(scenarioContext)
{
// you need to instantiate your steps by passing the scenarioContext to the base
}
Resolver.Instance.Resolve<INavigationService>().CurrentViewModelType.ShouldEqualType<MainViewModel>();
Para agregar al primer ejemplo, para probar las declaraciones de navegación que se producen
dentro de la aplicación, debemos proporcionar un ViewModel con un gancho a la navegación.
Lograr esto:
https://riptutorial.com/es/home 187
INavigation Navigation { get; set; }
• El marco de prueba recogerá y gestionará la navegación interna.
• Puede usar cualquier marco MVVM para su aplicación (como XLabs , MVVMCross , Prism ,
por nombrar algunos. Mientras la interfaz IViewModel esté implementada en su ViewModel,
el marco lo recogerá.
https://riptutorial.com/es/home 188
Capítulo 40: Usando ListViews
Introducción
Esta documentación detalla cómo usar los diferentes componentes de Xamarin Forms ListView
Examples
Tirar para actualizar en XAML y codificar detrás
Para habilitar Pull to Refresh en un ListView en Xamarin, primero debe especificar que
PullToRefresh está habilitado y luego especificar el nombre del comando que desea invocar
cuando se PullToRefresh ListView :
itemListView.IsPullToRefreshEnabled = true;
itemListView.RefreshCommand = Refresh;
https://riptutorial.com/es/home 189
Capítulo 41: Xamarin.Formas Células
Examples
EntryCell
Un EntryCell es una celda que combina las capacidades de una etiqueta y una entrada. El
EntryCell puede ser útil en escenarios cuando se construye alguna funcionalidad dentro de su
aplicación para recopilar datos del usuario. Se pueden colocar fácilmente en un TableView y ser
tratados como un formulario simple.
XAML
Código
SwitchCell
Un SwitchCell es una celda que combina las capacidades de una etiqueta y un interruptor de
encendido y apagado. Un SwitchCell puede ser útil para activar y desactivar la funcionalidad, o
incluso las preferencias de usuario u opciones de configuración.
XAML
https://riptutorial.com/es/home 190
<SwitchCell Text="Switch It Up!" />
Código
TextCell
Un TextCell es una celda que tiene dos áreas de texto separadas para mostrar datos. Un TextCell
se usa normalmente con fines informativos en los controles TableView y ListView. Las dos áreas
de texto están alineadas verticalmente para maximizar el espacio dentro de la celda. Este tipo de
celda también se usa comúnmente para mostrar datos jerárquicos, por lo que cuando el usuario
toca esta celda, navegará a otra página.
XAML
Código
https://riptutorial.com/es/home 191
ImageCell
Un ImageCell es exactamente lo que suena. Es una simple celda que contiene solo una imagen.
Este control funciona de manera muy similar a un control de imagen normal, pero con menos
campanas y silbidos.
XAML
<ImageCell ImageSource="http://d2g29cya9iq7ip.cloudfront.net/content/imag
es/company/aboutus-video-bg.png?v=25072014072745")),
Text="This is some text"
Detail="This is some detail" />
Código
https://riptutorial.com/es/home 192
ViewCell
Usted puede considerar a un ViewCell una pizarra en blanco. Es tu lienzo personal crear una
celda que se vea exactamente como la quieres. Incluso puede componerlo de instancias de otros
objetos de Vista combinados con controles de Diseño. Sólo estás limitado por tu imaginación. Y
tal vez el tamaño de la pantalla.
XAML
<ViewCell>
<ViewCell.View>
<StackLayout>
<Button Text="My Button"/>
Código
https://riptutorial.com/es/home 193
Lea Xamarin.Formas Células en línea: https://riptutorial.com/es/xamarin-
forms/topic/7370/xamarin-formas-celulas
https://riptutorial.com/es/home 194
Capítulo 42: Xamarin.Formas vistas
Examples
Botón
XAML
<Button
x:Name="MyButton"
Text="Click Me!"
TextColor="Red"
BorderColor="Blue"
VerticalOptions="Center"
HorizontalOptions="Center"
Clicked="Button_Clicked"/>
Código
https://riptutorial.com/es/home 195
Selector de fechas
Muy a menudo dentro de las aplicaciones móviles, habrá una razón para tratar con las fechas.
Cuando trabaje con fechas, probablemente necesitará algún tipo de información del usuario para
seleccionar una fecha. Esto podría ocurrir cuando se trabaja con una aplicación de calendario o
calendario. En este caso, es mejor proporcionar a los usuarios un control especializado que les
permita elegir una fecha de manera interactiva, en lugar de requerir que los usuarios escriban una
fecha manualmente. Aquí es donde el control DatePicker es realmente útil.
XAML
Código
https://riptutorial.com/es/home 196
Entrada
La Vista de entrada se utiliza para permitir a los usuarios escribir una sola línea de texto. Esta
única línea de texto se puede usar para múltiples propósitos, incluyendo el ingreso de notas
básicas, credenciales, URL y más. Esta vista es una vista multipropósito, lo que significa que si
necesita escribir texto regular o quiere ocultar una contraseña, todo se hace a través de este
único control.
XAML
Código
https://riptutorial.com/es/home 197
Editor
El Editor es muy similar a la Entrada, ya que permite a los usuarios ingresar texto de forma libre.
La diferencia es que el Editor permite la entrada multilínea, mientras que la entrada solo se utiliza
para la entrada de una sola línea. La Entrada también proporciona algunas propiedades más que
el Editor para permitir una mayor personalización de la Vista.
XAML
<Editor HorizontalOptions="Fill"
VerticalOptions="Fill"
Keyboard="Chat"/>
Código
https://riptutorial.com/es/home 198
Imagen
Las imágenes son partes muy importantes de cualquier aplicación. Brindan la oportunidad de
inyectar elementos visuales adicionales, así como de marca en su aplicación. Sin mencionar que
las imágenes suelen ser más interesantes de ver que el texto o los botones. Puede usar una
imagen como elemento independiente dentro de su aplicación, pero un elemento de imagen
también se puede agregar a otros elementos de vista, como un botón.
XAML
Código
https://riptutorial.com/es/home 199
Etiqueta
Lo creas o no, el Label es una de las clases de View más importantes y menos apreciadas, no
solo en Xamarin.Forms, sino en el desarrollo de IU en general. Se ve como una línea de texto
bastante aburrida, pero sin esa línea de texto sería muy difícil transmitir ciertas ideas al usuario.
Los controles de etiqueta se pueden usar para describir lo que el usuario debe ingresar en un
editor o control de entrada. Pueden describir una sección de la interfaz de usuario y darle
contexto. Se pueden utilizar para mostrar el total en una aplicación de calculadora. Sí, la etiqueta
es realmente el control más versátil en su bolsa de herramientas que puede no siempre despertar
mucha atención, pero es la primera que se observa si no está allí.
XAML
Código
https://riptutorial.com/es/home 200
Lea Xamarin.Formas vistas en línea: https://riptutorial.com/es/xamarin-forms/topic/7369/xamarin-
formas-vistas
https://riptutorial.com/es/home 201
Capítulo 43: Xamarin.Forms Page
Examples
TabbedPage
XAML
Código
https://riptutorial.com/es/home 202
}
};
var tabbedPage = new TabbedPage {
Children = { page1, page2 }
};
Pagina de contenido
XAML
Código
https://riptutorial.com/es/home 203
MasterDetailPage
XAML
Código
TextColor = Color.Black,
Text = "This is the Master page.",
HorizontalOptions = LayoutOptions.Center,
https://riptutorial.com/es/home 204
VerticalOptions = LayoutOptions.Center
}
},
Detail = new ContentPage {
Content = new Label {
Title = "Detail",
Text = "This is the Detail page.",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}
}
};
https://riptutorial.com/es/home 205
Creditos
S.
Capítulos Contributors
No
¿Ciclo de vida de la
aplicación
Xamarin.Forms
2 Zverev Eugene
genérico?
Dependiente de la
plataforma!
Acceso a funciones
4 nativas con Gerald Versluis, hankide, hvaughan3, Sergey Metlov
DependencyService
Ajustes visuales
5 específicos de la Alois, GalaxiaGuy, Paul
plataforma.
Almacenamiento en
6 Sergey Metlov
caché
AppSettings Reader
7 Ben Ishiyama-Levy, GvSharma
en Xamarin.Forms
CarouselView -
9 Versión de dpserge
prelanzamiento
Complemento
10 Eng Soon Cheah
Xamarin
Comportamiento
11 específico de la Ege Aydın
plataforma
https://riptutorial.com/es/home 206
Creando controles
12 hvaughan3, spaceplane, Yehor Hromadskyi
personalizados
Diseños de formas
14 Eng Soon Cheah, Gerald Versluis, Lucas Moura Veloso
de Xamarin
Disparadores y
15 hamalaiv, hvaughan3
comportamientos
Disposición relativa
16 Ege Aydın
de Xamarin
Fuentes
20 personalizadas en Roma Rudyak
estilos
Manejo de
23 Yehor Hromadskyi
excepciones
Selector de
contactos - Formas
30 Pucho Eric
Xamarin (Android y
iOS)
31 Servicios de RIYAZ
https://riptutorial.com/es/home 207
dependencia
Trabajando con
32 Taras Shevchuk
Mapas
Unidad de Pruebas
34 BDD en Xamarin. Ben Ishiyama-Levy
Formas
Xamarin.Formas
36 Eng Soon Cheah
Células
Xamarin.Formas
37 Aaron Thompson, Eng Soon Cheah
vistas
https://riptutorial.com/es/home 208