我的头衔很烂,你可以随意改.
我找到一张tutorial for making custom controls in Maui using SkiaSharp美元的钞票.我使用C#标记而不是XAML对其进行了一些修改.除了必须用ProgressBar.Maui.ProgressBar progressBar
而不是ProgressBar progressBar
实例化进度条之外,一切都运行得很好.
我想稍微修改一下,将重画限制为仅在达到某个进度更改阈值后才会发生.(即,每x%进度只重画一次).我添加了一个按小于阈值的速度递增进度的按钮,因此我应该必须单击这些按钮几次才能看到进度条更新.但是,每次我单击该按钮时,进度条都会更新.
如果我手动更改进度,比如将progressBar.Progress = 0.01f;
添加到页面构造函数的末尾,进度栏将按预期运行.
以下是所有相关代码[我认为]
我的库项目只有2个文件
ProgressBar.cs个
using SkiaSharp;
using SkiaSharp.Views.Maui;
using SkiaSharp.Views.Maui.Controls;
using System.Diagnostics;
namespace ProgressBar.Maui;
// All the code in this file is included in all platforms.
public class ProgressBar : SKCanvasView
{
public static readonly BindableProperty ProgressProperty =
BindableProperty.Create(nameof(Progress), typeof(float), typeof(ProgressBar), 0f, propertyChanged: OnBindablePropertyChanged);
public static readonly BindableProperty ProgressColorProperty =
BindableProperty.Create(nameof(ProgressColor), typeof(Color), typeof(ProgressBar), Colors.CornflowerBlue, propertyChanged: OnBindablePropertyChanged);
public static readonly BindableProperty BaseColorProperty =
BindableProperty.Create(nameof(BaseColor), typeof(Color), typeof(ProgressBar), Colors.LightGray, propertyChanged: OnBindablePropertyChanged);
public float Progress
{
get => (float)GetValue(ProgressProperty);
set
{
if (Math.Abs(value - _previousProgress) >= _RedrawThreshold)
{
SetValue(ProgressProperty, value);
_previousProgress = value;
Debug.WriteLine("Progress updated 和 surface invalidated.");
}
else
{
Debug.WriteLine("Progress change below threshold. No redraw.");
}
}
}
public Color ProgressColor
{
get => (Color)GetValue(ProgressColorProperty);
set => SetValue(ProgressColorProperty, value);
}
public Color BaseColor
{
get => (Color)GetValue(BaseColorProperty);
set => SetValue(BaseColorProperty, value);
}
// actual canvas instance to draw on
private SKCanvas _canvas;
// rectangle which will be used to draw the Progress Bar
private SKRect _drawRect;
// holds information about the dimensions, etc.
private SKImageInfo _info;
private const float _RedrawThreshold = 0.5f; // 1% change
private float _previousProgress = 0f;
private SKPaint _basePaint = new()
{
Style = SKPaintStyle.Fill,
IsAntialias = true,
};
private SKPaint _progressPaint = new()
{
Style = SKPaintStyle.Fill,
IsAntialias = true,
};
protected override void OnPaintSurface (SKPaintSurfaceEventArgs e)
{
base.OnPaintSurface(e);
_canvas = e.Surface.Canvas;
_canvas.Clear();
_info = e.Info;
_drawRect = new SKRect(0, 0, _info.Width, _info.Height);
DrawBase();
DrawProgress();
}
private void DrawBase ()
{
using SKPath basePath = new();
basePath.AddRect(_drawRect);
_basePaint.Color = BaseColor.ToSKColor();
_canvas.DrawPath(basePath, _basePaint);
}
private void DrawProgress ()
{
using SKPath progressPath = new();
var progressRect = new SKRect(0, 0, _info.Width * Progress, _info.Height);
progressPath.AddRect(progressRect);
_progressPaint.Color = ProgressColor.ToSKColor();
_canvas.DrawPath(progressPath, _progressPaint);
}
private static void OnBindablePropertyChanged (BindableObject bindable, object oldValue, object newValue)
{
if (oldValue != newValue)
((ProgressBar)bindable).InvalidateSurface();
}
}
和
Registration.cs个
using SkiaSharp.Views.Maui.H和lers;
namespace ProgressBar.Maui;
public static class Registration
{
public static MauiAppBuilder UseProgressBar(this MauiAppBuilder builder)
{
builder.ConfigureMauiH和lers(h =>
{
h.AddH和ler<ProgressBar, SKCanvasViewH和ler>();
});
return builder;
}
}
我的样例项目包含
SamplePage.cs个
namespace ProgressBarSample.Views;
public partial class SamplePage : ContentPage
{
public SamplePage (SampleViewModel viewModel)
{
BindingContext = viewModel;
Content = new VerticalStackLayout
{
Spacing = 30,
Padding = new Thickness(30, 0),
VerticalOptions = LayoutOptions.Center,
Children =
{
new ProgressBar.Maui.ProgressBar()
{
WidthRequest = 300,
HeightRequest = 5,
ProgressColor = Colors.DeepSkyBlue,
}
.Assign(out ProgressBar.Maui.ProgressBar progressBar)
.Bind(ProgressBar.Maui.ProgressBar.ProgressProperty, nameof(SampleViewModel.Progress), BindingMode.OneWay),
new Button
{
Text = "Increment",
}
.BindComm和(nameof(SampleViewModel.IncrementProgressComm和))
}
};
}
}
和
SampleViewModel.cs个
namespace ProgressBarSample.ViewModels;
public partial class SampleViewModel : BaseViewModel
{
[ObservableProperty]
private float progress = 0.01f;
[RelayComm和]
private void IncrementProgress()
{
Debug.WriteLine("IncrementProgress()");
Progress +=0.01f;
}
}
BaseViewModel.cs是继承ObservableObject
的空类
我还把builder.UseProgressBar()
加到了MauiProgram.cs