gpt4 book ai didi

c# - UWP Composition - 将不透明蒙版应用于 ListView 的顶部 30px

转载 作者:太空狗 更新时间:2023-10-29 20:30:04 28 4
gpt4 key购买 nike

如何将效果应用于顶部 30px 从完全透明变为完全不透明的 ListView?这个想法是,当您向下滚动时,顶部的项目逐渐消失。

我正在构建一个 UWP 应用程序,其中设计要求 ListView 的顶部 30px 从不透明度 0 开始并过渡到不透明度 1。从概念上讲,我正在想象一个将应用于 SpriteVisual 顶部的不透明蒙版,但是我不知道如何实现这一目标。

我正在尝试使用 Windows 10 周年纪念版、Composition 和 Win2D。

编辑:一张图可能画出1000字:

Example of the fade

如果您看这张图片,在左下角和右下角有两个内容元素。虽然背景看起来是黑色,但实际上是渐变色。如果您检查这两个元素的顶部,它们在顶部变得更加透明,透过背景显示出来。这就是我想要达到的效果。

编辑 2:为了显示我正在寻找的效果的结果,这里有一个 GIF,它显示了我使用叠加位图时的效果: Scrolling Images

页眉背景图片为: header background

下方的 30 像素具有 alpha 渐变并出现在 gridview 上方,给出了 grid view 项目淡出并在背景下滑动的明显效果。

XAML 布局如下所示:

<Page
x:Class="App14.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App14"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="150" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<Image Source="/Assets/background.png"
Grid.Row="0"
Grid.RowSpan="2"
VerticalAlignment="Top"
Stretch="None" />

<GridView Grid.Row="1"
Margin="96,-30,96,96">
<GridView.Resources>
<Style TargetType="Image">
<Setter Property="Height" Value="400" />
<Setter Property="Width" Value="300" />
<Setter Property="Margin" Value="30" />
</Style>
</GridView.Resources>
<Image Source="Assets/1.jpg" />
<Image Source="Assets/2.jpg" />
<Image Source="Assets/3.jpg" />
<Image Source="Assets/4.jpg" />
<Image Source="Assets/5.jpg" />
<Image Source="Assets/6.jpg" />
<Image Source="Assets/7.jpg" />
<Image Source="Assets/8.jpg" />
<Image Source="Assets/9.jpg" />
<Image Source="Assets/10.jpg" />
<Image Source="Assets/11.jpg" />
<Image Source="Assets/12.jpg" />
</GridView>

<!-- Header above content -->

<Image Grid.Row="0" Source="/Assets/header_background.png"
Stretch="None" />

<TextBlock x:Name="Title"
Grid.Row="0"
FontSize="48"
Text="This Is A Title"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="White" />


</Grid>

最佳答案

所以在 @sohcatt 的帮助下在 Windows UI 开发实验室问题列表中,我构建了一个有效的解决方案。

enter image description here

这是 XAML:

    <Grid x:Name="LayoutRoot">

<Image x:Name="BackgroundImage"
ImageOpened="ImageBrush_OnImageOpened"
Source="../Assets/blue-star-background-wallpaper-3.jpg"
Stretch="UniformToFill" />

<GridView x:Name="Posters" Margin="200,48">
<GridView.Resources>
<Style TargetType="ListViewItem" />
<Style TargetType="Image">
<Setter Property="Stretch" Value="UniformToFill" />
<Setter Property="Width" Value="300" />
<Setter Property="Margin" Value="12" />
</Style>
</GridView.Resources>
<GridViewItem>
<Image Source="Assets/Posters/1.jpg" />
</GridViewItem>
<GridViewItem>
<Image Source="Assets/Posters/2.jpg" />
</GridViewItem>
<GridViewItem>
<Image Source="Assets/Posters/3.jpg" />
</GridViewItem>
<GridViewItem>
<Image Source="Assets/Posters/4.jpg" />
</GridViewItem>
<GridViewItem>
<Image Source="Assets/Posters/5.jpg" />
</GridViewItem>
<GridViewItem>
<Image Source="Assets/Posters/6.jpg" />
</GridViewItem>
<GridViewItem>
<Image Source="Assets/Posters/7.jpg" />
</GridViewItem>
<GridViewItem>
<Image Source="Assets/Posters/8.jpg" />
</GridViewItem>
<GridViewItem>
<Image Source="Assets/Posters/9.jpg" />
</GridViewItem>
<GridViewItem>
<Image Source="Assets/Posters/10.jpg" />
</GridViewItem>
<GridViewItem>
<Image Source="Assets/Posters/11.jpg" />
</GridViewItem>
<GridViewItem>
<Image Source="Assets/Posters/12.jpg" />
</GridViewItem>
</GridView>
</Grid>

