增加了动画以及用Style重写了样式。
FlipPanel.cs控制逻辑
using Avalonia; using Avalonia.Animation.Easings; using Avalonia.Controls; using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using System;namespace AvaloniaUI {[TemplatePart("PART_FrontHost", typeof(Border))][TemplatePart("PART_BackHost", typeof(Border))][TemplatePart("PART_FlipButton", typeof(ToggleButton))]public class FlipPanel2 : TemplatedControl{// ========== 依赖属性 ==========public static readonly StyledProperty<Control?> FrontContentProperty =AvaloniaProperty.Register<FlipPanel2, Control?>(nameof(FrontContent));public static readonly StyledProperty<Control?> BackContentProperty =AvaloniaProperty.Register<FlipPanel2, Control?>(nameof(BackContent));public static readonly StyledProperty<bool> IsFlippedProperty =AvaloniaProperty.Register<FlipPanel2, bool>(nameof(IsFlipped));public static readonly StyledProperty<double> FlipAngleProperty =AvaloniaProperty.Register<FlipPanel2, double>(nameof(FlipAngle), 0d);// ========== CLR 包装 ==========public Control? FrontContent{get => GetValue(FrontContentProperty);set => SetValue(FrontContentProperty, value);}public Control? BackContent{get => GetValue(BackContentProperty);set => SetValue(BackContentProperty, value);}public bool IsFlipped{get => GetValue(IsFlippedProperty);set => SetValue(IsFlippedProperty, value);}public double FlipAngle{get => GetValue(FlipAngleProperty);set => SetValue(FlipAngleProperty, value);}// ========== 模板部件 ==========private ToggleButton? flipButton;public FlipPanel2(){// 监听属性变化this.GetObservable(IsFlippedProperty).Subscribe(_ =>{UpdatePseudoClasses();});}protected override void OnApplyTemplate(TemplateAppliedEventArgs e){base.OnApplyTemplate(e);flipButton = e.NameScope.Find<ToggleButton>("PART_FlipButton");if (flipButton != null)flipButton.Click += (_, _) => ToggleFlipped();UpdatePseudoClasses();}private void ToggleFlipped(){IsFlipped = !IsFlipped;}private void UpdatePseudoClasses(){PseudoClasses.Set(":flipped", IsFlipped);}} }
FlipPanelAlternateTemplate.axaml代码
<Window xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="using:AvaloniaUI"x:Class="AvaloniaUI.FlipPanelAlternateTemplate"Width="350" Height="300"><Window.Resources><ControlTemplate x:Key="FancyFlipPanel" TargetType="local:FlipPanel2"><Grid><!-- FRONT --><Border x:Name="PART_FrontHost"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"CornerRadius="{TemplateBinding CornerRadius}"Background="#E3F2FD"RenderTransformOrigin="0.5,0.5"><ContentPresenter Content="{TemplateBinding FrontContent}"HorizontalAlignment="Center"VerticalAlignment="Center"/><Border.Styles><!-- 翻转到背面 --><Style Selector="local|FlipPanel2:flipped /template/ Border#PART_FrontHost"><Style.Animations><Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"><KeyFrame Cue="0%"><Setter Property="ScaleTransform.ScaleY" Value="1"/><Setter Property="BlurEffect.Radius" Value="0"/></KeyFrame><KeyFrame Cue="100%"><Setter Property="ScaleTransform.ScaleY" Value="0"/><Setter Property="BlurEffect.Radius" Value="30"/></KeyFrame></Animation></Style.Animations></Style><!-- 回到正面 --><Style Selector="local|FlipPanel2:not(:flipped) /template/ Border#PART_FrontHost"><Style.Animations><Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"><KeyFrame Cue="0%"><Setter Property="ScaleTransform.ScaleY" Value="0"/><Setter Property="BlurEffect.Radius" Value="30"/></KeyFrame><KeyFrame Cue="100%"><Setter Property="ScaleTransform.ScaleY" Value="1"/><Setter Property="BlurEffect.Radius" Value="0"/></KeyFrame></Animation></Style.Animations></Style></Border.Styles></Border><!-- BACK --><Border x:Name="PART_BackHost"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"CornerRadius="{TemplateBinding CornerRadius}"Background="#FFF3E0"RenderTransformOrigin="0.5,0.5"><ContentPresenter Content="{TemplateBinding BackContent}"HorizontalAlignment="Center"VerticalAlignment="Center"/><Border.Styles><Style Selector="local|FlipPanel2:flipped /template/ Border#PART_BackHost"><Style.Animations><Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"><KeyFrame Cue="0%"><Setter Property="ScaleTransform.ScaleY" Value="0"/><Setter Property="BlurEffect.Radius" Value="30"/></KeyFrame><KeyFrame Cue="100%"><Setter Property="ScaleTransform.ScaleY" Value="1"/><Setter Property="BlurEffect.Radius" Value="0"/></KeyFrame></Animation></Style.Animations></Style><Style Selector="local|FlipPanel2:not(:flipped) /template/ Border#PART_BackHost"><Style.Animations><Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"><KeyFrame Cue="0%"><Setter Property="ScaleTransform.ScaleY" Value="1"/><Setter Property="BlurEffect.Radius" Value="0"/></KeyFrame><KeyFrame Cue="100%"><Setter Property="ScaleTransform.ScaleY" Value="0"/><Setter Property="BlurEffect.Radius" Value="30"/></KeyFrame></Animation></Style.Animations></Style></Border.Styles></Border><!-- 按钮 --><ToggleButton x:Name="PART_FlipButton"HorizontalAlignment="Right"VerticalAlignment="Bottom"Margin="5"Padding="10,0"FontSize="14"Content="˄"><ToggleButton.Styles><Style Selector="local|FlipPanel2:flipped /template/ ToggleButton#PART_FlipButton"><Setter Property="Content" Value="˅"/><Setter Property="VerticalAlignment" Value="Top"/><Style.Animations><Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"><KeyFrame Cue="0%"><Setter Property="TranslateTransform.Y" Value="150"/></KeyFrame><KeyFrame Cue="100%"><Setter Property="TranslateTransform.Y" Value="0"/></KeyFrame></Animation></Style.Animations></Style><Style Selector="local|FlipPanel2:not(:flipped) ToggleButton#PART_FlipButton"><Setter Property="Content" Value="˄"/><Setter Property="VerticalAlignment" Value="Bottom"/><Style.Animations><Animation Duration="0:0:0.4" Easing="SineEaseInOut" FillMode="Forward"><KeyFrame Cue="0%"><Setter Property="TranslateTransform.Y" Value="-150"/></KeyFrame><KeyFrame Cue="100%"><Setter Property="TranslateTransform.Y" Value="0"/></KeyFrame></Animation></Style.Animations></Style></ToggleButton.Styles></ToggleButton></Grid></ControlTemplate></Window.Resources><Grid><local:FlipPanel2 Template="{StaticResource FancyFlipPanel}"Width="300" Height="200"BorderBrush="DarkOrange"BorderThickness="3"CornerRadius="6"Margin="20"><local:FlipPanel2.FrontContent><TextBlock Text="Front Side"FontSize="18"HorizontalAlignment="Center"VerticalAlignment="Center"/></local:FlipPanel2.FrontContent><local:FlipPanel2.BackContent><TextBlock Text="Back Side"FontSize="18"HorizontalAlignment="Center"VerticalAlignment="Center"/></local:FlipPanel2.BackContent></local:FlipPanel2></Grid> </Window>
FlipPanelAlternateTemplate.axaml.cs代码
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Shares.Avalonia;namespace AvaloniaUI;public partial class FlipPanelAlternateTemplate : Window
{public FlipPanelAlternateTemplate(){InitializeComponent();}
}
运行效果
