Benutzer:MovGP0/Xamarin/Custom Renderer

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen
   MovGP0        Über mich        Hilfen        Artikel        Weblinks        Literatur        Zitate        Notizen        Programmierung        MSCert        Physik      


Custom Renderer

[Bearbeiten | Quelltext bearbeiten]

PCL or Shared Project

[Bearbeiten | Quelltext bearbeiten]
using Xamarin.Forms;

// derives from BindableObject
public sealed class RoundedBoxView : BoxView
{
    public static readonly BindableProperty CornerRadiusProperty = 
        BindableProperty.Create(nameof(CornerRadius), typeof(double), typeof(RoundedBoxView), 0.0);
    
    public double CornerRadius 
    {
        get { return (double)GetValue(CornerRadiusProperty); }
        set { SetValue(CornerRadiusProperty, value); }
    }

    public static readonly BindableProperty StrokeProperty = 
        BindableProperty.Create(nameof(StrokeRadius), typeof(Color), typeof(RoundedBoxView), Colors.Transparent);
    
    public Color Stroke
    {
        get { return (Color)GetValue(StrokeProperty); }
        set { SetValue(StrokeProperty, value); }
    }

    public static readonly BindableProperty StrokeThicknessProperty = 
        BindableProperty.Create(nameof(StrokeThickness), typeof(double), typeof(RoundedBoxView), 1.0);
    
    public double StrokeThickness
    {
        get { return (double)GetValue(StrokeThicknessProperty); }
        set { SetValue(StrokeThicknessProperty, value); }
    }
}
<ContentPage xmlns:local="clr-namespace:NAMESPACE;assembly=ASSEMBLYNAME">
    <local:RoundedBoxView CornerRadius="5" StrokeThickness="3" Stroke="Red" />
</ContentPage>
using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Graphics;

[assembly: ExportRendererAttribute(typeof(RoundedBoxView), typeof(RoundedBoxViewRenderer))]

namespace MyApp.Android
{
    // derives from VisualElementRenderer<BoxView>
    // derives from Android.Views.View
    public class RoundedBoxViewRenderer : BoxRenderer
    {
       public RoundedBoxViewRenderer()
       {
           SetWillNotDraw(false);
       }

        public override void Draw(Canvas canvas)
        {
            var view = (RoundedBoxView)Element;
            var boundary = new Rect();
            GetDrawingRect(boundary);
            boundary.Inset((int)view.StrokeThickness, (int)view.StrokeThickness);
            
            var fillPaint = new Paint 
            {
                Color = view.Color.ToAndroid(), 
                AntiAlias = true 
            };
            canvas.DrawRoundRect(new RectF(boundary), (float)view.CornerRadius, (float)view.CornerRadius, fillPaint);
            
            var borderPaint = new Paint 
            { 
                Color = view.Stroke.ToAndroid(), 
                StrokeWidth = (float)view.StrokeThickness, 
                AntiAlias = true 
            };
            borderPaint.SetStyle(Paint.Style.Stroke);
            canvas.DrawRoundRect(new RectF(boundary), (float)view.CornerRadius, (float)view.CornerRadius, borderPaint);

            // base.Draw(canvas);
        }
    }
}
Derive from existing renderer
using System;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using MonoTouch.UIKit;
using MonoTouch.CoreGraphics;
using MonoTouch.CoreLocation;

[assembly: ExportRendererAttribute(typeof(RoundedBoxView), typeof(RoundedBoxViewRenderer))]

