圆形进度条 | 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