Personalizzazione di un elemento ContentPage
ContentPage è un elemento visivo con visualizzazione singola che occupa la maggior parte dello schermo. Questo articolo illustra come creare un renderer personalizzato per la pagina ContentPage che consente agli sviluppatori di eseguire l'override del rendering nativo predefinito usando una personalizzazione specifica della piattaforma.
Ogni Xamarin.Forms controllo ha un renderer a corredo per ogni piattaforma che crea un'istanza di un controllo nativo. ContentPage
Quando un oggetto viene sottoposto a rendering da un'applicazioneXamarin.Forms, in iOS viene creata un'istanza della PageRenderer
classe , che a sua volta crea un'istanza di un controllo nativoUIViewController
. Nella piattaforma Android la classe PageRenderer
crea un'istanza di un controllo ViewGroup
. Nella piattaforma UWP (Universal Windows Platform) la classe PageRenderer
crea un'istanza di un controllo FrameworkElement
. Per altre informazioni sulle classi di controllo native e del renderer a cui Xamarin.Forms viene eseguito il mapping dei controlli, vedere Classi di base del renderer e controlli nativi.
Il diagramma seguente illustra la relazione tra la classe ContentPage
e i controlli nativi corrispondenti che la implementano:
È possibile sfruttare il processo di rendering per implementare personalizzazioni specifiche della piattaforma creando un renderer personalizzato per una classe ContentPage
in ogni piattaforma. Il processo per eseguire questa operazione è il seguente:
- Creare una Xamarin.Forms pagina.
- Utilizzare la pagina da Xamarin.Forms.
- Creare il renderer personalizzato per la pagina in ogni piattaforma.
Verrà ora discusso un elemento alla volta per implementare un oggetto CameraPage
che rende disponibile un feed di fotocamera live e la possibilità di scattare una foto.
Creazione della Xamarin.Forms pagina
Un oggetto non modificato ContentPage
può essere aggiunto al progetto condiviso Xamarin.Forms , come illustrato nell'esempio di codice XAML seguente:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomRenderer.CameraPage">
<ContentPage.Content>
</ContentPage.Content>
</ContentPage>
In modo analogo, anche il file code-behind per l'oggetto ContentPage
deve rimanere invariato, come illustrato nell'esempio di codice seguente:
public partial class CameraPage : ContentPage
{
public CameraPage ()
{
// A custom renderer is used to display the camera UI
InitializeComponent ();
}
}
L'esempio di codice seguente illustra come creare la pagina in C#:
public class CameraPageCS : ContentPage
{
public CameraPageCS ()
{
}
}
Per visualizzare il feed di fotocamera live in ogni piattaforma verrà usata un'istanza di CameraPage
. La personalizzazione del controllo avviene nel renderer personalizzato. Non è pertanto necessaria alcuna implementazione aggiuntiva nella classe CameraPage
.
Utilizzo della Xamarin.Forms pagina
Il valore vuoto CameraPage
deve essere visualizzato dall'applicazione Xamarin.Forms . Ciò accade quando si tocca un pulsante nell'istanza di MainPage
che a sua volta esegue il metodo OnTakePhotoButtonClicked
, come illustrato nell'esempio di codice seguente:
async void OnTakePhotoButtonClicked (object sender, EventArgs e)
{
await Navigation.PushAsync (new CameraPage ());
}
Questo codice passa semplicemente all'oggetto CameraPage
nel quale i renderer personalizzati personalizzeranno l'aspetto della pagina in ogni piattaforma.
Creazione del renderer di pagina in ogni piattaforma
Il processo di creazione della classe di renderer personalizzato è il seguente:
- Creare una sottoclasse della classe
PageRenderer
. - Eseguire l'override del metodo
OnElementChanged
che esegue il rendering della pagina nativa e scrivere la logica per personalizzare la pagina. IlOnElementChanged
metodo viene chiamato quando viene creato il controllo corrispondente Xamarin.Forms . - Aggiungere un
ExportRenderer
attributo alla classe renderer di pagina per specificare che verrà usato per eseguire il rendering della Xamarin.Forms pagina. Questo attributo viene usato per registrare il renderer personalizzato con Xamarin.Forms.
Nota
La specifica di un renderer di pagina nel progetto di ogni piattaforma è facoltativa. Se non si registra un renderer personalizzato, verrà usato il renderer predefinito per la pagina.
Il diagramma seguente illustra le responsabilità di ogni progetto nell'applicazione di esempio, insieme alla relazione tra di esse:
Il rendering dell'istanza di CameraPage
viene eseguito dalle classi CameraPageRenderer
specifiche della piattaforma che derivano tutte dalla classe PageRenderer
per la piattaforma. Ciò determina il rendering di ogni istanza di CameraPage
con un feed di fotocamera live, come illustrato negli screenshot seguenti:
La PageRenderer
classe espone il OnElementChanged
metodo , che viene chiamato quando viene creata la pagina per eseguire il Xamarin.Forms rendering del controllo nativo corrispondente. Questo metodo accetta un parametro ElementChangedEventArgs
che contiene le proprietà OldElement
e NewElement
. Queste proprietà rappresentano l'elemento Xamarin.Forms a cui è stato associato il renderer e l'elemento Xamarin.Forms a cui è associato il renderer. Nell'applicazione di esempio la proprietà OldElement
sarà null
e la proprietà NewElement
conterrà un riferimento all'istanza di CameraPage
.
La personalizzazione della pagina nativa deve essere eseguita in una versione sostituita del metodo OnElementChanged
nella classe CameraPageRenderer
. È possibile ottenere un riferimento all'istanza Xamarin.Forms della pagina di cui viene eseguito il rendering tramite la Element
proprietà .
Ogni classe renderer personalizzata è decorata con un ExportRenderer
attributo che registra il renderer con Xamarin.Forms. L'attributo accetta due parametri: il nome del tipo della pagina di cui viene eseguito il Xamarin.Forms rendering e il nome del tipo del renderer personalizzato. Il prefisso assembly
dell'attributo specifica che l'attributo viene applicato all'intero assembly.
Le sezioni seguenti illustrano l'implementazione del renderer personalizzato CameraPageRenderer
per ogni piattaforma.
Creazione del renderer di pagina in iOS
L'esempio di codice seguente illustra il renderer di pagina per la piattaforma iOS:
[assembly:ExportRenderer (typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CustomRenderer.iOS
{
public class CameraPageRenderer : PageRenderer
{
...
protected override void OnElementChanged (VisualElementChangedEventArgs e)
{
base.OnElementChanged (e);
if (e.OldElement != null || Element == null) {
return;
}
try {
SetupUserInterface ();
SetupEventHandlers ();
SetupLiveCameraStream ();
AuthorizeCameraUse ();
} catch (Exception ex) {
System.Diagnostics.Debug.WriteLine (@" ERROR: ", ex.Message);
}
}
...
}
}
La chiamata al metodo OnElementChanged
della classe di base crea un'istanza di un controllo UIViewController
iOS. Il rendering del flusso della fotocamera live viene eseguito solo a condizione che il renderer non sia già collegato a un elemento esistente Xamarin.Forms e a condizione che esista un'istanza di pagina di cui viene eseguito il rendering dal renderer personalizzato.
La pagina viene quindi personalizzata da una serie di metodi che usano le API AVCapture
per consentire lo streaming live dalla fotocamera e la possibilità di scattare una foto.
Creazione del renderer di pagina in Android
L'esempio di codice seguente illustra il renderer di pagina per la piattaforma Android:
[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CustomRenderer.Droid
{
public class CameraPageRenderer : PageRenderer, TextureView.ISurfaceTextureListener
{
...
public CameraPageRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
try
{
SetupUserInterface();
SetupEventHandlers();
AddView(view);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(@" ERROR: ", ex.Message);
}
}
...
}
}
La chiamata al metodo OnElementChanged
della classe di base crea un'istanza di un controllo ViewGroup
Android, ovvero un gruppo di visualizzazioni. Il rendering del flusso della fotocamera live viene eseguito solo a condizione che il renderer non sia già collegato a un elemento esistente Xamarin.Forms e a condizione che esista un'istanza di pagina di cui viene eseguito il rendering dal renderer personalizzato.
La pagina viene quindi personalizzata richiamando una serie di metodi che usano l'API Camera
per consentire lo streaming live dalla fotocamera e la possibilità di scattare una foto prima che venga richiamato il metodo AddView
per aggiungere l'interfaccia utente dello streaming live della fotocamera al controllo ViewGroup
. Tenere presente che in Android è anche necessario eseguire l'override del metodo OnLayout
per eseguire operazioni di misura e layout nella visualizzazione.
Creazione del renderer di pagina in UWP
L'esempio di codice seguente illustra il renderer di pagina per la piattaforma UWP:
[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CustomRenderer.UWP
{
public class CameraPageRenderer : PageRenderer
{
...
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
try
{
...
SetupUserInterface();
SetupBasedOnStateAsync();
this.Children.Add(page);
}
...
}
protected override Size ArrangeOverride(Size finalSize)
{
page.Arrange(new Windows.Foundation.Rect(0, 0, finalSize.Width, finalSize.Height));
return finalSize;
}
...
}
}
La chiamata al metodo OnElementChanged
della classe di base crea un'istanza di un controllo FrameworkElement
in cui viene eseguito il rendering della pagina. Il rendering del flusso della fotocamera live viene eseguito solo a condizione che il renderer non sia già collegato a un elemento esistente Xamarin.Forms e a condizione che esista un'istanza di pagina di cui viene eseguito il rendering dal renderer personalizzato. La pagina viene quindi personalizzata richiamando una serie di metodi che usano l'API MediaCapture
per consentire lo streaming live dalla fotocamera e la possibilità di scattare una foto prima che la pagina personalizzata sia aggiunta alla raccolta Children
per la visualizzazione.
Quando si implementa un renderer personalizzato che deriva da PageRenderer
in UWP, è consigliabile implementare anche il metodo ArrangeOverride
per disporre i controlli della pagina perché il renderer di base non è in grado di eseguire questa operazione. In caso contrario, verrà restituita una pagina vuota. In questo esempio il metodo ArrangeOverride
chiama pertanto il metodo Arrange
sull'istanza Page
.
Nota
In un'applicazione UWP è importante arrestare ed eliminare gli oggetti che consentono l'accesso alla fotocamera. Questi possono infatti interferire con altre applicazioni che tentano di accedere alla fotocamera del dispositivo. Per altre informazioni, vedere Display the camera preview (Visualizzare l'anteprima della fotocamera).
Riepilogo
Questo articolo ha illustrato come creare un renderer personalizzato per la pagina ContentPage
che consente agli sviluppatori di eseguire l'override del rendering nativo predefinito usando una personalizzazione specifica della piattaforma. ContentPage
è un elemento visivo con visualizzazione singola che occupa la maggior parte dello schermo.