之前的问题涉及WinRT(Windows 8),但我希望有一个基于刷子的解决方案,而不是用图像填充画布。
目前,在UWP应用程序中显示平铺模式的背景图像只有两种解决方案,第一种是使用画布进行填充,这是您已知的。
我正在使用的第二种方法是创建一个面板并在其上绘制图像,这个想法源自于this article。
这种方法的作用是利用我们在矩形形状中重复绘制线条集的事实。首先,它尝试以与我们的瓷砖相同高度的块来绘制顶部的块。然后将该块复制到达底部。
我修改了一些代码并修复了一些问题:
public class TiledBackground : Panel
set
}
public static readonly DependencyProperty BackgroundImageProperty =
DependencyProperty.Register("BackgroundImage", typeof(ImageSource), typeof(TiledBackground), new PropertyMetadata(null, BackgroundImageChanged));
private static void BackgroundImageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
private static void DesignDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
private ImageBrush backgroundImageBrush = null;
private bool tileImageDataRebuildNeeded = true;
private byte[] tileImagePixels = null;
private int tileImageWidth = 0;
private int tileImageHeight = 0;
private readonly BitmapPixelFormat bitmapPixelFormat = BitmapPixelFormat.Bgra8;
private readonly BitmapTransform bitmapTransform = new BitmapTransform();
private readonly BitmapAlphaMode bitmapAlphaMode = BitmapAlphaMode.Straight;
private readonly ExifOrientationMode exifOrientationMode = ExifOrientationMode.IgnoreExifOrientation;
private readonly ColorManagementMode coloManagementMode = ColorManagementMode.ColorManageToSRgb;
public TiledBackground()
private async void TiledBackground_SizeChanged(object sender, SizeChangedEventArgs e)
private async void OnBackgroundImageChanged()
private async void OnDesignDataChanged()
private async Task RebuildTileImageData()
var imageSource = new Uri(imgUri);
StorageFile storageFile = await StorageFile.GetFileFromApplicationUriAsync(imageSource);
using (var imageStream = await storageFile.OpenAsync(FileAccessMode.Read))
}
}
private byte[] CreateBackgroud(int width, int height)
Array.Copy(tileImagePixels, tileIndex, data, dataIndex,
(width - fullTileInRowCount * tileImageWidth) * bytesPerPixel);
y++;
}
int rowLength = width * bytesPerPixel;
int blockLength = this.tileImageHeight * rowLength;
while (y <= (height - tileImageHeight))
for (int row = y; row < height; row++)
Array.Copy(data, (row - tileImageHeight) * rowLength, data, row * rowLength, rowLength);
return data;
}
private async Task Render(int width, int height)
ticks - ms", sw.ElapsedTicks, sw.ElapsedMilliseconds);
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, randomAccessStream);
encoder.SetPixelData(this.bitmapPixelFormat, this.bitmapAlphaMode, (uint)width, (uint)height, 96, 96, backgroundPixels);
await encoder.FlushAsync();
if (this.backgroundImageBrush.ImageSource == null)
else ((BitmapImage)this.backgroundImageBrush.ImageSource).SetSource(randomAccessStream);
}
}
else this.backgroundImageBrush.ImageSource = null;
fullsw.Stop();
Debug.WriteLine("Background rendering finished: ticks - ms", fullsw.ElapsedTicks, fullsw.ElapsedMilliseconds);
}
}
使用方法:
<Grid x:Name="rootGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<tileCtrl:TiledBackground
BackgroundImage="Assets/avatar1.png"
Width="{Binding ActualWidth, ElementName=rootGrid}" Height="{Binding ActualHeight, ElementName=rootGrid}"/>
</Grid>
![Screenshot](https://istack.dev59.com/NQtKQ.webp)
查看解决方案请访问 Github