使用自定义渲染器强制重绘Xamarin.Forms视图

时间:2014-08-04 19:51:50

标签: android ios xamarin xamarin.forms custom-renderer

我有一个可视化元素MyButton,其中包含为iOS实现的自定义渲染器。

共享:

namespace RendererTest
{
    public class MyButton: Button
    {
        public Color BoundaryColor { get; set; }
    }

    public static class App
    {
        public static Page GetMainPage()
        {    
            var button = new MyButton { Text = "Click me!", BoundaryColor = Color.Red };
            button.Clicked += (sender, e) => (sender as MyButton).BoundaryColor = Color.Blue;
            return new ContentPage { Content = button };
        }
    }
}

的iOS:

[assembly:ExportRenderer(typeof(MyButton), typeof(MyButtonRenderer))]

namespace RendererTest.iOS
{
    public class MyButtonRenderer: ButtonRenderer
    {
        public override void Draw(RectangleF rect)
        {
            using (var context = UIGraphics.GetCurrentContext()) {
                context.SetFillColor(Element.BackgroundColor.ToCGColor());
                context.SetStrokeColor((Element as MyButton).BoundaryColor.ToCGColor());
                context.SetLineWidth(10);
                context.AddPath(CGPath.FromRect(Bounds));
                context.DrawPath(CGPathDrawingMode.FillStroke);
            }
        }
    }
}

按下按钮时,红色边界应变为蓝色。显然渲染器没有注意到已更改的属性。如何触发重绘?

(此示例适用于iOS。但我的问题也适用于Android。)

2 个答案:

答案 0 :(得分:9)

首先,将BoundaryColor转换为可绑定属性。这不是必需的,触发INPC事件就足够了,但是你可以绑定它:

public static readonly BindableProperty BoundaryColorProperty =
    BindableProperty.Create ("BoundaryColor", typeof(Color), typeof(MyButton), Color.Default);

public Color BoundaryColor {
    get { return (Color)GetValue (BoudaryColorProperty); }
    set { SetValue (BoundaryColorProperty, value); }
}

然后,在你的渲染器中:

protected override void OnElementPropertyChanged (object sender, PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged (sender, e);

    if (e.PropertyName == MyButton.BoundaryColorProperty.PropertyName)
        SetNeedsDisplay ();
}

答案 1 :(得分:7)

需要进行两项修改:

  1. OnPropertyChanged属性的设置者中调用BoundaryColor

    public class MyButton: Button
    {
        Color boundaryColor = Color.Red;
    
        public Color BoundaryColor {
            get {
                return boundaryColor;
            }
            set {
                boundaryColor = value;
                OnPropertyChanged();  // <-- here
            }
        }
    }
    
  2. 使用OnElementChanged的{​​{1}}方法订阅活动:

    MyButtonRenderer
  3. 注意:public class MyButtonRenderer: ButtonRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Button> e) { base.OnElementChanged(e); Element.PropertyChanged += (s_, e_) => SetNeedsDisplay(); // <-- here } public override void Draw(RectangleF rect) { // ... } } 内订阅似乎很重要,而不是构造函数。否则会引发OnElementChanged