Xamarin - 径向进展组件问题

Zez*_*ez3 5 android xamarin

我一直在尝试在我的应用程序上实现RadialProgress组件(https://components.xamarin.com/view/radialprogress).我设法在屏幕上显示它,并更改进度颜色,但我找不到改变圆圈内部颜色的方法.

RadialProgressView对象本身有一个BackgroundTintMode字段,它接受DuffPorter.Mode,但每当我尝试设置背景色调模式时,应用程序就会破坏此消息(Message ="no method with name ='setBackgroundTintMode'train ='(Landroid/graphics/PorterDuff $模式;))

有没有办法做我想要的?

谢谢!

Fel*_*ala 8

是的,可以做到.虽然不是以非常直截了当的方式甚至是可维护的方式.

首先,让我们深入了解一下RadialProgressView绘图代码(由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);
    }
Run Code Online (Sandbox Code Playgroud)

我们在这里注意到一些颜色,比如bgCirclePaintbgBorderPaint.如果我们能够更改这些变量的值,我们将能够更改绘制ProgressView的颜色.

问题是RadialProgressView不暴露字段 - 它们都是私有的,因此简单地继承RadialProgressView将不允许我们将它们设置为新值.

但是,我们可以利用反射来更改这些私有字段,如下所示:

        var textPaintMember = typeof(RadialProgressView).GetField("textPaint", BindingFlags.Instance | BindingFlags.NonPublic);
        textPaintMember.SetValue(Instance, MyNewSuperCoolColorPaint);
Run Code Online (Sandbox Code Playgroud)

通过将两者结合起来,我们可以提出一个新的,可自定义的类,如下所示:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这将使我们获得我们追求的结果:

2

注意:注意到我们正在不正当地使用私有字段可能是明智的:我们正在从他们所在的类之外操纵它们.如果Xamarin决定改变RadialProgressView实现的方式,或者甚至只重命名其中一个私有变量,我们的代码将在运行时失败.解决这个问题的更好方法可能是让Xamarin提供你需要的getter/setter.但是,嘿,这种方式更凉爽;)