feat: improve demo.

This commit is contained in:
rabbitism
2024-02-08 19:19:38 +08:00
parent da511c6078
commit 2a08391dc7
4 changed files with 119 additions and 42 deletions

View File

@@ -1,15 +1,55 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="Ursa.Demo.Pages.SelectionListDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns="https://github.com/avaloniaui"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:u="https://irihi.tech/ursa" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="using:Ursa.Demo.ViewModels" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:DataType="vm:SelectionListDemoViewModel" xmlns:u="https://irihi.tech/ursa"
x:CompileBindings="True" xmlns:vm="using:Ursa.Demo.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
d:DesignHeight="450" d:DesignWidth="800"
x:Class="Ursa.Demo.Pages.SelectionListDemo"> x:CompileBindings="True"
x:DataType="vm:SelectionListDemoViewModel"
mc:Ignorable="d">
<StackPanel HorizontalAlignment="Left"> <StackPanel HorizontalAlignment="Left">
<u:SelectionList ItemsSource="{Binding Items}"></u:SelectionList> <u:SelectionList ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
<u:SelectionList.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</u:SelectionList.ItemsPanel>
</u:SelectionList>
<u:SelectionList ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" />
<u:SelectionList ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
<u:SelectionList.Indicator>
<Border Background="Transparent" CornerRadius="4">
<Border
Width="4"
Margin="0,8"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
Background="{DynamicResource SemiBlue6}"
CornerRadius="4" />
</Border>
</u:SelectionList.Indicator>
<u:SelectionList.ItemTemplate>
<DataTemplate>
<Panel Height="40">
<TextBlock
Classes.Active="{Binding $parent[u:SelectionListItem].IsSelected, Mode=OneWay}"
Margin="8,0"
VerticalAlignment="Center"
Text="{Binding}">
<TextBlock.Styles>
<Style Selector="TextBlock.Active">
<Setter Property="Foreground" Value="{DynamicResource SemiOrange6}" />
</Style>
</TextBlock.Styles>
</TextBlock>
</Panel>
</DataTemplate>
</u:SelectionList.ItemTemplate>
</u:SelectionList>
<Button Command="{Binding Clear}">Clear</Button>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View File

@@ -3,9 +3,10 @@ using CommunityToolkit.Mvvm.ComponentModel;
namespace Ursa.Demo.ViewModels; namespace Ursa.Demo.ViewModels;
public class SelectionListDemoViewModel: ObservableObject public partial class SelectionListDemoViewModel: ObservableObject
{ {
public ObservableCollection<string> Items { get; set; } public ObservableCollection<string> Items { get; set; }
[ObservableProperty] private string? _selectedItem;
public SelectionListDemoViewModel() public SelectionListDemoViewModel()
{ {
@@ -14,4 +15,9 @@ public class SelectionListDemoViewModel: ObservableObject
"Ding", "Otter", "Husky", "Mr. 17", "Cass" "Ding", "Otter", "Husky", "Mr. 17", "Cass"
}; };
} }
public void Clear()
{
SelectedItem = null;
}
} }

View File

@@ -3,9 +3,19 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:u="https://irihi.tech/ursa"> xmlns:u="https://irihi.tech/ursa">
<ControlTheme x:Key="{x:Type u:SelectionList}" TargetType="u:SelectionList"> <ControlTheme x:Key="{x:Type u:SelectionList}" TargetType="u:SelectionList">
<Setter Property="Background" Value="LightBlue"></Setter> <Setter Property="Background" Value="Transparent" />
<Setter Property="Indicator">
<Template>
<Border
Margin="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{DynamicResource SemiBlue1}"
Theme="{DynamicResource CardBorder}" />
</Template>
</Setter>
<Setter Property="ListBox.Template"> <Setter Property="ListBox.Template">
<ControlTemplate TargetType="ListBox"> <ControlTemplate TargetType="u:SelectionList">
<Border <Border
Name="border" Name="border"
Background="{TemplateBinding Background}" Background="{TemplateBinding Background}"
@@ -14,13 +24,7 @@
ClipToBounds="{TemplateBinding ClipToBounds}" ClipToBounds="{TemplateBinding ClipToBounds}"
CornerRadius="{TemplateBinding CornerRadius}"> CornerRadius="{TemplateBinding CornerRadius}">
<Panel> <Panel>
<Border <ContentPresenter Name="{x:Static u:SelectionList.PART_Indicator}" Content="{TemplateBinding Indicator}" />
Classes="Shadow"
Margin="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Name="{x:Static u:SelectionList.PART_Indicator}"
Theme="{DynamicResource CardBorder}" />
<ItemsPresenter <ItemsPresenter
Name="PART_ItemsPresenter" Name="PART_ItemsPresenter"
Margin="{TemplateBinding Padding}" Margin="{TemplateBinding Padding}"
@@ -33,20 +37,25 @@
<ControlTheme x:Key="{x:Type u:SelectionListItem}" TargetType="u:SelectionListItem"> <ControlTheme x:Key="{x:Type u:SelectionListItem}" TargetType="u:SelectionListItem">
<Setter Property="Background" Value="Transparent" /> <Setter Property="Background" Value="Transparent" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="8" /> <Setter Property="Padding" Value="8" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate TargetType="u:SelectionListItem"> <ControlTemplate TargetType="u:SelectionListItem">
<ContentPresenter <ContentPresenter
Name="PART_ContentPresenter" Name="PART_ContentPresenter"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Padding="{TemplateBinding Padding}" Padding="{TemplateBinding Padding}"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}" Background="{TemplateBinding Background}"
Content="{TemplateBinding Content}" Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" /> FontWeight="{TemplateBinding FontWeight}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Foreground="{TemplateBinding Foreground}" />
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>
<Style Selector="^:selected"> <Style Selector="^:selected">
<Setter Property="Foreground" Value="Blue"></Setter> <Setter Property="FontWeight" Value="Bold" />
</Style> </Style>
</ControlTheme> </ControlTheme>
</ResourceDictionary> </ResourceDictionary>

