Xamarin.Forms 帧渐变背景在 Android 上溢出其边界
Xamarin.Forms Frame Gradient Background spills over its boundaries on Android
我在 Xamarin.Forms 中制作了一个自定义框架,允许使用 3 色线性渐变和其他一些东西。但是,我注意到当我在 Grid 内部的自定义框架上设置渐变时,它会覆盖其上方的所有内容。见下文:
然而,如果我只是将背景设置为粉红色等纯色(即不使用渐变功能),则框架不会溢出。见下文:
这是我为 Android 使用的自定义渲染器的代码:
protected override void DispatchDraw(Canvas canvas)
{
var gradient = new Android.Graphics.LinearGradient(
0, 0, Width, Height,
new int[] { _startColor.ToAndroid(), _middleColor.ToAndroid(), _endColor.ToAndroid() },
null,
Android.Graphics.Shader.TileMode.Mirror);
var paint = new Android.Graphics.Paint()
{
Dither = true,
};
paint.SetShader(gradient);
canvas.DrawPaint(paint);
base.DispatchDraw(canvas);
}
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
if(e.NewElement != null && Control != null && e.NewElement is CustomFrame frame)
{
_startColor = frame.StartColor;
_middleColor = frame.MiddleColor;
_endColor = frame.EndColor;
}
}
我将 x 和 y 的线性渐变设置为 0,0 时,是否可能不是指控件的 x 和 y,而是整个屏幕的 x 和 y?
这里是 xaml 的粗略示例,如果您需要的话:
<Grid RowSpacing="0"
ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="25*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="40*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="40*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid x:Name="header"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Grid.Row="0"
Grid.ColumnSpan="4"
RowSpacing="0"
BackgroundColor="White">
<CarouselView ItemsSource=""
CurrentItem=""
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
PeekAreaInsets="30"
x:Name="dayCarousel">
<CarouselView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal"
SnapPointsAlignment="Center"
SnapPointsType="MandatorySingle"/>
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate>
<ContentView>
<StackLayout VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
BackgroundColor="White">
<StackLayout.Triggers>
<DataTrigger TargetType="StackLayout"
Binding="{Binding IsSelected}"
Value="False">
<Setter Property="Scale"
Value="0.85"/>
<Setter Property="Opacity"
Value="0.60"/>
</DataTrigger>
</StackLayout.Triggers>
</StackLayout>
</ContentView>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</Grid>
<cntrl:CustomFrame CornerRadius="20,20,0,0"
Grid.Row="1"
Grid.Column="2"
StartColor="{StaticResource GracePink}"
MiddleColor="{StaticResource GracePurple}"
EndColor="{StaticResource GraceDarkPurple}">
</cntrl:CustomFrame>
<cntrl:CustomFrame CornerRadius="40,40,0,0"
Grid.Row="2"
Grid.RowSpan="3"
Grid.ColumnSpan="4"
StartColor="{StaticResource GracePink}"
MiddleColor="{StaticResource GracePurple}"
EndColor="{StaticResource GraceDarkPurple}">
</cntrl:CustomFrame>
<cntrl:CustomFrame BackgroundColor="White"
CornerRadius="20,20,0,0"
Grid.Row="3"
Grid.Column="1">
</cntrl:CustomFrame>
<cntrl:CustomFrame BackgroundColor="White"
Grid.Row="4"
CornerRadius="40,40,0,0"
Grid.ColumnSpan="4">
</cntrl:CustomFrame>
</Grid>
任何帮助将不胜感激,提前致谢!
在您的自定义框架中,设置 IsClippedToBounds="True"
Gets or sets a value which determines if the Layout should clip its children to its bounds.
<cntrl:CustomFrame CornerRadius="20,20,0,0"
Grid.Row="1"
Grid.Column="2"
IsClippedToBounds="True"
StartColor="{StaticResource GracePink}"
MiddleColor="{StaticResource GracePurple}"
EndColor="{StaticResource GraceDarkPurple}">
</cntrl:CustomFrame>
如果 IsClipToBounds 不起作用,请尝试在 OnElementChanged
中执行此操作
try
{
if (e.NewElement != null && Control != null && e.NewElement is CustomFrame frame)
{
_startColor = frame.StartColor;
_middleColor = frame.MiddleColor;
_endColor = frame.EndColor;
var orientation = GradientDrawable.Orientation.ToBottomRight;
var gradient = new GradientDrawable(orientation, new[] { _startColor .ToAndroid().ToArgb(), _middleColor.ToAndroid().ToArgb(), _endColor .ToAndroid().ToArgb() });
ViewCompat.SetBackground(this, gradient);
}
}
catch (Exception ex)
{
}
我在 Xamarin.Forms 中制作了一个自定义框架,允许使用 3 色线性渐变和其他一些东西。但是,我注意到当我在 Grid 内部的自定义框架上设置渐变时,它会覆盖其上方的所有内容。见下文:
然而,如果我只是将背景设置为粉红色等纯色(即不使用渐变功能),则框架不会溢出。见下文:
这是我为 Android 使用的自定义渲染器的代码:
protected override void DispatchDraw(Canvas canvas)
{
var gradient = new Android.Graphics.LinearGradient(
0, 0, Width, Height,
new int[] { _startColor.ToAndroid(), _middleColor.ToAndroid(), _endColor.ToAndroid() },
null,
Android.Graphics.Shader.TileMode.Mirror);
var paint = new Android.Graphics.Paint()
{
Dither = true,
};
paint.SetShader(gradient);
canvas.DrawPaint(paint);
base.DispatchDraw(canvas);
}
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
if(e.NewElement != null && Control != null && e.NewElement is CustomFrame frame)
{
_startColor = frame.StartColor;
_middleColor = frame.MiddleColor;
_endColor = frame.EndColor;
}
}
我将 x 和 y 的线性渐变设置为 0,0 时,是否可能不是指控件的 x 和 y,而是整个屏幕的 x 和 y?
这里是 xaml 的粗略示例,如果您需要的话:
<Grid RowSpacing="0"
ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="25*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="40*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="40*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid x:Name="header"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Grid.Row="0"
Grid.ColumnSpan="4"
RowSpacing="0"
BackgroundColor="White">
<CarouselView ItemsSource=""
CurrentItem=""
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
PeekAreaInsets="30"
x:Name="dayCarousel">
<CarouselView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal"
SnapPointsAlignment="Center"
SnapPointsType="MandatorySingle"/>
</CarouselView.ItemsLayout>
<CarouselView.ItemTemplate>
<DataTemplate>
<ContentView>
<StackLayout VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
BackgroundColor="White">
<StackLayout.Triggers>
<DataTrigger TargetType="StackLayout"
Binding="{Binding IsSelected}"
Value="False">
<Setter Property="Scale"
Value="0.85"/>
<Setter Property="Opacity"
Value="0.60"/>
</DataTrigger>
</StackLayout.Triggers>
</StackLayout>
</ContentView>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</Grid>
<cntrl:CustomFrame CornerRadius="20,20,0,0"
Grid.Row="1"
Grid.Column="2"
StartColor="{StaticResource GracePink}"
MiddleColor="{StaticResource GracePurple}"
EndColor="{StaticResource GraceDarkPurple}">
</cntrl:CustomFrame>
<cntrl:CustomFrame CornerRadius="40,40,0,0"
Grid.Row="2"
Grid.RowSpan="3"
Grid.ColumnSpan="4"
StartColor="{StaticResource GracePink}"
MiddleColor="{StaticResource GracePurple}"
EndColor="{StaticResource GraceDarkPurple}">
</cntrl:CustomFrame>
<cntrl:CustomFrame BackgroundColor="White"
CornerRadius="20,20,0,0"
Grid.Row="3"
Grid.Column="1">
</cntrl:CustomFrame>
<cntrl:CustomFrame BackgroundColor="White"
Grid.Row="4"
CornerRadius="40,40,0,0"
Grid.ColumnSpan="4">
</cntrl:CustomFrame>
</Grid>
任何帮助将不胜感激,提前致谢!
在您的自定义框架中,设置 IsClippedToBounds="True"
Gets or sets a value which determines if the Layout should clip its children to its bounds.
<cntrl:CustomFrame CornerRadius="20,20,0,0"
Grid.Row="1"
Grid.Column="2"
IsClippedToBounds="True"
StartColor="{StaticResource GracePink}"
MiddleColor="{StaticResource GracePurple}"
EndColor="{StaticResource GraceDarkPurple}">
</cntrl:CustomFrame>
如果 IsClipToBounds 不起作用,请尝试在 OnElementChanged
中执行此操作try
{
if (e.NewElement != null && Control != null && e.NewElement is CustomFrame frame)
{
_startColor = frame.StartColor;
_middleColor = frame.MiddleColor;
_endColor = frame.EndColor;
var orientation = GradientDrawable.Orientation.ToBottomRight;
var gradient = new GradientDrawable(orientation, new[] { _startColor .ToAndroid().ToArgb(), _middleColor.ToAndroid().ToArgb(), _endColor .ToAndroid().ToArgb() });
ViewCompat.SetBackground(this, gradient);
}
}
catch (Exception ex)
{
}