Sì, si può fare. Anche se non in modo molto semplice o addirittura gestibile.
In primo luogo, cerchiamo di scavare un po 'in codice di disegno RadialProgressView
s' (come esposto da Xamarin Studio Assemblea 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);
}
Notiamo alcuni colori qui, come bgCirclePaint
e bgBorderPaint
. Se siamo in grado di cambiare il valore di queste variabili, saremo in grado di cambiare il colore con cui viene dipinto ProgressView.
Il problema è che RadialProgressView
non espone i campi - sono tutti privati, quindi semplicemente ereditare da RadialProgressView
non ci permetterà di impostarli su un nuovo valore.
Tuttavia, siamo in grado di fare uso di reflection di modificare questi campi privati, in questo modo:
var textPaintMember = typeof(RadialProgressView).GetField("textPaint", BindingFlags.Instance | BindingFlags.NonPublic);
textPaintMember.SetValue(Instance, MyNewSuperCoolColorPaint);
Combinando i due, siamo in grado di trovare una nuova classe personalizzabile in questo modo:
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);
}
}
Questo ci otterrà il risultato che cerchiamo:
Nota: è probabilmente opportuno notare che stiamo facendo un uso improprio dei campi privati: li stiamo manipolando al di fuori della classe in cui vivono. Se Xamarin decide di cambiare il modo in cui è implementato RadialProgressView
, o anche solo rinomina una delle variabili private, il nostro codice fallirà in fase di runtime. Il modo migliore per affrontare questo problema sarebbe probabilmente chiedere a Xamarin di fornire i getter/setter di cui hai bisogno. Ma, hey, è così molto più fresco in questo modo;)
hai una soluzione per questo? – SARATH
Sfortunatamente, non ho fatto Sarath. Non ho ancora provato il suggerimento di Mina, anche se così quando lo farò ti farò sapere. – Zez3