Skip to content

Instantly share code, notes, and snippets.

@dhindrik

dhindrik/RatingControl.cs

Last active Sep 17, 2020
Embed
What would you like to do?
#nullable enable
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using Xamarin.Forms.Shapes;
namespace ShapeDemo.Controls
{
public class RatingControl : StackLayout
{
public RatingControl()
{
Orientation = StackOrientation.Horizontal;
}
public static BindableProperty RatingProperty = BindableProperty.Create(nameof(Rating), typeof(double), typeof(RatingControl), 0.0, BindingMode.OneWay, propertyChanged: (bindable, newValue, oldValue) =>
{
var control = (RatingControl)bindable;
if (newValue != oldValue)
{
control.Draw();
}
});
private readonly List<Point> originalFullStarPoints = new List<Point>()
{
new Point(96,1.12977573),
new Point(66.9427701,60.0061542),
new Point(1.96882894,69.4474205),
new Point(48.9844145,115.27629),
new Point(37.8855403,179.987692),
new Point(96,149.435112),
new Point(154.11446,179.987692),
new Point(143.015586,115.27629),
new Point(190.031171,69.4474205),
new Point(125.05723,60.0061542),
new Point(96,1.12977573),
};
private readonly List<Point> originalHalfStarPoints = new List<Point>()
{
new Point(96,1.12977573),
new Point(66.9427701,60.0061542),
new Point(1.96882894,69.4474205),
new Point(48.9844145,115.27629),
new Point(37.8855403,179.987692),
new Point(96,149.435112),
new Point(96,1.12977573)
};
private readonly PointCollection fullStarPoints = new PointCollection();
private readonly PointCollection halfStarPoints = new PointCollection();
private double ratio;
private void Draw()
{
Children.Clear();
var newRatio = Size / 200;
if (newRatio != ratio)
{
ratio = newRatio;
CalculatePoints(fullStarPoints, originalFullStarPoints);
CalculatePoints(halfStarPoints, originalHalfStarPoints);
}
for (var i = 1; i <= Max; i++)
{
if (Rating >= i)
{
Children.Add(GetFullStar());
}
else if(Rating > i - 1)
{
Children.Add(GetHalfStar());
}
else
{
Children.Add(GetEmptyStar());
}
}
}
private void CalculatePoints(PointCollection calculated, List<Point> original)
{
calculated.Clear();
foreach (var point in original)
{
var x = point.X * ratio;
var y = point.Y * ratio;
var p = new Point(x, y);
calculated.Add(p);
}
}
private Polygon GetFullStar()
{
var fullStar = new Polygon()
{
Points = fullStarPoints,
Fill = FillColor,
StrokeThickness = StrokeThickness,
Stroke = StrokeColor
};
return fullStar;
}
private Grid GetHalfStar()
{
var grid = new Grid();
var halfStar = new Polygon()
{
Points = halfStarPoints,
Fill = fillColor,
Stroke = Color.Transparent,
StrokeThickness = 0,
};
var emptyStar = new Polygon()
{
Points = fullStarPoints,
StrokeThickness = StrokeThickness,
Stroke = StrokeColor
};
grid.Children.Add(halfStar);
grid.Children.Add(emptyStar);
return grid;
}
private Polygon GetEmptyStar()
{
var emptyStar = new Polygon()
{
Points = fullStarPoints,
StrokeThickness = StrokeThickness,
Stroke = StrokeColor
};
return emptyStar;
}
public double Rating
{
get => (double)GetValue(RatingProperty);
set => SetValue(RatingProperty, value);
}
private int max = 5;
public int Max
{
get => max;
set => Set(ref max, value);
}
private void Set<T>(ref T field, T newValue)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
{
field = newValue;
Draw();
}
}
private Color fillColor = Color.Yellow;
public Color FillColor
{
get => fillColor;
set => Set(ref fillColor, value);
}
private Color strokeColor = Color.Black;
public Color StrokeColor
{
get => strokeColor;
set => Set(ref strokeColor, value);
}
private double strokeThickness = 0;
public double StrokeThickness
{
get => strokeThickness;
set => Set(ref strokeThickness, value);
}
private double size = 50;
public double Size
{
get => size;
set => Set(ref size, value);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment