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

在MAUI中如何将Grid/Border/Frame背景设置为平铺图案?

MAUI 实现布局背景图片平铺方案

MAUI原生不直接支持通过XAML内置控件实现图片平铺作为Grid/Border/Frame的背景,你期望的<Image Mode="Tiled"/>写法无法直接生效,需要通过自定义Brush或者第三方库来实现。以下是两种可行的实现方案:

方案1:自定义跨平台TileBrush

通过继承MAUI的Brush类,手动实现图片平铺绘制逻辑:

1. 创建自定义TileBrush类

using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;

namespace YourAppNamespace
{
    public class TileBrush : Brush
    {
        public static readonly BindableProperty SourceProperty =
            BindableProperty.Create(nameof(Source), typeof(ImageSource), typeof(TileBrush));

        public ImageSource Source
        {
            get => (ImageSource)GetValue(SourceProperty);
            set => SetValue(SourceProperty, value);
        }

        private IImage _tileImage;

        public override void Paint(ICanvas canvas, RectF dirtyRect)
        {
            if (_tileImage == null && Source != null)
            {
                // 异步加载图片资源
                var imageLoader = Source.GetImageLoader();
                _ = imageLoader.LoadImageAsync(image =>
                {
                    _tileImage = image;
                    canvas?.Invalidate();
                });
                return;
            }

            if (_tileImage == null || _tileImage.Width <= 0 || _tileImage.Height <= 0)
                return;

            // 循环平铺绘制图片
            float tileWidth = _tileImage.Width;
            float tileHeight = _tileImage.Height;

            for (float y = dirtyRect.Top; y < dirtyRect.Bottom; y += tileHeight)
            {
                for (float x = dirtyRect.Left; x < dirtyRect.Right; x += tileWidth)
                {
                    canvas.DrawImage(_tileImage, x, y, tileWidth, tileHeight);
                }
            }
        }
    }
}

2. 在XAML中使用

先引入自定义控件的命名空间:

xmlns:local="clr-namespace:YourAppNamespace"

然后应用到Border/Grid/Frame的背景:

<Border>
    <Border.Background>
        <local:TileBrush Source="volcano_tile.png" />
    </Border.Background>
    <!-- 内部内容 -->
</Border>

方案2:基于SkiaSharp实现更稳定的平铺

SkiaSharp提供了原生的图片平铺渲染能力,适合对渲染稳定性有要求的游戏场景:

1. 安装SkiaSharp包

在项目中安装SkiaSharp.Views.Maui NuGet包。

2. 创建SkiaTileBrush类

using SkiaSharp;
using SkiaSharp.Views.Maui;
using Microsoft.Maui.Controls;

namespace YourAppNamespace
{
    public class SkiaTileBrush : Brush
    {
        public static readonly BindableProperty SourceProperty =
            BindableProperty.Create(nameof(Source), typeof(string), typeof(SkiaTileBrush));

        public string Source
        {
            get => (string)GetValue(SourceProperty);
            set => SetValue(SourceProperty, value);
        }

        private SKBitmap _tileBitmap;

        public override void Paint(ICanvas canvas, RectF dirtyRect)
        {
            if (_tileBitmap == null && !string.IsNullOrEmpty(Source))
            {
                // 从应用包加载图片资源
                using var stream = FileSystem.OpenAppPackageFileAsync(Source).Result;
                _tileBitmap = SKBitmap.Decode(stream);
                canvas?.Invalidate();
                return;
            }

            if (_tileBitmap == null) return;

            // 使用SkiaSharp的Shader实现平铺
            var skCanvas = (canvas as SKCanvasView.SKCanvasRenderer)?.Canvas;
            if (skCanvas == null) return;

            using var tileShader = SKShader.CreateBitmap(_tileBitmap, SKShaderTileMode.Repeat, SKShaderTileMode.Repeat);
            using var paint = new SKPaint { Shader = tileShader };

            skCanvas.DrawRect(dirtyRect.ToSKRect(), paint);
        }
    }
}

3. XAML使用方式

和方案1一致,直接替换Brush类型即可:

<Grid>
    <Grid.Background>
        <local:SkiaTileBrush Source="volcano_tile.png" />
    </Grid.Background>
</Grid>

注意事项

  • 确保图片资源volcano_tile.png的Build Action设置为MauiImage,否则无法正确加载。
  • 自定义Brush的图片加载是异步的,首次渲染可能会有短暂延迟;若需要预加载图片,可以在页面初始化时提前加载资源。
  • SkiaSharp方案的渲染性能更稳定,适合游戏这类对帧率要求较高的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 06:12:28