【问题标题】:Xamarin.Forms/iOS - Hidden parent controls not rendering their child with custom renderers properlyXamarin.Forms/iOS - 隐藏的父控件未使用自定义渲染器正确渲染其子控件
【发布时间】:2019-04-26 10:23:42
【问题描述】:

我在我的 iOS 渲染器上遇到了Draw 问题,我有一个自定义控件。这个控件(我们称之为GradientFrame)位于ContentViewIsVisible = false 中。现在问题出在控件初始化时,我的 iOS 渲染器上的 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 中,ContentView 具有 Opacity="0"StackLayout 具有 Scale="0"。这些在这里与后面代码中的动画一起使用。


预期:

现实:

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

【问题讨论】:

    标签: xamarin.forms xamarin.ios


    【解决方案1】:

    我改变了渲染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

    【讨论】:

      猜你喜欢
      • 2014-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-12
      • 2019-11-02
      相关资源
      最近更新 更多