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

问题描述 投票:-1回答:1

我的iOS渲染器上有一个Draw问题,我有一个自定义控件。这个控制(让我们称之为GradientFrame)在ContentView内部与IsVisible = false。现在问题在于控件的初始化,我的渲染器上的Draw方法没有被调用。

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

  • 我尝试在Draw方法中放置一个断点,但它从未停止过。
  • 当我设置StackLayoutIsVisible = true时它按预期工作并调用Draw方法,这在断点处停止。

我的iOS渲染器:

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;
        }
    }
    ...
}

在我的.xaml页面中:

<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>

你可能想知道,在我的.xaml上,ContentViewOpacity="0"StackLayoutScale="0"。这些用于后面的代码中的动画。


期望:

Expectation

现实:

Reality

注意:顶部框架具有与Expectation图像中相同的样式属性,但底部框架没有任何样式属性,并且它原样。

xamarin.forms xamarin.ios
1个回答
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

© www.soinside.com 2019 - 2024. All rights reserved.