Anpassen von vorhandenen Elementen mit abgeleiteten Renderern

Abgeschlossen

Wir betrachten nun die Anforderungen eines Label mit ein Schlagschatteneffekt. Da bereits ein Label integriert ist, ist eine der Optionen die Anpassung des vorhandenen Renderers. In einer realen App würden wir auch erwägen, einen Xamarin.Forms-Effekt zu verwenden, was die beste Möglichkeit ist, kleine Änderungen integrierter Steuerelemente durchzuführen. Die Anpassung eines Renderers empfiehlt sich, wenn viele Änderungen erforderlich oder die Änderungen derart sind, dass Effekte nicht funktionieren. Jetzt verwenden wir nur die Option zur Anpassung des Renderers.

In dieser Lerneinheit sehen wir, wie wir den vorhandenen Label-Renderer anpassen können, um einen Schlagschatteneffekt hinzuzufügen.

Erstellen eines abgeleiteten Elements

Beim Anpassen vorhandenen Verhaltens möchten wir in der Regel ein neues Element erstellen, das das vorhandene Element als Basisklasse verwendet, z.B.:

public class ShadowLabel : Xamarin.Forms.Label{
}

Wir können das neue Element dann überall verwenden, wo wir normalerweise ein Label verwenden. Das Ableiten einer neuen Elementklasse ist nicht erforderlich, ermöglicht uns jedoch die einfachere Implementierung, wenn wir nur ein reguläres benötigen. Zudem vereinfacht es die Problembehandlung, falls Probleme mit dieser Anpassung auftreten.

Erstellen von abgeleiteten Renderern

Da Renderer plattformspezifisch sind, müssen wir den Renderer für jede Plattform anpassen. Wir erstellen benutzerdefinierte Rendererklassen, die von den ursprünglichen Renderern abgeleitet werden.

In Android sieht unsere Rendererklasse wie folgt aus:

public class ShadowLabelRenderer : Xamarin.Forms.Platform.Android.LabelRenderer
{
    ...
}

In iOS sieht unsere Rendererklasse wie folgt aus:

public class ShadowLabelRenderer : Xamarin.Forms.Platform.iOS.LabelRenderer
{
    ...
}

Hinzufügen von Verhalten zu Renderern

Der Lebenszyklus eines Renderers beginnt mit einem Aufruf der OnElementChanged-Methode. Diese Methode wird aufgerufen, wenn der Renderer das erste Mal mit einem Xamarin.Forms-Element gekoppelt wird. Eine der Aktionen, die OnElementChanged ausführt, ist das Erstellen des nativen Steuerelements. Da wir eine vorhandene Implementierung anpassen, können wir in diesem Fall unsere Basisklassenimplementierung verwenden:

protected override void OnElementChanged(...)
{
    base.OnElementChanged(e);
    ...
}

Der Aufruf von base.OnElementChanged erstellt das native Steuerelement und legt die base.Control-Eigenschaft fest. Unser benutzerdefinierter Renderer kann dann mithilfe der nativen API jede erforderliche Anpassung durchführen.

Hier ist ein iOS-Beispiel:

public class ShadowLabelRenderer : Xamarin.Forms.Platform.iOS.LabelRenderer
{
    protected override void OnElementChanged( ... )
    {
        base.OnElementChanged(e); // The base class will set the Control property

        UIKit.UILabel theControl = base.Control; // base.Control is strongly typed to the native object (UILabel)

        theControl.Layer.ShadowOpacity = 1.0f; // Use native API to customize
        ...
    }
}

Registrieren und Verwenden des angepassten Renderers

Jetzt müssen wir sicherstellen, dass Xamarin.Forms immer dann, wenn es unser abgeleitetes Element rendert, unseren abgeleiteten Renderer verwendet. Wir erreichen dies durch Registrieren des Paars mit dem Assemblyattribut ExportRenderer:

[assembly: ExportRenderer(typeof(ShadowLabel), typeof(ShadowLabelRenderer))]

Wir verwenden das neu abgeleitete Element dann in gleicher Weise in Code oder XAML, wie wir ein integriertes Element verwenden würden:

var shadowyLabel = new ShadowLabel();
mainGrid.Children.Add(shadowyLabel);
<ContentPage xmlns:local="clr-namespace:NoteApp" ...>
    <local:ShadowLabel Text="I'm shadowy" />
</ContentPage>