Merge pull request #60 from Coolkeke/main

新增骨架屏控件
This commit is contained in:
Dong Bin
2024-02-26 01:30:14 +08:00
committed by GitHub
17 changed files with 229 additions and 0 deletions

View File

@@ -27,6 +27,7 @@ public static class MenuKeys
public const string MenuKeyRangeSlider = "RangeSlider";
public const string MenuKeySelectionList = "SelectionList";
public const string MenuKeyTagInput = "TagInput";
public const string MenuKeySkeleton = "Skeleton";
public const string MenuKeyTimeline = "Timeline";
public const string MenuKeyTwoTonePathIcon = "TwoTonePathIcon";
public const string MenuKeyThemeToggler = "ThemeToggler";

View File

@@ -0,0 +1,62 @@
<UserControl
x:Class="Ursa.Demo.Pages.SkeletonDemo"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:u="https://irihi.tech/ursa"
xmlns:vm="clr-namespace:Ursa.Demo.ViewModels"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Design.DataContext>
<vm:SkeletonDemoViewModel />
</Design.DataContext>
<StackPanel>
<ToggleSwitch Name="loading" Content="Loading" />
<ToggleSwitch Name="active" Content="Active" />
<Grid
MinWidth="400"
HorizontalAlignment="Left"
ColumnDefinitions="auto,*">
<u:Skeleton
Width="100"
Height="100"
VerticalAlignment="Center"
CornerRadius="2"
IsActive="{Binding #active.IsChecked}"
Loading="{Binding #loading.IsChecked}">
<Image RenderOptions.BitmapInterpolationMode="HighQuality" Source="../Assets/Ursa.ico" />
</u:Skeleton>
<UniformGrid
Grid.Column="1"
Margin="5,0"
Columns="1"
Rows="3">
<u:Skeleton
Margin="0,0,200,0"
VerticalAlignment="Top"
CornerRadius="2"
IsActive="{Binding #active.IsChecked}"
Loading="{Binding #loading.IsChecked}">
<TextBlock Margin="0,2" Text="是先有鸡还是先有蛋" />
</u:Skeleton>
<u:Skeleton
Margin="0,0,100,0"
VerticalAlignment="Center"
CornerRadius="2"
IsActive="{Binding #active.IsChecked}"
Loading="{Binding #loading.IsChecked}">
<TextBlock Margin="0,2" Text="什么是工匠精神" />
</u:Skeleton>
<u:Skeleton
VerticalAlignment="Bottom"
CornerRadius="2"
IsActive="{Binding #active.IsChecked}"
Loading="{Binding #loading.IsChecked}">
<TextBlock Margin="0,2" Text="看山不是山,看水不是水,看山还是山,看水还是水" />
</u:Skeleton>
</UniformGrid>
</Grid>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,14 @@
using Avalonia.Controls;
using Ursa.Demo.ViewModels;
namespace Ursa.Demo.Pages
{
public partial class SkeletonDemo : UserControl
{
public SkeletonDemo()
{
InitializeComponent();
DataContext = new SkeletonDemoViewModel();
}
}
}

View File

@@ -26,4 +26,10 @@
<ProjectReference Include="..\..\src\Ursa.Themes.Semi\Ursa.Themes.Semi.csproj" />
<ProjectReference Include="..\..\src\Ursa\Ursa.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Pages\SkeletonDemo.axaml.cs">
<DependentUpon>SkeletonDemo.axaml</DependentUpon>
</Compile>
</ItemGroup>
</Project>

View File

@@ -48,8 +48,10 @@ public class MainViewViewModel : ViewModelBase
MenuKeys.MenuKeyPagination => new PaginationDemoViewModel(),
MenuKeys.MenuKeyRangeSlider => new RangeSliderDemoViewModel(),
MenuKeys.MenuKeySelectionList => new SelectionListDemoViewModel(),
MenuKeys.MenuKeySkeleton => new SkeletonDemoViewModel(),
MenuKeys.MenuKeyTagInput => new TagInputDemoViewModel(),
MenuKeys.MenuKeyTimeline => new TimelineDemoViewModel(),
MenuKeys.MenuKeySkeleton => new SkeletonDemoViewModel(),
MenuKeys.MenuKeyTwoTonePathIcon => new TwoTonePathIconDemoViewModel(),
MenuKeys.MenuKeyThemeToggler => new ThemeTogglerDemoViewModel(),
MenuKeys.MenuKeyToolBar => new ToolBarDemoViewModel(),

View File

@@ -35,6 +35,7 @@ public class MenuViewModel: ViewModelBase
new() { MenuHeader = "Pagination", Key = MenuKeys.MenuKeyPagination },
new() { MenuHeader = "RangeSlider", Key = MenuKeys.MenuKeyRangeSlider },
new() { MenuHeader = "Selection List", Key = MenuKeys.MenuKeySelectionList, Status = "New" },
new() { MenuHeader = "Skeleton", Key = MenuKeys.MenuKeySkeleton },
new() { MenuHeader = "TagInput", Key = MenuKeys.MenuKeyTagInput },
new() { MenuHeader = "Theme Toggler", Key = MenuKeys.MenuKeyThemeToggler, Status = "New" },
new() { MenuHeader = "Timeline", Key = MenuKeys.MenuKeyTimeline, Status = "WIP" },

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ursa.Demo.ViewModels
{
public class SkeletonDemoViewModel : ViewModelBase
{
}
}

View File

