在自定义控制按钮上设置高程不起作用
Setting Elevation on Custom control button not working
我正在努力实现像这个截图一样的按钮:
所以我为 iOS 和 Android 做了一个带有特定渲染器的自定义控件,控件如下:
public class ElevationButton : Button
{
public float Elevation
{
get => (float)GetValue(ElevationProperty);
set => SetValue(ElevationProperty, value);
}
public static BindableProperty ElevationProperty = BindableProperty.Create(nameof(Elevation), typeof(float), typeof(ElevationButton), 4.0f);
}
这是 iOS 渲染器:
public class ElevationButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
UpdateShadow();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var element = (ElevationButton)this.Element;
if (e.PropertyName == nameof(element.Elevation))
UpdateShadow();
}
private void UpdateShadow()
{
var element = (ElevationButton)this.Element;
Layer.ShadowRadius = element.Elevation;
Layer.ShadowColor = UIColor.Gray.CGColor;
Layer.ShadowOffset = new CGSize(2, 2);
Layer.ShadowOpacity = 0.80f;
Layer.ShadowPath = UIBezierPath.FromRect(Layer.Bounds).CGPath;
Layer.MasksToBounds = false;
}
}
和Android一个:
public class ElevationButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer
{
public ElevationButtonRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
var element = (ElevationButton)this.Element;
// we need to reset the StateListAnimator to override the setting of Elevation on touch down and release.
Control.StateListAnimator = new Android.Animation.StateListAnimator();
// set the elevation manually
ViewCompat.SetElevation(this, element.Elevation);
ViewCompat.SetElevation(Control, element.Elevation);
}
public override void Draw(Canvas canvas)
{
var element = (ElevationButton)this.Element;
Control.Elevation = element.Elevation;
base.Draw(canvas);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var element = (ElevationButton)this.Element;
if (e.PropertyName == nameof(element.Elevation))
{
ViewCompat.SetElevation(this, element.Elevation);
ViewCompat.SetElevation(Control, element.Elevation);
UpdateLayout();
}
}
}
这是我声明自定义控件的 xaml:
<StackLayout Orientation="Horizontal">
<StackLayout Orientation="Vertical">
<controls:ElevationButton x:Name="buttonTest"
BackgroundColor="White"
HeightRequest="40"
WidthRequest="40"
Elevation="20"
CornerRadius="50"
Padding="10,10,10,10"
Text="{x:Static fa:FontAwesomeIcons.Camera}"
FontFamily="FASolid"
TextColor="{StaticResource Text}" />
<Label Text="PHOTO" />
</StackLayout>
因此,当我测试此代码时,无论我为 Elevation 设置哪个值,渲染都是这样,不显示任何 Elevation 和阴影 属性 :
我在其他帖子上看到 CornerRadius 存在一些问题,在我的情况下,有或没有它,Elevation 都没有显示。
如果您有任何想法,我很乐意阅读。
如果你只是想要阴影,你可以使用Community Toolkit
。
从 NuGet 安装:https://www.nuget.org/packages/Xamarin.CommunityToolkit/2.0.1?_src=template
Xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:App1"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
x:Class="App1.Page6">
<StackLayout Orientation="Horizontal">
<StackLayout Orientation="Vertical">
<controls:ElevationButton x:Name="buttonTest"
BackgroundColor="White"
.......
xct:ShadowEffect.Color="Red"
xct:ShadowEffect.OffsetY="12" />
<Label Text="PHOTO" />
</StackLayout>
</StackLayout>
</ContentPage>
我正在努力实现像这个截图一样的按钮:
所以我为 iOS 和 Android 做了一个带有特定渲染器的自定义控件,控件如下:
public class ElevationButton : Button
{
public float Elevation
{
get => (float)GetValue(ElevationProperty);
set => SetValue(ElevationProperty, value);
}
public static BindableProperty ElevationProperty = BindableProperty.Create(nameof(Elevation), typeof(float), typeof(ElevationButton), 4.0f);
}
这是 iOS 渲染器:
public class ElevationButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
UpdateShadow();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var element = (ElevationButton)this.Element;
if (e.PropertyName == nameof(element.Elevation))
UpdateShadow();
}
private void UpdateShadow()
{
var element = (ElevationButton)this.Element;
Layer.ShadowRadius = element.Elevation;
Layer.ShadowColor = UIColor.Gray.CGColor;
Layer.ShadowOffset = new CGSize(2, 2);
Layer.ShadowOpacity = 0.80f;
Layer.ShadowPath = UIBezierPath.FromRect(Layer.Bounds).CGPath;
Layer.MasksToBounds = false;
}
}
和Android一个:
public class ElevationButtonRenderer : Xamarin.Forms.Platform.Android.AppCompat.ButtonRenderer
{
public ElevationButtonRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
return;
var element = (ElevationButton)this.Element;
// we need to reset the StateListAnimator to override the setting of Elevation on touch down and release.
Control.StateListAnimator = new Android.Animation.StateListAnimator();
// set the elevation manually
ViewCompat.SetElevation(this, element.Elevation);
ViewCompat.SetElevation(Control, element.Elevation);
}
public override void Draw(Canvas canvas)
{
var element = (ElevationButton)this.Element;
Control.Elevation = element.Elevation;
base.Draw(canvas);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var element = (ElevationButton)this.Element;
if (e.PropertyName == nameof(element.Elevation))
{
ViewCompat.SetElevation(this, element.Elevation);
ViewCompat.SetElevation(Control, element.Elevation);
UpdateLayout();
}
}
}
这是我声明自定义控件的 xaml:
<StackLayout Orientation="Horizontal">
<StackLayout Orientation="Vertical">
<controls:ElevationButton x:Name="buttonTest"
BackgroundColor="White"
HeightRequest="40"
WidthRequest="40"
Elevation="20"
CornerRadius="50"
Padding="10,10,10,10"
Text="{x:Static fa:FontAwesomeIcons.Camera}"
FontFamily="FASolid"
TextColor="{StaticResource Text}" />
<Label Text="PHOTO" />
</StackLayout>
因此,当我测试此代码时,无论我为 Elevation 设置哪个值,渲染都是这样,不显示任何 Elevation 和阴影 属性 :
我在其他帖子上看到 CornerRadius 存在一些问题,在我的情况下,有或没有它,Elevation 都没有显示。
如果您有任何想法,我很乐意阅读。
如果你只是想要阴影,你可以使用Community Toolkit
。
从 NuGet 安装:https://www.nuget.org/packages/Xamarin.CommunityToolkit/2.0.1?_src=template
Xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:App1"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
x:Class="App1.Page6">
<StackLayout Orientation="Horizontal">
<StackLayout Orientation="Vertical">
<controls:ElevationButton x:Name="buttonTest"
BackgroundColor="White"
.......
xct:ShadowEffect.Color="Red"
xct:ShadowEffect.OffsetY="12" />
<Label Text="PHOTO" />
</StackLayout>
</StackLayout>
</ContentPage>