I am trying to design a control that displays current status of a process, like this image below.
So, we have a circular display of status with colored sections for milestones or checkpoints. In the image, we are already through the first two stages, and third stage is 70% done.
I know there is a control in Jquery that was pretty similar. But I am not sure, if there is a third party control in Xamarin Forms that I can use. If there is no third party control, how should I proceed with the design.
Should I just create images for different stages and display the image? Or should I create a custom control which can take two values, "milestone" and "percentage_complete", and then design maybe a pie chart on the fly?
Using NGraphics
w/ NControl
you can create a "vector" version of your "completeness meter" without creating platform renderers or needing to add libraries like Skia
to your project.
Note: SkiaSharp and other native 2d/3d libraries are great, but add an lot of overhead to an app and if you do not need all their features then the bloat (app size, memory usage, initialization time, etc...) is not worth it (IMHO).
re: https://github.com/praeclarum/NGraphics
I stripped down a MultiSegmentProgressControl
that I did to show you the basics of the arc drawing. The full version that I did allows you to add and animate multiple segments, displaying percentages, break-out segments on touch, etc...
Using NControl
you can create composite controls with touch elements, so it is up to you on how far you need to take it.
re: https://github.com/chrfalch/NControl
public class MultiSegmentProgressControl2 : NControlView
{
double ringWidth = 50;
double ringInnerWidth = 100;
SolidBrush redBush = new SolidBrush(Colors.Red);
RadialGradientBrush redSegmentBrush = new RadialGradientBrush(
new Point(0.5, 0.5),
new Size(.75, .75),
Colors.LightGray,
Colors.Red);
SolidBrush blueBush = new SolidBrush(Colors.Blue);
RadialGradientBrush blueSegmentBrush = new RadialGradientBrush(
new Point(0.5, 0.5),
new Size(.75, .75),
Colors.LightGray,
Colors.Green);
Tuple<double, double> _redSegment;
public Tuple<double, double> RedSegment { get { return _redSegment; } set { _redSegment = value; Invalidate(); } }
Tuple<double, double> _greenSegment;
public Tuple<double, double> GreenSegment { get { return _greenSegment; } set { _greenSegment = value; Invalidate(); } }
public override void Draw(ICanvas canvas, Rect rect)
{
canvas.FillEllipse(rect.TopLeft, rect.Size, Colors.Gray);
var n = rect;
n.X += ringWidth;
n.Y = n.X;
n.Width -= ringWidth * 2;
n.Height = n.Width;
var i = n;
canvas.FillEllipse(n.TopLeft, n.Size, Colors.LightGray);
n.X += ringInnerWidth;
n.Y = n.X;
n.Width -= ringInnerWidth * 2;
n.Height = n.Width;
canvas.FillEllipse(n.TopLeft, n.Size, Colors.White);
var r = rect.Width / 2;
DrawSegment(canvas, rect, ringWidth, redBush, r, _redSegment.Item1, _redSegment.Item2);
DrawSegment(canvas, i, ringInnerWidth, redSegmentBrush, r - ringWidth, _redSegment.Item1, _redSegment.Item2);
DrawSegment(canvas, rect, ringWidth, blueBush, r, _greenSegment.Item1, _greenSegment.Item2);
DrawSegment(canvas, i, ringInnerWidth, blueSegmentBrush, r - ringWidth, _greenSegment.Item1, _greenSegment.Item2);
}
void DrawSegment(ICanvas canvas, Rect rect, double width, Brush brush, double r, double s, double f)
{
canvas.DrawPath(new PathOp[]{
new MoveTo(SegmentEdgePoint(rect.Center, r, s)),
new ArcTo(new Size(rect.Height / 2, rect.Width / 2), false, true, SegmentEdgePoint(rect.Center, r, f)),
new LineTo(SegmentEdgePoint(rect.Center, r - width, f)),
new ArcTo(new Size(r, r), false, false, SegmentEdgePoint(rect.Center, r - width, s)),
new LineTo(SegmentEdgePoint(rect.Center, r, s)),
new ClosePath()
}, null, brush);
}
Point SegmentEdgePoint(Point c, double r, double d)
{
return new Point(
c.X + r * Math.Cos(d * Math.PI / 180),
c.Y + r * Math.Sin(d * Math.PI / 180)
);
}
}
When using NGraphics
I highly recommend using the NGraphics.Editor
or a Xamarin' WorkBook to interactively design your control:
If you can't find an already completed solution (highly recommended if you can find one!) then creating a control with incremental calls to a graphics library with DrawSegment calls might work.
Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With