Vos premiers pas avec le skiharp à .net Maui

Dans cet article, vous apprendrez ce qu’est le Skiasharp et comment commencer avec lui pour créer des interfaces dans .net Maui que vous ne pourrez peut-être pas créer si facilement autrement.
Note importante: À la fin de cet article, vous saurez comment créer un contrôle personnalisé à l’aide de SkiSharp, bien que ma recommandation personnelle soit que autant que possible, vous utilisez des contrôles testés et robustes qui fournissent également un support pour toute éventualité, comme les progrès TELERIK COMMANDS POUR .NET MAUI.
Qu’est-ce que Skihsharp?
Skiharpe est une API graphique 2D multiplateforme basée sur la bibliothèque graphique SKIA de Google. Il peut être utilisé dans les projets mobiles, de bureau et de serveur .NET pour rendre des images. Dans le cas de .net Maui, il est très utile pour créer des objets à l’écran qui seraient très compliqués autrement, comme les commandes personnalisées, les arrière-plans avec des formes non symétriques, des effets graphiques, etc.
Utilisation de Skesharp dans des projets Maui .net
Pour intégrer le package SkiSharp dans un projet Maui .NET existant, vous devez effectuer ce qui suit:
- Ajouter le package Nuget
SkiaSharp.Views.Maui.Controls
qui installera le package et ses dépendances. - Dans
MauiProgram.cs
ajouter leUseSkiaSharp
Méthode comme suit:
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseSkiaSharp()
...
}
}
Avec la configuration ci-dessus, nous pouvons commencer à expérimenter avec Skiasharp dans l’interface utilisateur de l’application.
Définir un skcanvasview pour utiliser Skiasharp
Lorsque vous souhaitez rendre des éléments à l’aide de Skesharp, quelque chose que vous devez savoir est que vous devez utiliser un objet de type SKCanvas
. C’est le conteneur sur lequel nous pouvons dessiner des lignes, des formes, du texte, des images, etc. SKCanvasView
directement sur une page de contenu comme dans l’exemple suivant:
<ContentPage
xmlns:skia="clr-namespace:SkiaSharp.Views.Maui.Controls;assembly=SkiaSharp.Views.Maui.Controls"
...>
<Grid>
<skia:SKCanvasView
x:Name="canvas"
BackgroundColor="DarkRed"
HeightRequest="500"
WidthRequest="500" />
</Grid>
</ContentPage>
Le code ci-dessus génère un espace de 500px par 500px pour en tirer des éléments:
L’étape suivante pour dessiner des éléments sur la toile consiste à ajouter un gestionnaire d’événements pour le PaintSurface
événement. Cet événement se déclenche chaque fois qu’il est nécessaire de redessiner le contrôle, par exemple lorsqu’il s’initialise, redimensionne ou nous forcerons un rafraîchissement:
<skia:SKCanvasView
x:Name="canvas"
BackgroundColor="DarkRed"
HeightRequest="500"
PaintSurface="canvas_PaintSurface"
WidthRequest="500" />
Le PaintSurface
L’événement contient un paramètre de type SKPaintSurfaceEventArgs
qui fournit une référence au SKCanvas
à travers le e.Surface.Canvas
propriété, ainsi que le Info
propriété de type SKPaintSurfaceEventArgs
qui contient des informations sur la toile, comme sa taille:
private void canvas_PaintSurface(object sender, SkiaSharp.Views.Maui.SKPaintSurfaceEventArgs e)
{
var canvas = e.Surface.Canvas;
var info = e.Info;
Debug.WriteLine($"Canvas size: {info.Width} x {info.Height}");
}
Méthodes communes de l’objet Skcanvas
Une fois que nous savons comment récupérer le SKCanvas
Objet du code derrière, il est temps de parler de certaines méthodes disponibles. Ces méthodes permettent de dessiner sur la surface de la toile et ont généralement des noms assez descriptifs:
DrawColor
: Remplit la toile d’une couleur unieDrawLine
: Permet des lignes de dessinDrawRect
: Permet de dessiner des rectanglesDrawCircle
: Permet de dessiner des cerclesDrawText
: Permet de dessiner du texteDrawPath
: Permet des vecteurs de dessinDrawBitmap
: Permet de dessiner des imagesClear
: Efface la toile permettant une nouvelle couleur d’arrière-planClipRect
/ /ClipPath
: Limite les zones de dessinMoveTo
: Déplace le curseur de dessin vers certaines coordonnées, mais sans rien dessiner
Les méthodes ci-dessus ne sont qu’une partie de toutes les méthodes disponibles dans l’API. Maintenant, supposons que nous voulions changer la couleur de la toile chaque seconde avec une couleur aléatoire; Pour y parvenir, nous pourrions utiliser le DrawColor
Méthode comme suit:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
}
private void MainPage_Loaded(object? sender, EventArgs e)
{
var timer = new System.Timers.Timer(1000);
timer.Elapsed += (s, args) =>
{
canvas.Dispatcher.Dispatch(() => canvas.InvalidateSurface());
};
timer.Start();
}
private void canvas_PaintSurface(object sender, SkiaSharp.Views.Maui.SKPaintSurfaceEventArgs e)
{
var random = new Random();
var color = new SKColor((byte)random.Next(256), (byte)random.Next(256), (byte)random.Next(256));
var canvas = e.Surface.Canvas;
canvas.DrawColor(color);
}
}
Le code ci-dessus fait remplir l’arrière-plan de la toile d’une couleur différente chaque seconde:
Maintenant, chaque méthode que nous avons mentionnée dans la liste précédente prend un type différent pour exécuter sa fonction. Par exemple, dans le code précédent, nous pouvons voir que le DrawColor
La méthode s’attend à un type SKColor
. Parlons davantage des types d’objets que nous pouvons utiliser pour dessiner à l’aide de SkiSharp.
Types communs pour dessiner sur un objet Skcanvas
Dans l’API SKISHALSHARP, nous pouvons trouver un ensemble de classes qui permettent de dessiner divers objets sur un SKCanvas
objet. Parmi les plus couramment utilisés figurent:
SKPaint
: Définit à quoi ressemblera un élément rendu, en spécifiant des caractéristiques telles que la couleur, l’épaisseur de la ligne, la taille de la police, etc.SKColor
: Représente une couleur RGBASKRect
: Représente un rectangleSKBitmap
etSKImage
: Définir une image en mémoireSKTypeface
: Représente une policeSKPath
: Définit les chemins vectorielsSKMatrix
: Permet d’appliquer des transformationsSKRoundRect
: Permet de dessiner un rectangle arrondi
En règle générale, nous définissons ces objets en fonction de la méthode que nous voulons utiliser. L’exemple suivant montre comment dessiner un visage à l’aide de skiharp:
private void canvas_PaintSurface(object sender, SkiaSharp.Views.Maui.SKPaintSurfaceEventArgs e)
{
var canvas = e.Surface.Canvas;
var info = e.Info;
float width = info.Width;
float height = info.Height;
canvas.Clear(SKColors.White);
float cx = width / 2f;
float cy = height / 2f;
float radius = Math.Min(width, height) * 0.4f;
using (var paintFill = new SKPaint
{
Color = SKColors.Yellow,
Style = SKPaintStyle.Fill,
IsAntialias = true
})
{
canvas.DrawCircle(cx, cy, radius, paintFill);
}
using (var paintStroke = new SKPaint
{
Color = SKColors.Black,
Style = SKPaintStyle.Stroke,
StrokeWidth = radius * 0.05f,
IsAntialias = true
})
{
canvas.DrawCircle(cx, cy, radius, paintStroke);
}
float eyeOffsetX = radius * 0.3f;
float eyeOffsetY = radius * 0.2f;
float eyeRadius = radius * 0.1f;
using (var paintEye = new SKPaint
{
Color = SKColors.Black,
Style = SKPaintStyle.Fill,
IsAntialias = true
})
{
canvas.DrawCircle(cx - eyeOffsetX, cy - eyeOffsetY, eyeRadius, paintEye);
canvas.DrawCircle(cx + eyeOffsetX, cy - eyeOffsetY, eyeRadius, paintEye);
}
using (var paintMouth = new SKPaint
{
Color = SKColors.Black,
Style = SKPaintStyle.Stroke,
StrokeWidth = radius * 0.05f,
IsAntialias = true
})
{
var path = new SKPath();
float mouthW = radius * 0.6f;
float mouthH = radius * 0.3f;
float yMouth = cy + radius * 0.2f;
path.MoveTo(cx - mouthW / 2f, yMouth);
path.CubicTo(
cx - mouthW / 4f, yMouth + mouthH,
cx + mouthW / 4f, yMouth + mouthH,
cx + mouthW / 2f, yMouth);
canvas.DrawPath(path, paintMouth);
}
}
Dans le code ci-dessus, vous pouvez voir comment une combinaison de types et de méthodes dans SkiSharp est utilisée pour dessiner des sections du visage. Il est également possible de remarquer un schéma commun: pour chaque section, un SKPaint
le type est défini d’abord, indiquant à quoi ressemblera l’objet dessiné, puis la méthode correspondante est utilisée pour dessiner la forme avec les caractéristiques définies dans SKPaint
. Le résultat de l’exécution précédente est la suivante:
Création d’un contrôle à l’aide de Skesharp
Maintenant que nous avons les principes fondamentaux de l’utilisation du skiasharp dans .net Maui, créons un petit contrôle réutilisable qui permet de basculer entre le mode clair et l’obscurité dans l’application. Jusqu’à présent, nous avons utilisé le SKCanvasView
contrôle pour définir l’emplacement du SKCanvas
sur une page de contenu. Idéalement, nous serions en mesure de réutiliser le contrôle sur plusieurs pages, afin que nous puissions créer une classe qui hérite de SKCanvasView
comme suit:
public class ToggleSwitch : SKCanvasView
{
protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
{
var canvas = e.Surface.Canvas;
canvas.Clear();
}
}
Ensuite, nous pouvons utiliser ce nouveau composant dans une page de contenu comme suit:
<ContentPage
xmlns:controls="clr-namespace:SkiaSharpDemo"
xmlns:skia="clr-namespace:SkiaSharp.Views.Maui.Controls;assembly=SkiaSharp.Views.Maui.Controls"
...>
<Grid>
<VerticalStackLayout Padding="30" Spacing="20">
<controls:ToggleSwitch HeightRequest="50" WidthRequest="100" />
</VerticalStackLayout>
</Grid>
</ContentPage>
Une fois que nous aurons l’espace prêt à commencer à dessiner des formes sur la toile, nous utiliserons le DrawRoundRect
Méthode pour dessiner le conteneur du contrôle et DrawCircle
Pour dessiner le bouton qui contrôlera le mode sélectionné:
Vous pouvez voir que nous avons déjà une toile avec deux formes représentant l’état de l’interrupteur. L’étape suivante consiste à ajouter de l’interactivité au contrôle, permettant à l’utilisateur de personnaliser à quoi ressemble le contrôle et agit. Pour ce faire, nous ajouterons des propriétés liaisables au contrôle:
public class ToggleSwitch : SKCanvasView
{
public static readonly BindableProperty IsToggledProperty =
BindableProperty.Create(
nameof(IsToggled),
typeof(bool),
typeof(ToggleSwitch),
false,
propertyChanged: OnToggledChanged);
public bool IsToggled
{
get => (bool)GetValue(IsToggledProperty);
set => SetValue(IsToggledProperty, value);
}
public static readonly BindableProperty OnBackgroundColorProperty =
BindableProperty.Create(
nameof(OnBackgroundColor),
typeof(Color),
typeof(ToggleSwitch),
Colors.DarkSlateGray,
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
{
((ToggleSwitch)bindable).InvalidateSurface();
});
public Color OnBackgroundColor
{
get => (Color)GetValue(OnBackgroundColorProperty);
set => SetValue(OnBackgroundColorProperty, value);
}
public static readonly BindableProperty OffBackgroundColorProperty =
BindableProperty.Create(
nameof(OffBackgroundColor),
typeof(Color),
typeof(ToggleSwitch),
Colors.LightGray,
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
{
((ToggleSwitch)bindable).InvalidateSurface();
});
public Color OffBackgroundColor
{
get => (Color)GetValue(OffBackgroundColorProperty);
set => SetValue(OffBackgroundColorProperty, value);
}
public static readonly BindableProperty KnobOnColorProperty =
BindableProperty.Create(
nameof(KnobOnColor),
typeof(Color),
typeof(ToggleSwitch),
Colors.White,
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
{
((ToggleSwitch)bindable).InvalidateSurface();
});
public Color KnobOnColor
{
get => (Color)GetValue(KnobOnColorProperty);
set => SetValue(KnobOnColorProperty, value);
}
public static readonly BindableProperty KnobOffColorProperty =
BindableProperty.Create(
nameof(KnobOffColor),
typeof(Color),
typeof(ToggleSwitch),
Colors.White,
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
{
((ToggleSwitch)bindable).InvalidateSurface();
});
public Color KnobOffColor
{
get => (Color)GetValue(KnobOffColorProperty);
set => SetValue(KnobOffColorProperty, value);
}
public event EventHandler<ToggledEventArgs> Toggled;
static void OnToggledChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (ToggleSwitch)bindable;
control.InvalidateSurface();
control.Toggled?.Invoke(control, new ToggledEventArgs((bool)newValue));
}
...
}
Dans le code ci-dessus, une série de propriétés contraignables sont définies qui nous permettent de savoir si le contrôle de bascule est activé ou désactivé, les couleurs ON et OFF et, enfin, les couleurs du bouton dans leurs différents états. Vous pouvez également remarquer qu’une méthode appelée InvalidateSurface
est fréquemment utilisé, ce qui indique que le contenu du contrôle a changé et doit être repeint.
Avec les nouvelles propriétés ajoutées, nous pouvons modifier le OnPaintSurface
Méthode pour les utiliser et contrôler comment l’interface graphique sera affichée à tout moment comme suit:
protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
{
var canvas = e.Surface.Canvas;
canvas.Clear();
float width = e.Info.Width;
float height = e.Info.Height;
float radius = height / 2f;
using (var paint = new SKPaint
{
Color = (IsToggled
? OnBackgroundColor.ToSKColor()
: OffBackgroundColor.ToSKColor()),
IsAntialias = true
})
{
var rect = new SKRoundRect(
new SKRect(0, 0, width, height),
radius, radius);
canvas.DrawRoundRect(rect, paint);
}
float knobRadius = radius - 4;
float knobX = IsToggled ? width - radius : radius;
float knobY = radius;
using (var paint = new SKPaint
{
Color = (IsToggled
? KnobOffColor.ToSKColor()
: KnobOnColor.ToSKColor()),
IsAntialias = true
})
{
canvas.DrawCircle(knobX, knobY, knobRadius, paint);
}
}
Si vous exécutez l’application en ce moment, vous remarquerez que le contrôle ne réagit pas à être pressé. C’est parce que nous devons ajouter le OnTouch
événement, qui lui permet de réagir aux interactions utilisateur:
public class ToggleSwitch2 : SKCanvasView
{
public ToggleSwitch()
{
EnableTouchEvents = true;
Touch += OnTouch;
}
private void OnTouch(object? sender, SKTouchEventArgs e)
{
if (e.ActionType == SKTouchAction.Released)
{
IsToggled = !IsToggled;
e.Handled = true;
}
}
...
}
Après ce changement, vous verrez que le contrôle est désormais utilisable:
La dernière étape consiste à modifier le code derrière ou ViewModel de la page afin qu’il y ait une propriété pour connaître l’état du contrôle, ce qui permet d’effectuer une action dans l’application. Dans notre exemple, nous utiliserons la nouvelle propriété pour modifier le thème de l’application comme suit:
public partial class MainPage : ContentPage
{
public static readonly BindableProperty IsDarkModeProperty =
BindableProperty.Create(
nameof(IsDarkMode),
typeof(bool),
typeof(MainPage),
false,
propertyChanged: OnIsDarkModeChanged);
public bool IsDarkMode
{
get => (bool)GetValue(IsDarkModeProperty);
set => SetValue(IsDarkModeProperty, value);
}
static void OnIsDarkModeChanged(BindableObject bindable, object oldValue, object newValue)
{
var page = (MainPage)bindable;
bool isDark = (bool)newValue;
Application.Current.UserAppTheme = isDark ? AppTheme.Dark : AppTheme.Light;
}
public MainPage()
{
InitializeComponent();
BindingContext = this;
}
}
Enfin, nous lierons la nouvelle propriété au IsToggled
Propriété du contrôle, la configurer dans sa forme finale:
<controls:ToggleSwitch
HeightRequest="50"
IsToggled="{Binding IsDarkMode, Mode=TwoWay}"
KnobOffColor="#1F2125"
KnobOnColor="#FFCF00"
OffBackgroundColor="LightGray"
OnBackgroundColor="#FFCF00"
WidthRequest="100" />
Avec ces modifications, vous pouvez voir comment le thème de l’application change dynamiquement, grâce à l’utilisation du contrôle créé dans Skiasharp:
Et c’est tout! Nous avons créé un contrôle personnalisé à partir de zéro à l’aide de SkiSharp.
Conclusion
Tout au long de cet article, vous avez appris ce qu’est Skiasharp et comment l’intégrer dans une application .net Maui. De même, vous vous êtes familiarisé avec le plus couramment utilisé SKCanvas
Méthodes ainsi que les types communs utilisés pour créer des formes dans la toile. Enfin, vous avez vu comment créer un contrôle personnalisé que nous pouvons utiliser grâce à un ensemble de propriétés contraignables que nous avons ajoutées.
L’utilisation de Skihsharp peut être idéale si vous souhaitez créer un contrôle qui n’existe pas ou ne dessine pas une forme spéciale sur l’écran que vous ne pouvez pas réaliser d’une autre manière. Maintenant, c’est à votre tour d’expérimenter ce fabuleux cadre et de voir comment l’intégrer dans vos propres applications.
Source link