9
votes

I want to know the best way to create the similar thing of this image with Xamarin Forms:

enter image description here

I never created anything like that. I know how to use Progress bar, but not a 'circle progress bar'

Thank you for your help and for any tips.

EDIT : If you have a plugin/nuget to do that, it's cool, but I would like to know how to do it myself. I never made something like this.

6
Have you got the solution for iOS and Android?AbsoluteSith

6 Answers

3
votes

My Trip Countdown is a Xamarin.Forms sample to show how to create goodlooking UI with Xamarin.Forms. This sample is based on Countdown timer designed by Victoria Sgarro.

Here You go: https://github.com/jsuarezruiz/MyTripCountdownenter image description here

2
votes

You can achieve this using Custom Renderer.

Xamarin's James Montemagno have a good guide regarding creating custom circular progress bar.

https://devblogs.microsoft.com/xamarin/using-custom-controls-in-xamarin-forms-on-android/

Official Documentation on Xamarin.Forms Custom Renderers can be found at https://developer.xamarin.com/guides/xamarin-forms/custom-renderer/

1
votes

I found this post to have the best solution so far for a Xamarin Forms "circle progress bar." Basically you use two half circle images and rotate them based on the progress which I think is a really creative and elegant solution. No custom renderers needed!

1
votes

I know it's an old post, but some people like me got this thread when we do a search for circular progress.

Andreas Hennig made a nice plugin, working for iOS and Android, you can install it from nuget: Progress Ring Control Plugin

XAML

  1. Add XAML namespace:

    xmlns:control="clr-namespace:ProgressRingControl.Forms.Plugin;assembly=ProgressRing.Forms.Plugin"

  2. Add the xaml:

    <control:ProgressRing RingThickness="20" Progress="0.5"/>

You can find it at:

https://github.com/AndreasHennig/ProgressRingPlugin

1
votes

I tried finding a library for Xamarin Forms but couldn't find any which had support for both Android as well as iOS. Moreover, there isn't much of choice to choose from different types of progress indicators. I ended up building up my own custom radial progress indicator widget in Xamarin Forms using SkiaSharp which supported both Android & iOS.

Tutorial Link: https://medium.com/@kpshinde25/custom-radial-progress-indicator-in-xamarin-forms-c7ed81840c1e

You can modify the code to have a circle, multi-circle indicators etc as per your requirement.

0
votes

Code from https://github.com/billreiss/xamlnative/tree/master/XamarinForms/CircularProgress

public class CircularProgress : Grid
{
    View progress1;
    View progress2;
    View background1;
    View background2;
    public CircularProgress()
    {
        var baseUrl = "https://github.com/billreiss/xamlnative/raw/master/XamarinForms/CircularProgress/CircularProgress/CircularProgress.Droid/Resources/drawable/";
        
        progress1 = CreateImage($"{baseUrl}progress_done.png");
        background1 = CreateImage($"{baseUrl}progress_pending.png");
        background2 = CreateImage($"{baseUrl}progress_pending.png");
        progress2 = CreateImage($"{baseUrl}progress_done.png");
        HandleProgressChanged(1, 0);
    }

    private View CreateImage(string imageName)
    {
        var img = new Image();
        img.Source = ImageSource.FromUri(new Uri(imageName));
        this.Children.Add(img);
        return img;
    }

    public static BindableProperty ProgressProperty =
BindableProperty.Create(nameof(Progress), typeof(double), typeof(CircularProgress), 0d, propertyChanged: ProgressChanged);

    private static void ProgressChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var c = bindable as CircularProgress;
        c.HandleProgressChanged(Clamp((double)oldValue, 0, 1), Clamp((double)newValue, 0, 1));
    }

    static double Clamp(double value, double min, double max)
    {
        if (value <= max && value >= min) return value;
        else if (value > max) return max;
        else return min;
    }

    private void HandleProgressChanged(double oldValue, double p)
    {
        if (p < .5)
        {
            if (oldValue >= .5)
            {
                // this code is CPU intensive so only do it if we go from >=50% to <50%
                background1.IsVisible = true;
                progress2.IsVisible = false;
                background2.Rotation = 180;
                progress1.Rotation = 0;
            }
            double rotation = 360 * p;
            background1.Rotation = rotation;
        }
        else
        {
            if (oldValue < .5)
            {
                // this code is CPU intensive so only do it if we go from <50% to >=50%
                background1.IsVisible = false;
                progress2.IsVisible = true;
                progress1.Rotation = 180;
            }
            double rotation = 360 * p;
            background2.Rotation = rotation;
        }
    }

    public double Progress
    {
        get { return (double)this.GetValue(ProgressProperty); }
        set { SetValue(ProgressProperty, value); }
    }
}