首页 文章

Xamarin形式的梯度stacklayout

提问于
浏览
1

我现在正在研究Xamarin表格 . 我需要一个渐变stacklayout视图,其宽度设置为堆栈布局,大于设备的纵向宽度 . 设置此宽度将确保stacklayout适合纵向视图,并且在横向中可以看到具有宽度的stacklayout . 在这里,我需要一个从上到下的渐变stacklayout . 我已经看到一些用于stacklayout的自定义渲染器的帖子,并且效果很好 .

但是当我使用这些渲染器时,我可以看到在实时场景中将方向从纵向更改为横向时,绘制的渐变布局宽度被视为纵向宽度,其余区域为空 . 请参阅附图

portrait

[![肖像] [1] [1]

and landscape

landscape

这是XAML代码图像enter image description here

<AbsoluteLayout>
<Image Source="img_bg.png" Aspect="AspectFill" VerticalOptions="FillAndExpand" AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All"/>
<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All" Spacing="0" Padding="0,20,0,0">
  <Image Source="img_logo.png" HorizontalOptions="Center" WidthRequest="200" HeightRequest="80"/>
  <ScrollView>
          <local:GradientStack StartColor="#99ddde" EndColor="#2896b1" HeightRequest="375" WidthRequest="300" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Padding="25,5,25,0" Margin="20,25,20,0" Spacing="0">
      <Label Text="Log in" HorizontalOptions="Start" TextColor="#e5f8fc" FontSize="34"/>
      <Label Text="Username" HorizontalOptions="Start" TextColor="#e5f8fc" FontSize="20" Margin="0,10,0,0"/>
      <local:CustomBorderEntry x:Name="txtUserName" HorizontalOptions="FillAndExpand"
                               HeightRequest="38" Margin="0,5,0,0"
                               BackgroundColor="#e5f8fc" FontSize="16"
                               TextColor ="#201f1f"
                               HorizontalTextAlignment="Start" />
      <Label Text="Password" HorizontalOptions="Start" TextColor="#e5f8fc" FontSize="20" Margin="0,10,0,0"/>
      <local:CustomBorderEntry x:Name="txtPassword" HorizontalOptions="FillAndExpand"
                               HeightRequest="38" Margin="0,5,0,0"
                               BackgroundColor="#e5f8fc" FontSize="16"
                               TextColor ="#201f1f"
                               HorizontalTextAlignment="Start" IsPassword="true"/>
      <Label Text="Event Code" HorizontalOptions="Start" TextColor="#e5f8fc" FontSize="20" Margin="0,10,0,0"/>
      <local:CustomBorderEntry x:Name="txtEventCode" HorizontalOptions="FillAndExpand"
                               HeightRequest="36" Margin="0,5,0,0"
                               BackgroundColor="#e5f8fc" FontSize="16"
                               TextColor ="#201f1f"
                               HorizontalTextAlignment="Start"/>
      <StackLayout Margin="0,20,0,0" Padding="0,1,0,0" BackgroundColor="#e5f8fc" HorizontalOptions="FillAndExpand" HeightRequest="45">
        <local:GradientStack StartColor="#2c7f9d" EndColor="#0e5a8c" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" x:Name="slLogin">
          <Label Text="Log in" FontSize="20" TextColor="#e5f8fc" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"/>
        </local:GradientStack>            
      </StackLayout>
    </local:GradientStack>
  </ScrollView>
</StackLayout>

自定义控件:

public class GradientStack : StackLayout
{
    public Color StartColor { get; set; }
    public Color EndColor { get; set; }
}

自定义渲染器:

public class GradientStackRenderer : VisualElementRenderer<GradientStack>
{
    public override void Draw(CGRect rect)
    {
        base.Draw(rect);
        CAGradientLayer layer = new CAGradientLayer();
        layer.Frame = rect;
        layer.Colors = new CGColor[] {
            Element.StartColor.ToCGColor(),
            Element.EndColor.ToCGColor()
        };
        Layer.InsertSublayer(layer, 0);
    }
}

2 回答

  • 0

    要在重绘时避免上述解决方案中的null异常,您需要确保检查Sublayers属性是否为null,如下所示:

    if (Layer.Sublayers?[0] is CAGradientLayer)
    {
        Layer.ReplaceSublayer(Layer.Sublayers[0], gradientLayer);
    }
    else
    {
        Layer.InsertSublayer(gradientLayer, 0);
    }
    
  • 2

    这是解决方案 . 当堆栈布局的大小改变时,我们需要强制重绘 .

    [assembly: ExportRenderer(typeof(GradientStack), typeof(GradientStackRenderer))]
    
    namespace yournamespace.iOS
    {
        class GradientStackRenderer : ViewRenderer<StackLayout, UIView>
        {
    
            public override void Draw(CGRect rect)
            {
                base.Draw(rect);
                CAGradientLayer layer = new CAGradientLayer();
                layer.Frame = rect;
                layer.Colors = new CGColor[]
                {
                    ((GradientStack)Element).StartColor.ToCGColor(),
                    ((GradientStack)Element).EndColor.ToCGColor()
                };
    
                if(Layer.Sublayers[0] is CAGradientLayer)
                    Layer.ReplaceSublayer(Layer.Sublayers[0], layer);
                else
                    Layer.InsertSublayer(layer, 0);
    
            }
    
            protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                base.OnElementPropertyChanged(sender, e);
    
                if(e.PropertyName=="Width")
                    SetNeedsDisplay();
            }
    
    
        }
    }
    

    我们也不想在每次绘制时添加图层,因此如果已经在子图层中,我们检查并替换我们的图层 .

    我也会删除不必要的大小请求

    <AbsoluteLayout>
            <Image Source="img_bg.png" Aspect="AspectFill" VerticalOptions="FillAndExpand" AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All"/>
            <StackLayout  AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All" Spacing="0" Padding="0,20,0,0">
                <Image Source="img_bg.png" HorizontalOptions="Center" WidthRequest="200" HeightRequest="80"/>
                <ScrollView>
                    <local:GradientStack StartColor="#99ddde" EndColor="#2896b1" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Padding="25,5,25,20" Margin="20,25,20,0" Spacing="0">
                        <Label Text="Log in" HorizontalOptions="Start" TextColor="#e5f8fc" FontSize="34"/>
                        <Label Text="Username" HorizontalOptions="Start" TextColor="#e5f8fc" FontSize="20" Margin="0,10,0,0"/>
                        <local:CustomBorderEntry x:Name="txtUserName" HorizontalOptions="FillAndExpand"
                               HeightRequest="38" Margin="0,5,0,0"
                               BackgroundColor="#e5f8fc" FontSize="16"
                               TextColor ="#201f1f"
                               HorizontalTextAlignment="Start" />
                        <Label Text="Password" HorizontalOptions="Start" TextColor="#e5f8fc" FontSize="20" Margin="0,10,0,0"/>
                        <local:CustomBorderEntry x:Name="txtPassword" HorizontalOptions="FillAndExpand"
                               HeightRequest="38" Margin="0,5,0,0"
                               BackgroundColor="#e5f8fc" FontSize="16"
                               TextColor ="#201f1f"
                               HorizontalTextAlignment="Start" IsPassword="true"/>
                        <Label Text="Event Code" HorizontalOptions="Start" TextColor="#e5f8fc" FontSize="20" Margin="0,10,0,0"/>
                        <local:CustomBorderEntry x:Name="txtEventCode" HorizontalOptions="FillAndExpand"
                               HeightRequest="36" Margin="0,5,0,0"
                               BackgroundColor="#e5f8fc" FontSize="16"
                               TextColor ="#201f1f"
                               HorizontalTextAlignment="Start"/>
                        <StackLayout Margin="0,20,0,0" Padding="0,1,0,0" BackgroundColor="#e5f8fc" HorizontalOptions="FillAndExpand" HeightRequest="45">
                            <local:GradientStack StartColor="#2c7f9d" EndColor="#0e5a8c" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" x:Name="slLogin">
                                <Label Text="Log in" FontSize="20" TextColor="#e5f8fc" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"/>
                            </local:GradientStack>
                        </StackLayout>
                    </local:GradientStack>
                </ScrollView>
            </StackLayout>
        </AbsoluteLayout>
    

相关问题