Tak, można to zrobić. Chociaż nie w bardzo prosty sposób, a nawet możliwy do utrzymania.
Po pierwsze, niech kopać trochę w kodzie rysunku RadialProgressView
„s (jak wystawiony przez Xamarin Studio Assembly Browser):
protected override void OnDraw(Canvas canvas)
{
// ... there's more stuff here, but you get the idea
canvas.DrawCircle(this.bgCx, this.bgCy, this.radius, this.bgCirclePaint);
canvas.DrawCircle(this.bgCx, this.bgCy, this.innerLineRadius, this.bgBorderPaint);
canvas.DrawText(this.valueText, this.textX, this.textY, this.textPaint);
}
Widzimy tu pewne kolory, jak bgCirclePaint
i bgBorderPaint
. Jeśli będziemy w stanie zmienić wartość tych zmiennych, będziemy mogli zmienić kolor, z którym malowany jest ProgressView.
Problem polega na tym, że RadialProgressView
nie eksponuje pól - wszystkie są prywatne, więc zwyczajne dziedziczenie po RadialProgressView
nie pozwoli nam ustawić ich na nową wartość.
Możemy jednak skorzystać z reflection zmienić te prywatne pola, tak jak poniżej:
var textPaintMember = typeof(RadialProgressView).GetField("textPaint", BindingFlags.Instance | BindingFlags.NonPublic);
textPaintMember.SetValue(Instance, MyNewSuperCoolColorPaint);
Łącząc dwa, możemy wymyślić nowe, niestandardowe klasy jak ten:
public class CustomizableRadialProgressView : RadialProgressView
{
public CustomizableRadialProgressView(Context context) : base(context)
{
}
public void SetTextColor(Color color)
{
var paint = new Paint();
paint.SetTypeface(Typeface.DefaultBold);
paint.Color = color;
paint.AntiAlias = true;
var textPaintMember = typeof(RadialProgressView).GetField("textPaint", BindingFlags.Instance | BindingFlags.NonPublic);
textPaintMember.SetValue(this, paint);
}
public void SetCircleColor(Color color)
{
var paint = new Paint();
paint.SetStyle(Paint.Style.Fill);
paint.Color = color;
paint.AntiAlias = true;
var circlePaintMember = typeof(RadialProgressView).GetField("bgCirclePaint", BindingFlags.Instance | BindingFlags.NonPublic);
circlePaintMember.SetValue(this, paint);
}
public void SetBorderColor(Color color)
{
var paint = new Paint();
paint.SetStyle(Paint.Style.Stroke);
paint.Color = color;
paint.AntiAlias = true;
var circlePaintMember = typeof(RadialProgressView).GetField("bgBorderPaint", BindingFlags.Instance | BindingFlags.NonPublic);
circlePaintMember.SetValue(this, paint);
}
public void SetProgressPackgroundColor(Color color)
{
var paint = new Paint();
paint.SetStyle(Paint.Style.Stroke);
paint.Color = color;
paint.AntiAlias = true;
var circlePaintMember = typeof(RadialProgressView).GetField("bgProgressPaint", BindingFlags.Instance | BindingFlags.NonPublic);
circlePaintMember.SetValue(this, paint);
}
}
to dostanie nam wynik jesteśmy po:
Uwaga: Prawdopodobnie mądrze jest zauważyć, że niewłaściwie używamy prywatnych pól: manipulujemy nimi spoza klasy, w której żyją. Jeśli Xamarin kiedykolwiek zdecyduje się zmienić sposób, w jaki zaimplementowano RadialProgressView
, lub nawet zmienia nazwy jedną ze zmiennych prywatnych, nasz kod nie powiedzie się w czasie wykonywania. Lepszym sposobem podejścia do tego problemu byłoby prawdopodobnie poproszenie Xamarina o dostarczenie potrzebnych programów pobierających/ustawiających. Ale, hej, jest o wiele chłodniej w ten sposób;)
masz jakieś rozwiązanie? – SARATH
Niestety, nie zrobiłem Saratha. Jeszcze nie próbowałem sugestii Miny, więc kiedy to zrobię, dam ci znać. – Zez3