gpt4 book ai didi

c# - 如何在 Xamarin Forms 中复制 iOS 开关的功能,使其在 iOS 和 Android 中看起来相同?

转载 作者:行者123 更新时间:2023-11-30 15:15:11 25 4
gpt4 key购买 nike

我的应用程序使用如下所示的开关:

enter image description here

我想在 Xamarin Forms 中复制此功能,以便它在 iOS 和 Android 中显示和看起来完全像这个 iOS 版本。

我该怎么做呢?如果可能的话,我想要一个不使用任何 iOS 和 Android 渲染器的解决方案。取而代之的是仅使用 Forms 的 TapGestureRecognizer。

最佳答案

这是一个使用 SkiaSharp 的解决方案。通过 nuget 将 SkiaSharp 和 SkiaSharp.Views.Forms 包含到您的项目中。

现在创建一个新的内容 View :

CustomSwitch.xaml

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:skia="clr- namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
x:Class="MyNamespace.CustomSwitch" MinimumWidthRequest="120" MinimumHeightRequest="60" WidthRequest="120" HeightRequest="60">
<ContentView.Content>
<skia:SKCanvasView x:Name="PrimaryCanvas" PaintSurface="OnPaintSurface" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<skia:SKCanvasView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnElementTapped" />
</skia:SKCanvasView.GestureRecognizers>
</skia:SKCanvasView>
</ContentView.Content>
</ContentView>

CustomSwitch.xaml.cs

public partial class CustomSwitch : ContentView
{
#region Properties
public static BindableProperty OutlineColorProperty = BindableProperty.Create("OutlineColor", typeof(Color), typeof(Color), Color.LightGray);
public static BindableProperty SwitchBackgroundColorProperty = BindableProperty.Create("SwitchBackgroundColor", typeof(Color), typeof(Color), Color.White);
public static BindableProperty SwitchBackgroundColorToggledProperty = BindableProperty.Create("SwitchBackgroundColorToggled", typeof(Color), typeof(Color), Color.Green);
public static BindableProperty ButtonFillColorProperty = BindableProperty.Create("ButtonFillColor", typeof(Color), typeof(Color), Color.White);
public static BindableProperty IsToggledProperty = BindableProperty.Create("IsToggled", typeof(bool), typeof(bool), false);


public Color OutlineColor
{
get { return (Color)GetValue(OutlineColorProperty); }
set { SetValue(OutlineColorProperty, value); }
}

public Color ToggledBackgroundColor
{
get { return (Color)GetValue(SwitchBackgroundColorToggledProperty); }
set { SetValue(SwitchBackgroundColorToggledProperty, value); }
}

public Color SwitchBackgroundColor
{
get { return (Color)GetValue(SwitchBackgroundColorProperty); }
set { SetValue(SwitchBackgroundColorProperty, value); }
}

public Color ButtonFillColor
{
get { return (Color)GetValue(ButtonFillColorProperty); }
set { SetValue(ButtonFillColorProperty, value); }
}

public bool IsToggled
{
get { return (bool)GetValue(IsToggledProperty); }
set {
SetValue(IsToggledProperty, value);
OnToggleChange?.Invoke(this, value);
}
}

#endregion

public CustomSwitch()
{
InitializeComponent();
}

public event EventHandler<bool> OnToggleChange;

private SKColor? animatedBgColor = null;
private SKPoint buttonPosition = new SKPoint(30, 30);
private bool isAnimating = false;

protected virtual void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
SKImageInfo info = e.Info;
SKSurface surface = e.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();

SKPaint primaryFill = new SKPaint
{
Style = SKPaintStyle.Fill,
Color = animatedBgColor != null ? animatedBgColor.Value : IsToggled ? ToggledBackgroundColor.ToSKColor() : SwitchBackgroundColor.ToSKColor(),
IsAntialias = true
};
SKPaint primaryOutline = new SKPaint
{
Style = SKPaintStyle.Stroke,
StrokeWidth = 2,
Color = OutlineColor.ToSKColor(),
IsAntialias = true
};
SKPaint circleFill = new SKPaint
{
Style = SKPaintStyle.Fill,
Color = ButtonFillColor.ToSKColor(),
IsAntialias = true
};
SKPaint circleOutline = new SKPaint
{
Style = SKPaintStyle.Stroke,
StrokeWidth = 2,
Color = OutlineColor.ToSKColor(),
IsAntialias = true
};
SKRoundRect rect = new SKRoundRect(new SKRect(0, 0, 120, 60), 30, 30);
SKRoundRect rectOutline = new SKRoundRect(new SKRect(1, 1, 119, 59), 28, 28);
if (!isAnimating)
buttonPosition.X = IsToggled ? 90f : 30f;
canvas.DrawRoundRect(rect, primaryFill);
canvas.DrawRoundRect(rectOutline, primaryOutline);

canvas.DrawCircle(buttonPosition, 24, circleFill);
canvas.DrawCircle(buttonPosition, 23, circleOutline);
}

private void AnimateToToggle()
{
isAnimating = true;
new Animation((value) =>
{
double colorPartWeight = 1 - value;
animatedBgColor = SkiaTools.CalculateWeightedColor(SwitchBackgroundColor, ToggledBackgroundColor, colorPartWeight, value);
PrimaryCanvas.InvalidateSurface();
}).Commit(this, "bgcolorAnimation", length: (uint)250, repeat: () => false);

new Animation((value) =>
{
buttonPosition.X = 30 + (float)(value * 60.0);
}).Commit(this, "positionAnimation", length: (uint)250, repeat: () => false, finished: (v,c) => { buttonPosition.X = 90.0f; isAnimating = false; });
}

private void AnimateFromToggle()
{
isAnimating = true;
new Animation((value) =>
{
double colorPartWeight = 1 - value;
animatedBgColor = SkiaTools.CalculateWeightedColor(ToggledBackgroundColor, SwitchBackgroundColor, colorPartWeight, value);
PrimaryCanvas.InvalidateSurface();
}).Commit(this, "bgcolorAnimation", length: (uint)250, repeat: () => false);

new Animation((value) =>
{
buttonPosition.X = 90 - (float)(value * 60.0);
}).Commit(this, "positionAnimation", length: (uint)250, repeat: () => false, finished: (v, c) => { buttonPosition.X = 30.0f; isAnimating = false; });
}

private void OnElementTapped(object sender, EventArgs e)
{
IsToggled = !IsToggled;
if (IsToggled == true)
AnimateToToggle();
else
AnimateFromToggle();
}
}

同时创建一个名为 SkiaTools.cs 的新类,其中包含一些必要的静态方法:

SkiaTools.cs

public static class SkiaTools
{
public static SKColor CalculateWeightedColor(Xamarin.Forms.Color from, Xamarin.Forms.Color to, double weightA, double weightB)
{
double r = (from.R * weightA) + (to.R * weightB);
double g = (from.G * weightA) + (to.G * weightB);
double b = (from.B * weightA) + (to.B * weightB);
double a = (from.A * weightA) + (to.A * weightB);

byte bR = (byte)Math.Max(0, Math.Min(255, (int)Math.Floor(r * 256.0)));
byte bG = (byte)Math.Max(0, Math.Min(255, (int)Math.Floor(g * 256.0)));
byte bB = (byte)Math.Max(0, Math.Min(255, (int)Math.Floor(b * 256.0)));
byte bA = (byte)Math.Max(0, Math.Min(255, (int)Math.Floor(a * 256.0)));

return new SKColor(bR, bG, bB, bA);
}

public static SKColor ToSkColor(this Xamarin.Forms.Color xcolor)
{
byte r = (byte)Math.Max(0, Math.Min(255, (int)Math.Floor(xcolor.R * 256.0)));
byte g = (byte)Math.Max(0, Math.Min(255, (int)Math.Floor(xcolor.G * 256.0)));
byte b = (byte)Math.Max(0, Math.Min(255, (int)Math.Floor(xcolor.B * 256.0)));
byte a = (byte)Math.Max(0, Math.Min(255, (int)Math.Floor(xcolor.A * 256.0)));

return new SKColor(r,g,b,a);
}
}

现在终于可以在您的 View 或页面中使用以下 xaml 来使用开关了:

<local:CustomSwitch Margin="10,5,10,5" SwitchBackgroundColor="White" OutlineColor="LightGray" ButtonFillColor="White" ToggledBackgroundColor="Green" IsToggled="True" OnToggleChange="CustomSwitch_OnToggleChange"/>

结果将如下所示(未切换/切换):

enter image description here

关于c# - 如何在 Xamarin Forms 中复制 iOS 开关的功能,使其在 iOS 和 Android 中看起来相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53076616/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com