namespace MyApp.iOS
{
    // derives from VisualElementRenderer<BoxView>
    // derives from UIView
    public class RoundedBoxViewRenderer : BoxRenderer
    {
        public override void Draw(RectangleF rect)
        {
            var view = (RoundedBoxView)Element;
            using(context = UIGraphics.GetCurrentContext()){
                context.SetFillColor(view.Color.ToCGColor());
                context.SetStrokeColor(view.Stroke.ToCGColor());
                context.SetLineWidth(view.StrokeThickness);

                var boundary = Bounds.Inset((int)view.StrokeThickness, (int)view.StrokeThickness);
                var cornerRadius = (float)view.CornerRaduis;
                var radius = Math.Max(0f, Math.Min(cornerRadius), Math.Max(boundary.Height/2f, boundary.Width/2f)));
                var path = CGPath.FromRoundedRect(boundary, raduis, radius);
                context.AddPath(path);
                context.Draw(CGPathDrawingMode.FillStroke);
            }
        }

        public override void OnElementPropertyChanged(object sender, PreopertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(sender, args);

            if(args.PropertyName == RoundedBoxView.CornerRadiusProperty.PropertyName 
            || args.PropertyName == RoundedBoxView.StrokeProperty.PropertyName
            || args.PropertyName == RoundedBoxView.StrokeThicknessProperty.PropertyName)
            {
                SetNeedsDisplay();
            }
        }
    }
}
Implement custom renderer
using System;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using MonoTouch.UIKit;
using MonoTouch.CoreGraphics;
using MonoTouch.CoreLocation;

[assembly: ExportRendererAttribute(typeof(RoundedBoxView), typeof(RoundedBoxViewRenderer))]

namespace MyApp.iOS
{
    public class RoundedBoxViewRenderer : ViewRenderer<RoundedBoxView, UIView>
    {
        public override void OnElementChanged(object sender, PreopertyChangedEventArgs args)
        {
            base.OnElementChanged(args);
            var view = e.NewElement;
            if(view == null) return;

            var shadowView = new UIView();
            
            var childView = new UIView 
            {
                BackgroundColor = view.Color.ToUIColor(), 
                Layer = {
                    CornerRadius = (float) view.CornerRadius, 
                    BorderColor = view.Stroke.ToCGColor(), 
                    BorderWidth = view.StrokeThickness, 
                    MasksToBounds = true
                }, 
                AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
            };
            shadowView.Add(childView);

            if(view.HasShadow)
            {
                RenderShadow(shadowView);
            }

            SetNativeControl(shadowView);
        }

        private void RenderShadow(View shadowView)
        {
            shadowView.Layer.ShadowColor = UIColor.Black.CGColor, 
            shadowView.Layer.ShadowOffset = new SizeF(3,3);
            shadowView.Layer.ShadowOpacity = 1;
            shadowView.Layer.ShadowRaduis = 5;
        }

        private void RenderNoShadow(View shadowView)
        {
            shadowView.Layer.ShadowColor = UIColor.Clear.CGColor, 
            shadowView.Layer.ShadowOffset = new SizeF();
            shadowView.Layer.ShadowOpacity = 0;
            shadowView.Layer.ShadowRaduis = 0;
        }

        public override void OnElementPropertyChanged(object sender, PreopertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(sender, args);

            if(args.PropertyName == RoundedBoxView.CornerRadiusProperty.PropertyName)
            {
                childView.Layer.CornerRadius = (float)Element.CornerRadius;
            }
            else if(args.PropertyName == RoundedBoxView.StrokeProperty.PropertyName)
            {
                childView.Layer.BorderColor = Element.Stroke.ToCGColor();
            }
            else if(args.PropertyName == RoundedBoxView.StrokeThicknessProperty.PropertyName)
            {
                childView.Layer.BorderWidth = (float)Element.StrokeThickness;
            }
            else if(args.PropertyName == RoundedBoxView.ColorProperty.PropertyName)
            {
                childView.BackgroundColor = Element.Color.ToUIColor();
            }
            else if(args.PropertyName == RoundedBoxView.HasShadowProperty.PropertyName)
            {
                if(Element.HasShadow)
                {
                    RenderShadow(NativeView);
                }
                else
                {
                    RenderNoShadow(NativeView);
                }
            }
        }
    }
}