Xamarin.Forms / iOS-隐藏的父控件无法使用自定义渲染器正确渲染其子级

时间:2019-04-25 14:20:01

标签: xamarin.forms xamarin.ios

我的iOS渲染器上遇到一个Draw问题,因为我拥有一个自定义控件。此控件(简称为GradientFrame)位于带有ContentView的{​​{1}}内部。现在问题出在控件的初始化上,我的iOS渲染器上的IsVisible = false方法没有被调用。

以下是我注意到的一些关键点,这些假设导致了我的假设:

  • 我尝试在Draw方法内放置一个断点,但是它从未在此停下来。
  • 当我设置Draw的{​​{1}}时,它按预期方式工作,并调用StackLayout方法,此方法在断点处停止。

我的iOS渲染器:

IsVisible = true

在我的.xaml页面中:

Draw

如果您可能想知道,在我的.xaml上,class GradientFrameRenderer : FrameRenderer { ... public override void Draw(CGRect rect) { base.Draw(rect); if (Element is GradientFrame control) { CAGradientLayer gradientLayer = new CAGradientLayer() { Frame = rect, // i left the other stuffs out to minimize this post. }; Layer.InsertSublayerBelow(gradientLayer, Layer.Sublayers.LastOrDefault()); Layer.MasksToBounds = true; } } ... } <ContentView IsVisible="false" Opacity="0"> <Stacklayout Scale="0"> <custom:GradientFrame <!-- my style properties goes in here. again left out to minimize this post --> /> </StackLayout> </ContentView> ,而ContentViewOpacity="0"。这些将与后面的代码中的动画一起使用。


期望:

Expectation

现实:

Reality

  

注意:顶部框架的样式属性与期望图像中的样式属性相同,但是底部框架没有任何样式,旨在满足其要求是。

1 个答案:

答案 0 :(得分:0)

我更改了渲染GradientFrame的方法,而改用了this方法。所以我的渲染现在看起来像这样:

class GradientFrameRenderer : FrameRenderer {
    public override CGRect Frame {
        get => base.Frame;
        set {
            if(value.Width > 0 && value.Height > 0) { 
                foreach(var layer in Layer.Sublayers.Where(layer => layer is CAGradientLayer)) {
                    layer.Frame = new CGRect(0, 0, value.Width, value.Height);
                }
            }
            base.Frame = value;
        }
    }

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

        if (e.PropertyName == GradientFrame.StartColorProperty.PropertyName ||
            e.PropertyName == GradientFrame.EndColorProperty.PropertyName ||
            e.PropertyName == GradientFrame.DirectionProperty.PropertyName) {
            UpdateLayer();
        }
    }

    void UpdateLayer() {
        if (Element is GradientFrame control) {
            CAGradientLayer gradientLayer = new CAGradientLayer() {
                // i left the other stuffs out to minimize this post.
            };

            Layer.InsertSublayerBelow(gradientLayer, Layer.Sublayers.LastOrDefault());
            Layer.MasksToBounds = true;
        }
    }
}

因此,现在不再使用Draw方法来呈现控件,而是在每次调用OnElementPropertyChanged时(属性更改时)都完成了呈现过程。然后我覆盖了渲染器的Frame,以更新我添加的图层的Frame