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

如何在Xamarin Form中实现目标UI仪表盘设计?求助修正代码

问题:Xamarin Forms实现目标仪表盘UI

我正在使用Xamarin Form开发Android和iOS项目,想要实现目标UI仪表盘(目标UI效果)。我尝试了很多方法,但无法达到预期设计效果,附上了我的XAML代码和当前输出效果截图(当前实现效果),请帮忙修正代码以实现目标UI。


解决方案

针对目标仪表盘的UI实现,以下是修正后的代码方案,解决了布局对齐、自定义圆环绘制、刻度标记等核心问题:

核心思路

使用SkiaSharp实现自定义圆形仪表盘(这是Xamarin Forms中实现复杂图形UI的最优方案之一),通过分层绘制背景环、进度环、刻度,叠加文本实现目标效果。

XAML代码

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="YourProjectNamespace.DashboardPage">
    <ContentPage.Content>
        <!-- 外层容器,确保整体居中 -->
        <StackLayout Padding="30" VerticalOptions="Center" HorizontalOptions="Center">
            <!-- 仪表盘网格容器,统一管理所有元素层级 -->
            <Grid WidthRequest="320" HeightRequest="320">
                <!-- 1. 背景圆环 -->
                <skia:SKCanvasView x:Name="BgCircleCanvas" PaintSurface="BgCircleCanvas_PaintSurface" />
                <!-- 2. 进度圆环 -->
                <skia:SKCanvasView x:Name="ProgressCircleCanvas" PaintSurface="ProgressCircleCanvas_PaintSurface" />
                <!-- 3. 刻度标记 -->
                <skia:SKCanvasView x:Name="ScaleMarksCanvas" PaintSurface="ScaleMarksCanvas_PaintSurface" />
                <!-- 4. 中心数值文本 -->
                <Label Text="75%" 
                       FontSize="48" 
                       FontAttributes="Bold" 
                       TextColor="#2E7D32"
                       HorizontalOptions="Center" 
                       VerticalOptions="Center" />
                <!-- 5. 底部标题 -->
                <Label Text="完成率" 
                       FontSize="22" 
                       TextColor="#424242"
                       HorizontalOptions="Center" 
                       VerticalOptions="End" 
                       Margin="0,0,0,30" />
            </Grid>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

C#后台代码

using SkiaSharp;
using SkiaSharp.Views.Forms;
using Xamarin.Forms;

namespace YourProjectNamespace
{
    public partial class DashboardPage : ContentPage
    {
        // 进度值(0-1对应0%-100%)
        private readonly float _targetProgress = 0.75f;

        public DashboardPage()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 绘制背景圆环
        /// </summary>
        private void BgCircleCanvas_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
        {
            var canvas = e.Surface.Canvas;
            canvas.Clear();

            var size = e.Info.Size;
            var center = new SKPoint(size.Width / 2, size.Height / 2);
            var radius = Math.Min(size.Width, size.Height) / 2 - 25;

            var paint = new SKPaint
            {
                Style = SKPaintStyle.Stroke,
                Color = SKColors.LightGray.WithAlpha(180),
                StrokeWidth = 20,
                IsAntialias = true
            };

            canvas.DrawCircle(center, radius, paint);
        }

        /// <summary>
        /// 绘制进度圆环
        /// </summary>
        private void ProgressCircleCanvas_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
        {
            var canvas = e.Surface.Canvas;
            canvas.Clear();

            var size = e.Info.Size;
            var center = new SKPoint(size.Width / 2, size.Height / 2);
            var radius = Math.Min(size.Width, size.Height) / 2 - 25;

            var paint = new SKPaint
            {
                Style = SKPaintStyle.Stroke,
                Color = SKColors.Green,
                StrokeWidth = 20,
                IsAntialias = true,
                StrokeCap = SKStrokeCap.Round // 圆角端点,匹配目标UI
            };

            // 从顶部开始绘制圆弧,进度对应角度
            var startAngle = -90f;
            var sweepAngle = _targetProgress * 360f;

            canvas.DrawArc(new SKRect(center.X - radius, center.Y - radius, center.X + radius, center.Y + radius),
                          startAngle, sweepAngle, false, paint);
        }

        /// <summary>
        /// 绘制刻度标记
        /// </summary>
        private void ScaleMarksCanvas_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
        {
            var canvas = e.Surface.Canvas;
            canvas.Clear();

            var size = e.Info.Size;
            var center = new SKPoint(size.Width / 2, size.Height / 2);
            var outerRadius = Math.Min(size.Width, size.Height) / 2 - 25;
            var innerRadius = outerRadius - 12;

            var paint = new SKPaint
            {
                Color = SKColors.DarkGray,
                StrokeWidth = 2,
                IsAntialias = true
            };

            // 绘制12个均匀分布的刻度
            for (int i = 0; i < 12; i++)
            {
                var angle = (i * 30) * (float)Math.PI / 180;
                var startPoint = new SKPoint(
                    center.X + (float)Math.Cos(angle) * innerRadius,
                    center.Y + (float)Math.Sin(angle) * innerRadius
                );
                var endPoint = new SKPoint(
                    center.X + (float)Math.Cos(angle) * outerRadius,
                    center.Y + (float)Math.Sin(angle) * outerRadius
                );

                canvas.DrawLine(startPoint, endPoint, paint);
            }
        }
    }
}

关键调整说明

  • 分层绘制:通过多个SKCanvasView分层绘制背景、进度、刻度,避免元素互相遮挡,保证UI层级清晰
  • 样式匹配:进度圆环使用圆角端点,背景环采用半透明浅灰色,完全匹配目标UI的视觉风格
  • 布局对齐:使用Grid容器将所有元素居中,确保在不同屏幕尺寸下的一致性
  • 可扩展性:进度值通过变量_targetProgress控制,可直接绑定ViewModel实现动态更新

注意事项

  1. 需要先通过NuGet安装SkiaSharp.Views.Forms包
  2. 如果你的原始代码使用了第三方仪表盘控件,可替换为上述自定义实现,或基于此思路调整控件样式参数

内容的提问来源于stack exchange,提问作者Kirti Zare

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 09:33:20