You need to enable JavaScript to run this app. Xamarin.Forms使用SkiaSharp绘制饼图时弧线颜色无法差异化设置求助
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Forms使用SkiaSharp绘制饼图时弧线颜色无法差异化设置求助

错误原因

  1. 全程使用同一个SKPaint对象绘制所有弧线,且没有根据当前遍历的Profile对象修改画笔颜色,所有绘制都沿用了初始化时硬编码的SKColors.Green
  2. 所有弧线都被添加到同一个SKPath路径对象中,每次调用DrawPath都会重绘之前所有累积的弧线,即使修改了画笔颜色,最后一次绘制也会把所有弧线覆盖为集合最后一个对象的颜色
  3. StartAngle属性的变更通知填写错误,绑定属性变更时错误触发了SweepAngle的通知

修复代码

直接替换你的OnCanvasViewPaintSurface方法即可:

void OnCanvasViewPaintSurface(System.Object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs args)
{
    SKImageInfo info = args.Info;
    SKSurface surface = args.Surface;
    SKCanvas canvas = surface.Canvas;
    canvas.Clear();

    SKPaint FilledCircle = new SKPaint
    {
        Style = SKPaintStyle.Fill,
        Color = Color.LightGray.ToSKColor(),
    };

    // 弧线画笔仅初始化通用属性,颜色后续循环中动态修改
    SKPaint arcPaint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        StrokeWidth = 200,
        IsAntialias = true // 加抗锯齿让边缘更平滑
    };

    SKPoint center = new SKPoint(info.Width / 2, info.Height / 2);
    SKRect _rect = new SKRect(center.X - 150, center.Y - 150, center.X + 150, center.Y + 150);

    // 初始化数据源
    ProfileDetails = new ObservableCollection<Profile>()
    {
        new Profile{Id = 0,Name = "Dog", sKColors = SKColors.Red , Values = 541 },
        new Profile{Id = 1,Name = "Cat",sKColors = SKColors.Pink ,Values = 2587 },
        new Profile{Id = 2,Name = "Horse",sKColors = SKColors.Green, Values = 365 },
        new Profile{Id = 3,Name = "Tiger",sKColors = SKColors.Blue, Values = 257 }
    };

    // 计算总值
    float _total = 0;
    foreach (var item in ProfileDetails)
    {
        _total += item.Values;
    }

    // 用局部变量存当前起始角度,避免依赖绑定属性的通知问题
    float currentStartAngle = 0;
    foreach (var item in ProfileDetails)
    {
        // 计算当前弧的扫过角度
        float percentage = item.Values / _total * 100;
        float sweepAngle = (percentage / 100) * 360 * -1;
        sweepAngle = (float)Math.Round(sweepAngle, 2);

        // 每次新建路径,避免和之前的弧累积
        using (SKPath path = new SKPath())
        {
            path.AddArc(_rect, currentStartAngle, sweepAngle);
            // 动态设置当前弧的颜色
            arcPaint.Color = item.sKColors;
            canvas.DrawPath(path, arcPaint);
        }

        // 更新下一段弧的起始角度
        currentStartAngle += sweepAngle;
    }

    canvas.DrawCircle(center, 80, FilledCircle);
}

额外优化建议

  • 数据源初始化不要放在OnCanvasViewPaintSurface方法里,这个方法会频繁触发,每次都重新初始化集合会造成不必要的性能损耗,建议移到页面构造方法里
  • 可以删掉没用的全局字段_temp、_percentage、_arcAnglePoint,改用循环内局部变量更安全,避免多轮绘制时全局值累积出错

内容的提问来源于stack exchange,提问作者Samy Gray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 21:06:08