代码如下:

        private bool _imageLoaded;

// this is an initial way of handling resize
// I will investigate expressions
private async void OnSizeChanged(object sender, SizeChangedEventArgs args)
{
if (!_imageLoaded)
{
return;
}
await RenderOverlayAsync();
}

private async void ImageBrush_OnImageOpened(object sender, RoutedEventArgs e)
{
_imageLoaded = true;
await RenderOverlayAsync();
}

// this method must be called after the background image is opened, otherwise
// the render target bitmap is empty
private async Task RenderOverlayAsync()
{
// setup composition
// (in line here for readability - will be member variables moving forwards)
var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
var canvasDevice = new CanvasDevice();
var compositionDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, canvasDevice);

// determine what region of the background we need to "cut out" for the overlay
GeneralTransform gt = Posters.TransformToVisual(LayoutRoot);
Point elementPosition = gt.TransformPoint(new Point(0, 0));

// our overlay height is as wide as our poster control and is 30 px high
var overlayHeight = 30;
var areaToRender = new Rect(elementPosition.X, elementPosition.Y, Posters.ActualWidth, overlayHeight);

// Capture the image from our background.
//
// Note: this is just the <Image/> element, not the Grid. If we took the <Grid/>,
// we would also have all of the child elements, such as the <GridView/> rendered as well -
// which defeats the purpose!
//
// Note 2: this method must be called after the background image is opened, otherwise
// the render target bitmap is empty
var bitmap = new RenderTargetBitmap();
await bitmap.RenderAsync(BackgroundImage);
var pixels = await bitmap.GetPixelsAsync();

// we need the display DPI so we know how to handle the bitmap correctly when we render it
var dpi = DisplayInformation.GetForCurrentView().LogicalDpi;

// load the pixels from RenderTargetBitmap onto a CompositionDrawingSurface
CompositionDrawingSurface uiElementBitmapSurface;
using (
// this is the entire background image
// Note we are using the display DPI here.
var canvasBitmap = CanvasBitmap.CreateFromBytes(
canvasDevice, pixels.ToArray(),
bitmap.PixelWidth,
bitmap.PixelHeight,
DirectXPixelFormat.B8G8R8A8UIntNormalized,
dpi)
)
{
// we create a surface we can draw on in memory.
// note we are using the desired size of our overlay
uiElementBitmapSurface =
compositionDevice.CreateDrawingSurface(
new Size(areaToRender.Width, areaToRender.Height),
DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
using (var session = CanvasComposition.CreateDrawingSession(uiElementBitmapSurface))
{
// here we draw just the part of the background image we wish to use to overlay
session.DrawImage(canvasBitmap, 0, 0, areaToRender);
}
}

// assign CompositionDrawingSurface to the CompositionSurfacebrush with which I want to paint the relevant SpriteVisual
var backgroundImageBrush = _compositor.CreateSurfaceBrush(uiElementBitmapSurface);

// load in our opacity mask image.
// this is created in a graphic tool such as paint.net
var opacityMaskSurface = await SurfaceLoader.LoadFromUri(new Uri("ms-appx:///Assets/OpacityMask.Png"));

// create surfacebrush with ICompositionSurface that contains the background image to be masked
backgroundImageBrush.Stretch = CompositionStretch.UniformToFill;

// create surfacebrush with ICompositionSurface that contains the gradient opacity mask asset
CompositionSurfaceBrush opacityBrush = _compositor.CreateSurfaceBrush(opacityMaskSurface);
opacityBrush.Stretch = CompositionStretch.UniformToFill;

// create maskbrush
CompositionMaskBrush maskbrush = _compositor.CreateMaskBrush();
maskbrush.Mask = opacityBrush; // surfacebrush with gradient opacity mask asset
maskbrush.Source = backgroundImageBrush; // surfacebrush with background image that is to be masked

// create spritevisual of the approproate size, offset, etc.
SpriteVisual maskSprite = _compositor.CreateSpriteVisual();
maskSprite.Size = new Vector2((float)Posters.ActualWidth, overlayHeight);
maskSprite.Brush = maskbrush; // paint it with the maskbrush

// set the sprite visual as a child of the XAML element it needs to be drawn on top of
ElementCompositionPreview.SetElementChildVisual(Posters, maskSprite);
}

关于c# - UWP Composition - 将不透明蒙版应用于 ListView 的顶部 30px,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38361081/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com