在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
相关产品推荐
相关产品推荐

