圆形进度条 | Xamarin 表格
Progress bar in the shape of a circle | Xamarin forms
preview
如何实现。我已经使用了不同的渲染器,但没有任何效果
你想达到如下GIF效果吗?
如果是这样,您可以使用SkiaSharp
来实现它。以下代码绘制两个圆圈。
public async Task drawGaugeAsync()
{
// Radial Gauge Constants
int uPadding = 30;
int side = 500;
int radialGaugeWidth = 25;
// Line TextSize inside Radial Gauge
int lineSize1 = 220;
int lineSize2 = 70;
int lineSize3 = 80;
// Line Y Coordinate inside Radial Gauge
int lineHeight1 = 100;
int lineHeight2 = 200;
int lineHeight3 = 300;
// Start & End Angle for Radial Gauge
float startAngle = -90;
float sweepAngle = 360;
try
{
// Getting Canvas Info
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
progressUtils.setDevice(info.Height, info.Width);
canvas.Clear();
// Getting Device Specific Screen Values
// -------------------------------------------------
// Top Padding for Radial Gauge
float upperPading = progressUtils.getFactoredHeight(uPadding);
/* Coordinate Plotting for Radial Gauge
*
* (X1,Y1) ------------
* | (XC,YC) |
* | . |
* Y | |
* | |
* ------------ (X2,Y2))
* X
*
*To fit a perfect Circle inside --> X==Y
* i.e It should be a Square
*/
// Xc & Yc are center of the Circle
int Xc = info.Width / 2;
float Yc = progressUtils.getFactoredHeight(side);
// X1 Y1 are lefttop cordiates of rectange
int X1 = (int)(Xc - Yc);
int Y1 = (int)(Yc - Yc + upperPading);
// X2 Y2 are rightbottom cordiates of rectange
int X2 = (int)(Xc + Yc);
int Y2 = (int)(Yc + Yc + upperPading);
//Loggig Screen Specific Calculated Values
Debug.WriteLine("INFO " + info.Width + " - " + info.Height);
Debug.WriteLine(" C : " + upperPading + " " + info.Height);
Debug.WriteLine(" C : " + Xc + " " + Yc);
Debug.WriteLine("XY : " + X1 + " " + Y1);
Debug.WriteLine("XY : " + X2 + " " + Y2);
// Empty Gauge Styling
SKPaint paint1 = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = Color.FromHex("#05c782").ToSKColor(), // Colour of Radial Gauge
StrokeWidth = progressUtils.getFactoredWidth(radialGaugeWidth), // Width of Radial Gauge
StrokeCap = SKStrokeCap.Round // Round Corners for Radial Gauge
};
// Filled Gauge Styling
SKPaint paint2 = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = Color.FromHex("#e0dfdf").ToSKColor(), // Overlay Colour of Radial Gauge
StrokeWidth = progressUtils.getFactoredWidth(radialGaugeWidth), // Overlay Width of Radial Gauge
StrokeCap = SKStrokeCap.Round // Round Corners for Radial Gauge
};
// Defining boundaries for Gauge
SKRect rect = new SKRect(X1, Y1, X2, Y2);
//canvas.DrawRect(rect, paint1);
//canvas.DrawOval(rect, paint1);
// Rendering Empty Gauge
SKPath path1 = new SKPath();
path1.AddArc(rect, startAngle, sweepAngle);
canvas.DrawPath(path1, paint1);
// Rendering Filled Gauge
SKPath path2 = new SKPath();
path2.AddArc(rect, startAngle, (float)sweepAngleSlider.Value);
canvas.DrawPath(path2, paint2);
//---------------- Drawing Text Over Gauge ---------------------------
// Achieved Minutes
using (SKPaint skPaint = new SKPaint())
{
skPaint.Style = SKPaintStyle.Fill;
skPaint.IsAntialias = true;
skPaint.Color = SKColor.Parse("#676a69");
skPaint.TextAlign = SKTextAlign.Center;
skPaint.TextSize = progressUtils.getFactoredHeight(lineSize1);
skPaint.Typeface = SKTypeface.FromFamilyName(
"Arial",
SKFontStyleWeight.Bold,
SKFontStyleWidth.Normal,
SKFontStyleSlant.Upright);
// Drawing Achieved Minutes Over Radial Gauge
if (sw_listToggle.IsToggled)
canvas.DrawText(monthlyWorkout+"", Xc, Yc + progressUtils.getFactoredHeight(lineHeight1), skPaint);
else
canvas.DrawText(dailyWorkout+"", Xc, Yc + progressUtils.getFactoredHeight(lineHeight1), skPaint);
}
// Achieved Minutes Text Styling
using (SKPaint skPaint = new SKPaint())
{
skPaint.Style = SKPaintStyle.Fill;
skPaint.IsAntialias = true;
skPaint.Color = SKColor.Parse("#676a69");
skPaint.TextAlign = SKTextAlign.Center;
skPaint.TextSize = progressUtils.getFactoredHeight(lineSize2);
canvas.DrawText("Minutes", Xc, Yc + progressUtils.getFactoredHeight(lineHeight2), skPaint);
}
// Goal Minutes Text Styling
using (SKPaint skPaint = new SKPaint())
{
skPaint.Style = SKPaintStyle.Fill;
skPaint.IsAntialias = true;
skPaint.Color = SKColor.Parse("#e2797a");
skPaint.TextAlign = SKTextAlign.Center;
skPaint.TextSize = progressUtils.getFactoredHeight(lineSize3);
// Drawing Text Over Radial Gauge
if (sw_listToggle.IsToggled)
canvas.DrawText("Goal " + goal + " Min", Xc, Yc + progressUtils.getFactoredHeight(lineHeight3), skPaint);
else
{
canvas.DrawText("Goal " + goal/30 + " Min", Xc, Yc + progressUtils.getFactoredHeight(lineHeight3), skPaint);
}
}
}
catch (Exception e)
{
Debug.WriteLine(e.StackTrace);
}
}
}
然后为圈子添加animateProgress
。
// Animating the Progress of Radial Gauge
async void animateProgress(int progress)
{
sw_listToggle.IsEnabled = false;
sweepAngleSlider.Value = 1;
// Looping at data interval of 5
for (int i = 0; i < progress; i=i+5)
{
sweepAngleSlider.Value = i;
await Task.Delay(3);
}
sweepAngleSlider.Value = progress;
sw_listToggle.IsEnabled = true;
}
我参考了这个博客关于如何实现它。可以参考一下。
https://medium.com/@KPS250/custom-radial-progress-indicator-in-xamarin-forms-c7ed81840c1e
我上传我的demo给你,你可以根据自己的需要定制。
https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/RadioProgressBar.zip
preview
如何实现。我已经使用了不同的渲染器,但没有任何效果
你想达到如下GIF效果吗?
如果是这样,您可以使用SkiaSharp
来实现它。以下代码绘制两个圆圈。
public async Task drawGaugeAsync()
{
// Radial Gauge Constants
int uPadding = 30;
int side = 500;
int radialGaugeWidth = 25;
// Line TextSize inside Radial Gauge
int lineSize1 = 220;
int lineSize2 = 70;
int lineSize3 = 80;
// Line Y Coordinate inside Radial Gauge
int lineHeight1 = 100;
int lineHeight2 = 200;
int lineHeight3 = 300;
// Start & End Angle for Radial Gauge
float startAngle = -90;
float sweepAngle = 360;
try
{
// Getting Canvas Info
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
progressUtils.setDevice(info.Height, info.Width);
canvas.Clear();
// Getting Device Specific Screen Values
// -------------------------------------------------
// Top Padding for Radial Gauge
float upperPading = progressUtils.getFactoredHeight(uPadding);
/* Coordinate Plotting for Radial Gauge
*
* (X1,Y1) ------------
* | (XC,YC) |
* | . |
* Y | |
* | |
* ------------ (X2,Y2))
* X
*
*To fit a perfect Circle inside --> X==Y
* i.e It should be a Square
*/
// Xc & Yc are center of the Circle
int Xc = info.Width / 2;
float Yc = progressUtils.getFactoredHeight(side);
// X1 Y1 are lefttop cordiates of rectange
int X1 = (int)(Xc - Yc);
int Y1 = (int)(Yc - Yc + upperPading);
// X2 Y2 are rightbottom cordiates of rectange
int X2 = (int)(Xc + Yc);
int Y2 = (int)(Yc + Yc + upperPading);
//Loggig Screen Specific Calculated Values
Debug.WriteLine("INFO " + info.Width + " - " + info.Height);
Debug.WriteLine(" C : " + upperPading + " " + info.Height);
Debug.WriteLine(" C : " + Xc + " " + Yc);
Debug.WriteLine("XY : " + X1 + " " + Y1);
Debug.WriteLine("XY : " + X2 + " " + Y2);
// Empty Gauge Styling
SKPaint paint1 = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = Color.FromHex("#05c782").ToSKColor(), // Colour of Radial Gauge
StrokeWidth = progressUtils.getFactoredWidth(radialGaugeWidth), // Width of Radial Gauge
StrokeCap = SKStrokeCap.Round // Round Corners for Radial Gauge
};
// Filled Gauge Styling
SKPaint paint2 = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = Color.FromHex("#e0dfdf").ToSKColor(), // Overlay Colour of Radial Gauge
StrokeWidth = progressUtils.getFactoredWidth(radialGaugeWidth), // Overlay Width of Radial Gauge
StrokeCap = SKStrokeCap.Round // Round Corners for Radial Gauge
};
// Defining boundaries for Gauge
SKRect rect = new SKRect(X1, Y1, X2, Y2);
//canvas.DrawRect(rect, paint1);
//canvas.DrawOval(rect, paint1);
// Rendering Empty Gauge
SKPath path1 = new SKPath();
path1.AddArc(rect, startAngle, sweepAngle);
canvas.DrawPath(path1, paint1);
// Rendering Filled Gauge
SKPath path2 = new SKPath();
path2.AddArc(rect, startAngle, (float)sweepAngleSlider.Value);
canvas.DrawPath(path2, paint2);
//---------------- Drawing Text Over Gauge ---------------------------
// Achieved Minutes
using (SKPaint skPaint = new SKPaint())
{
skPaint.Style = SKPaintStyle.Fill;
skPaint.IsAntialias = true;
skPaint.Color = SKColor.Parse("#676a69");
skPaint.TextAlign = SKTextAlign.Center;
skPaint.TextSize = progressUtils.getFactoredHeight(lineSize1);
skPaint.Typeface = SKTypeface.FromFamilyName(
"Arial",
SKFontStyleWeight.Bold,
SKFontStyleWidth.Normal,
SKFontStyleSlant.Upright);
// Drawing Achieved Minutes Over Radial Gauge
if (sw_listToggle.IsToggled)
canvas.DrawText(monthlyWorkout+"", Xc, Yc + progressUtils.getFactoredHeight(lineHeight1), skPaint);
else
canvas.DrawText(dailyWorkout+"", Xc, Yc + progressUtils.getFactoredHeight(lineHeight1), skPaint);
}
// Achieved Minutes Text Styling
using (SKPaint skPaint = new SKPaint())
{
skPaint.Style = SKPaintStyle.Fill;
skPaint.IsAntialias = true;
skPaint.Color = SKColor.Parse("#676a69");
skPaint.TextAlign = SKTextAlign.Center;
skPaint.TextSize = progressUtils.getFactoredHeight(lineSize2);
canvas.DrawText("Minutes", Xc, Yc + progressUtils.getFactoredHeight(lineHeight2), skPaint);
}
// Goal Minutes Text Styling
using (SKPaint skPaint = new SKPaint())
{
skPaint.Style = SKPaintStyle.Fill;
skPaint.IsAntialias = true;
skPaint.Color = SKColor.Parse("#e2797a");
skPaint.TextAlign = SKTextAlign.Center;
skPaint.TextSize = progressUtils.getFactoredHeight(lineSize3);
// Drawing Text Over Radial Gauge
if (sw_listToggle.IsToggled)
canvas.DrawText("Goal " + goal + " Min", Xc, Yc + progressUtils.getFactoredHeight(lineHeight3), skPaint);
else
{
canvas.DrawText("Goal " + goal/30 + " Min", Xc, Yc + progressUtils.getFactoredHeight(lineHeight3), skPaint);
}
}
}
catch (Exception e)
{
Debug.WriteLine(e.StackTrace);
}
}
}
然后为圈子添加animateProgress
。
// Animating the Progress of Radial Gauge
async void animateProgress(int progress)
{
sw_listToggle.IsEnabled = false;
sweepAngleSlider.Value = 1;
// Looping at data interval of 5
for (int i = 0; i < progress; i=i+5)
{
sweepAngleSlider.Value = i;
await Task.Delay(3);
}
sweepAngleSlider.Value = progress;
sw_listToggle.IsEnabled = true;
}
我参考了这个博客关于如何实现它。可以参考一下。
https://medium.com/@KPS250/custom-radial-progress-indicator-in-xamarin-forms-c7ed81840c1e
我上传我的demo给你,你可以根据自己的需要定制。
https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/RadioProgressBar.zip