@@ -0,0 +1,62 @@
<ResourceDictionary
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:u="https://irihi.tech/ursa">
<Design.PreviewWith>
<Border Padding="20">
<!-- Add Controls for Previewer Here -->
</Border>
</Design.PreviewWith>
<ControlTheme x:Key="{x:Type u:Skeleton}" TargetType="u:Skeleton">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<ControlTemplate TargetType="u:Skeleton">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
ClipToBounds="{TemplateBinding ClipToBounds}"
CornerRadius="{TemplateBinding CornerRadius}">
<Panel>
<ContentPresenter
x:Name="PART_ContentPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
<Border
x:Name="PART_Border"
Classes.Active="{Binding Path= IsActive, RelativeSource={RelativeSource TemplatedParent}}"
IsHitTestVisible="{TemplateBinding Loading}"
IsVisible="{TemplateBinding Loading}"
>
<Border.Styles>
<Style Selector="Border">
<Setter Property="Background" Value="{DynamicResource SkeletonDefaultBackground}"></Setter>
</Style>
<Style Selector="Border.Active">
<Style.Animations>
<Animation
FillMode="None"
IterationCount="Infinite"
Easing="CubicEaseInOut"
PlaybackDirection="Alternate"
Duration="0:0:1.4">
<KeyFrame Cue="0%">
<Setter Property="Border.Background" Value="{DynamicResource SkeletonStartAnimationBackground}" />
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="Border.Background" Value="{DynamicResource SkeletonEndAnimationBackground}" />
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
</Border.Styles>
</Border>
</Panel>
</Border>
</ControlTemplate>
</Setter>
</ControlTheme>
<!-- Add Styles Here -->
</ResourceDictionary>

View File

@@ -28,6 +28,7 @@
<ResourceInclude Source="TagInput.axaml" />
<ResourceInclude Source="ThemeSelector.axaml" />
<ResourceInclude Source="Timeline.axaml" />
<ResourceInclude Source="Skeleton.axaml" />
<ResourceInclude Source="TwoTonePathIcon.axaml" />
<ResourceInclude Source="ToolBar.axaml" />
</ResourceDictionary.MergedDictionaries>

View File

@@ -0,0 +1,14 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<LinearGradientBrush x:Key="SkeletonStartAnimationBackground" StartPoint="0%,100%" EndPoint="100%,100%">
<GradientStop Offset="0" Color="#FF1C1F23" />
<GradientStop Offset="0" Color="#FF2E3238" />
<GradientStop Offset="1" Color="#FF1C1F23" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SkeletonEndAnimationBackground" StartPoint="0%,100%" EndPoint="100%,100%">
<GradientStop Offset="0" Color="#FF1C1F23" />
<GradientStop Offset="1" Color="#FF2E3238" />
<GradientStop Offset="1" Color="#FF1C1F23" />
</LinearGradientBrush>
<SolidColorBrush x:Key="SkeletonDefaultBackground" Color="#FF1C1F23"></SolidColorBrush>
<!-- Add Resources Here -->
</ResourceDictionary>

View File

@@ -14,5 +14,6 @@
<MergeResourceInclude Source="Pagination.axaml" />
<MergeResourceInclude Source="TagInput.axaml" />
<MergeResourceInclude Source="Timeline.axaml" />
<MergeResourceInclude Source="Skeleton.axaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

View File

@@ -0,0 +1,14 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<LinearGradientBrush x:Key="SkeletonStartAnimationBackground" StartPoint="0%,100%" EndPoint="100%,100%">
<GradientStop Offset="0" Color="#FFF9F9F9" />
<GradientStop Offset="0" Color="#FFE6E8EA" />
<GradientStop Offset="1" Color="#FFF9F9F9" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SkeletonEndAnimationBackground" StartPoint="0%,100%" EndPoint="100%,100%">
<GradientStop Offset="0" Color="#FFF9F9F9" />
<GradientStop Offset="1" Color="#FFE6E8EA" />
<GradientStop Offset="1" Color="#FFF9F9F9" />
</LinearGradientBrush>
<SolidColorBrush x:Key="SkeletonDefaultBackground" Color="#FFF9F9F9"></SolidColorBrush>
<!-- Add Resources Here -->
</ResourceDictionary>

View File

@@ -14,5 +14,6 @@
<MergeResourceInclude Source="Pagination.axaml" />
<MergeResourceInclude Source="TagInput.axaml" />
<MergeResourceInclude Source="Timeline.axaml" />
<MergeResourceInclude Source="Skeleton.axaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

View File

@@ -0,0 +1,4 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Add Resources Here -->
</ResourceDictionary>

View File

@@ -14,6 +14,7 @@
<MergeResourceInclude Source="NavigationMenu.axaml" />
<MergeResourceInclude Source="Pagination.axaml" />
<MergeResourceInclude Source="TagInput.axaml" />
<MergeResourceInclude Source="Skeleton.axaml" />
<MergeResourceInclude Source="ThemeSelector.axaml" />
<MergeResourceInclude Source="ToolBar.axaml" />
</ResourceDictionary.MergedDictionaries>

View File

@@ -20,4 +20,8 @@
<ProjectReference Include="..\Ursa\Ursa.csproj" />
</ItemGroup>
<ItemGroup>
<UpToDateCheckInput Remove="Controls\Skeleton.axaml" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,29 @@
using Avalonia;
using Avalonia.Controls;
using System;
using System.Collections.Generic;
using System.Text;
namespace Ursa.Controls
{
public class Skeleton : ContentControl
{
public static readonly StyledProperty<bool> IsActiveProperty =
AvaloniaProperty.Register<Skeleton, bool>(nameof(IsActive));
public bool IsActive
{
get { return GetValue(IsActiveProperty); }
set { SetValue(IsActiveProperty, value); }
}
public static readonly StyledProperty<bool> LoadingProperty =
AvaloniaProperty.Register<Skeleton, bool>(nameof(Loading));
public bool Loading
{
get => GetValue(LoadingProperty);
set => SetValue(LoadingProperty, value);
}
}
}