You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.Net MAUI GraphicsView 更新异常求助:Android端进度无法正常渲染

问题分析

你的核心问题出在ProgressChart的继承逻辑错误,以及未正确触发GraphicsView的重绘机制:

  1. ProgressChart同时继承GraphicsView并实现IDrawable是不合理的——GraphicsView是MAUI的UI控件,而IDrawable是负责绘制逻辑的纯接口,应该作为GraphicsView.Drawable的赋值对象,而非让Drawable本身成为控件。
  2. 首次加载时,即使修改了Progress值,你调用的Invalidate()是继承自GraphicsView的自身方法,而非关联的ChartView的重绘触发;返回页面后控件布局已稳定,重绘逻辑才正常生效。
解决方案
  1. 修正ProgressChart的定义:仅实现IDrawable(可选继承BindableObject以支持绑定),移除GraphicsView继承。
  2. 在SunProgress的Progress属性变更时,触发关联的GraphicsView(ChartView)执行Invalidate(),强制重绘Drawable。
  3. 可选:在SunProgress的Loaded事件中手动触发一次重绘,确保首次加载时布局稳定后绘制进度。
修改后的代码示例

1. 修正ProgressChart类

// 仅实现IDrawable,继承BindableObject以支持MVVM绑定(可选)
public class ProgressChart : BindableObject, IDrawable
{
    // 可选:用BindableProperty支持绑定
    public static readonly BindableProperty ProgressProperty = BindableProperty.Create(
        nameof(Progress), typeof(float), typeof(ProgressChart), defaultValue: 0f);

    public float Progress
    {
        get => (float)GetValue(ProgressProperty);
        set => SetValue(ProgressProperty, value);
    }

    public Color Color { get; set; } = Colors.Orange;

    public void Draw(ICanvas canvas, RectF dirtyRect)
    {
        // 避免布局未完成时的无效绘制
        if (dirtyRect.Width <= 0 || dirtyRect.Height <= 0)
            return;

        // 你的绘制逻辑示例
        var centerX = dirtyRect.Center.X;
        var centerY = dirtyRect.Center.Y;
        var radius = Math.Min(dirtyRect.Width, dirtyRect.Height) / 2 - 10;

        // 绘制背景圆环
        canvas.StrokeColor = Colors.Gray;
        canvas.StrokeSize = 10;
        canvas.DrawCircle(centerX, centerY, radius);

        // 绘制进度弧
        canvas.StrokeColor = Color;
        var sweepAngle = 360 * Progress;
        canvas.DrawArc(centerX - radius, centerY - radius, radius * 2, radius * 2, 0, sweepAngle, false);
    }
}

2. 修改SunProgress控件的ProgressChanged方法

public partial class SunProgress : ContentView
{
    public static readonly BindableProperty ProgressProperty = BindableProperty.Create(
        nameof(Progress), typeof(float), typeof(SunProgress), propertyChanged: ProgressChanged);

    public float Progress
    {
        get => (float)GetValue(ProgressProperty);
        set => SetValue(ProgressProperty, value);
    }

    public SunProgress()
    {
        InitializeComponent();
        // 可选:首次加载完成后强制重绘,确保布局稳定后绘制
        Loaded += (s, e) => ChartView.Invalidate();
    }

    private static void ProgressChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var control = bindable as SunProgress;
        if (control == null) return;
        
        control.Chart.Progress = (float)newValue;
        // 关键:触发GraphicsView重绘绑定的Drawable
        control.ChartView.Invalidate();
    }
}

3. 原布局保持不变

<ContentView>
...
    <GraphicsView Grid.Row="0"
                  x:Name="ChartView"
                  HorizontalOptions="Center"
                  HeightRequest="150"
                  WidthRequest="150">
        <GraphicsView.Drawable>
            <controls:ProgressChart x:Name="Chart" />
        </GraphicsView.Drawable>
    </GraphicsView>
...
</ContentView>

内容的提问来源于stack exchange,提问作者Radek Bocoń

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 03:17:25