Xamarin - 径向进展组件问题

时间:2015-07-14 15:49:44

标签: android xamarin

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

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

有没有办法做我想做的事?

谢谢!

2 个答案:

答案 0 :(得分: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);
    }

我们注意到了一些颜色,例如bgCirclePaintbgBorderPaint。如果我们能够更改这些变量的值,我们将能够更改绘制ProgressView的颜色。

问题是RadialProgressView没有公开字段 - 它们都是私有的,因此只需继承RadialProgressView就不允许我们将它们设置为新值。

但是,我们可以使用reflection更改这些私有字段,如下所示:

        var textPaintMember = typeof(RadialProgressView).GetField("textPaint", BindingFlags.Instance | BindingFlags.NonPublic);
        textPaintMember.SetValue(Instance, MyNewSuperCoolColorPaint);

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

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);
    }
}

这将为我们带来我们之后的结果:

2

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

答案 1 :(得分:1)

您可以尝试实施自定义ViewRenderer并访问基础本机Android视图,以根据需要进行修改。 https://blog.xamarin.com/using-custom-controls-in-xamarin.forms-on-android/

关于" setBackgroundTintMode"的错误方法表示您可能需要更新Xamarin平台以确保最新的API可用