我有一个 uwp xaml 应用程序,在 UI 中有一系列按钮。
我正在使用 Windows 组合可视层 API 为 Button 的视觉对象之一的 RotationAngleInDegrees 设置动画。
按钮的内容在我预期的正面是可见的,但是当视觉对象的背面旋转到视图中时,它也是可见的(尽管反转)。
期望的结果是按钮看起来类似于被翻转的扑克牌,其中内容从正面可见,但在卡片翻转时隐藏。
我尝试了很多事情,包括:
修改按钮模板以将内容演示者嵌套在父边框控件中,认为从后面查看时包含可能会遮挡前面
将 Visual 的 BackfaceVisibility 属性设置为 CompositionBackfaceVisibility.Visible
摆弄按钮背景颜色和视觉效果的不透明度设置
但是,Visual 元素似乎仍然是透明的,并且内容显示在旋转的视觉对象的两个面上。
这是 Windows 组合 API 中的限制还是错误?是否有一种简单的解决方法可以使视觉效果的背面显示的内容与正面显示的内容不同?
以下是生成动画的旋转代码的基础知识:
var btnVisual = ElementCompositionPreview.GetElementVisual(btn);
var compositor = btnVisual.Compositor;
ScalarKeyFrameAnimation flipAnimation = compositor.CreateScalarKeyFrameAnimation();
flipAnimation.InsertKeyFrame(0.0f, 0);
flipAnimation.InsertKeyFrame(0.0001f, 180);
flipAnimation.InsertKeyFrame(1f, 0);
flipAnimation.Duration = TimeSpan.FromMilliseconds(800);
flipAnimation.IterationBehavior = AnimationIterationBehavior.Count;
flipAnimation.IterationCount = 1;
btnVisual.CenterPoint = new Vector3((float)(0.5 * btn.ActualWidth),(float) (0.5f * btn.ActualHeight), (float)(btn.ActualWidth/4));
btnVisual.RotationAxis = new Vector3(0.0f, 1f, 0f);
btnVisual.StartAnimation(nameof(btnVisual.RotationAngleInDegrees), flipAnimation);
被翻转的按钮是一个默认的 xaml 按钮,最初的样式非常简单:
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="Margin" Value="10" />
<Setter Property="FontSize" Value="80" />
<Setter Property="FontFamily" Value="Webdings" />
</Style>
我的一项实验涉及修改默认按钮模板以将内容呈现器嵌套在几个边框容器中:
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="Margin" Value="10" />
<Setter Property="FontSize" Value="80" />
<Setter Property="FontFamily" Value="Webdings" />
<Setter Property="Background" Value="Silver" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<PointerUpThemeAnimation Storyboard.TargetName="RootGrid" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<PointerDownThemeAnimation Storyboard.TargetName="RootGrid" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Background="Red">
<Border Background="#FF62FB0A" Margin="10,10,10,10">
<ContentPresenter x:Name="ContentPresenter"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTransitions="{TemplateBinding ContentTransitions}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"/>
</Border>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
特别是部分修改部分是
<Border Background="Red">
<Border Background="#FF62FB0A" Margin="10,10,10,10">
<ContentPresenter x:Name="ContentPresenter"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTransitions="{TemplateBinding ContentTransitions}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"/>
</Border>
</Border>
这帮助我确认将按钮内容放在边框容器中并不会阻止视觉在旋转时被看到。