View File

@@ -1,6 +1,8 @@
using System.Runtime.CompilerServices;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Metadata; using Avalonia.Controls.Metadata;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Controls.Selection; using Avalonia.Controls.Selection;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
@@ -11,14 +13,23 @@ using Irihi.Avalonia.Shared.Helpers;
namespace Ursa.Controls; namespace Ursa.Controls;
[TemplatePart(PART_Indicator, typeof(Control))] [TemplatePart(PART_Indicator, typeof(ContentPresenter))]
public class SelectionList: SelectingItemsControl public class SelectionList: SelectingItemsControl
{ {
public const string PART_Indicator = "PART_Indicator"; public const string PART_Indicator = "PART_Indicator";
private static readonly FuncTemplate<Panel?> DefaultPanel = new(() => new StackPanel()); private static readonly FuncTemplate<Panel?> DefaultPanel = new(() => new StackPanel());
private Control? _indicator;
private ImplicitAnimationCollection? _implicitAnimations; private ImplicitAnimationCollection? _implicitAnimations;
private ContentPresenter? _indicator;
public static readonly StyledProperty<Control?> IndicatorProperty = AvaloniaProperty.Register<SelectionList, Control?>(
nameof(Indicator));
public Control? Indicator
{
get => GetValue(IndicatorProperty);
set => SetValue(IndicatorProperty, value);
}
static SelectionList() static SelectionList()
{ {
@@ -75,25 +86,23 @@ public class SelectionList: SelectingItemsControl
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
base.OnApplyTemplate(e); base.OnApplyTemplate(e);
_indicator = e.NameScope.Find<Control>(PART_Indicator); _indicator= e.NameScope.Find<ContentPresenter>(PART_Indicator);
_indicator?.Arrange(new Rect()); EnsureIndicatorAnimation();
}
private void EnsureIndicatorAnimation()
{
if (_indicator is not null) if (_indicator is not null)
{ {
_indicator.Opacity = 0; _indicator.Opacity = 0;
SetUpAnimation(); SetUpAnimation();
if (ElementComposition.GetElementVisual(_indicator) is { } v) if (ElementComposition.GetElementVisual(_indicator) is { } v)
{ {
v.ImplicitAnimations = _implicitAnimations; v.ImplicitAnimations = _implicitAnimations;
} }
_indicator.SizeChanged += OnIndicatorSizeChanged;
} }
} }
private void OnIndicatorSizeChanged(object sender, SizeChangedEventArgs e)
{
}
internal void SelectByIndex(int index) internal void SelectByIndex(int index)
{ {
using var operation = Selection.BatchUpdate(); using var operation = Selection.BatchUpdate();
@@ -103,13 +112,16 @@ public class SelectionList: SelectingItemsControl
private void SetUpAnimation() private void SetUpAnimation()
{ {
if (_implicitAnimations != null) return;
var compositorVisual = ElementComposition.GetElementVisual(this);
if (compositorVisual is null) return;
var compositor = ElementComposition.GetElementVisual(this)!.Compositor; var compositor = ElementComposition.GetElementVisual(this)!.Compositor;
var offsetAnimation = compositor.CreateVector3KeyFrameAnimation(); var offsetAnimation = compositor.CreateVector3KeyFrameAnimation();
offsetAnimation.Target = "Offset"; offsetAnimation.Target = nameof(CompositionVisual.Offset);
offsetAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue"); offsetAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue");
offsetAnimation.Duration = TimeSpan.FromSeconds(0.3); offsetAnimation.Duration = TimeSpan.FromSeconds(0.3);
var sizeAnimation = compositor.CreateVector2KeyFrameAnimation(); var sizeAnimation = compositor.CreateVector2KeyFrameAnimation();
sizeAnimation.Target = "Size"; sizeAnimation.Target = nameof(CompositionVisual.Size);
sizeAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue"); sizeAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue");
sizeAnimation.Duration = TimeSpan.FromSeconds(0.3); sizeAnimation.Duration = TimeSpan.FromSeconds(0.3);
var opacityAnimation = compositor.CreateScalarKeyFrameAnimation(); var opacityAnimation = compositor.CreateScalarKeyFrameAnimation();
@@ -118,9 +130,19 @@ public class SelectionList: SelectingItemsControl
opacityAnimation.Duration = TimeSpan.FromSeconds(0.3); opacityAnimation.Duration = TimeSpan.FromSeconds(0.3);
_implicitAnimations = compositor.CreateImplicitAnimationCollection(); _implicitAnimations = compositor.CreateImplicitAnimationCollection();
_implicitAnimations["Offset"] = offsetAnimation; _implicitAnimations[nameof(CompositionVisual.Offset)] = offsetAnimation;
_implicitAnimations["Size"] = sizeAnimation; _implicitAnimations[nameof(CompositionVisual.Size)] = sizeAnimation;
_implicitAnimations["Opacity"] = opacityAnimation; _implicitAnimations[nameof(CompositionVisual.Opacity)] = opacityAnimation;
} }
protected override void OnKeyDown(KeyEventArgs e)
{
var hotkeys = Application.Current!.PlatformSettings?.HotkeyConfiguration;
if (e.Key.ToNavigationDirection() is { } direction && direction.IsDirectional())
{
e.Handled |= MoveSelection(direction, WrapSelection);
}
base.OnKeyDown(e);
}
} }