Add Loading support for card

This commit is contained in:
qinware
2025-09-05 17:51:36 +08:00
parent f8628a823b
commit cab042e5ef
6 changed files with 99 additions and 56 deletions
+20
View File
@@ -154,6 +154,12 @@ public class Card : HeaderedContentControl,
o => o.EffectiveBorderThickness,
(o, v) => o.EffectiveBorderThickness = v);
internal static readonly DirectProperty<Card, bool> ActionsPanelVisibleProperty =
AvaloniaProperty.RegisterDirect<Card, bool>(
nameof(ActionsPanelVisible),
o => o.ActionsPanelVisible,
(o, v) => o.ActionsPanelVisible = v);
private Thickness _headerBorderThickness;
internal Thickness HeaderBorderThickness
@@ -170,6 +176,13 @@ public class Card : HeaderedContentControl,
set => SetAndRaise(EffectiveBorderThicknessProperty, ref _effectiveBorderThickness, value);
}
private bool _actionsPanelVisible;
internal bool ActionsPanelVisible
{
get => _actionsPanelVisible;
set => SetAndRaise(ActionsPanelVisibleProperty, ref _actionsPanelVisible, value);
}
#endregion
private CardActionPanel? _cardActionPanel;
@@ -318,5 +331,12 @@ public class Card : HeaderedContentControl,
throw new NotSupportedException();
}
}
SetCurrentValue(ActionsPanelVisibleProperty, Actions.Count > 0);
}
protected override Size MeasureOverride(Size availableSize)
{
return base.MeasureOverride(availableSize);
}
}
+63 -45
View File
@@ -2,53 +2,63 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atom="https://atomui.net"
xmlns:converters="using:Avalonia.Controls.Converters"
x:ClassModifier="internal">
<converters:CornerRadiusFilterConverter x:Key="CornerRadiusFilterConverter"
Filter="TopLeft, TopRight" />
<ControlTheme x:Key="{x:Type atom:Card}" TargetType="atom:Card">
<Setter Property="Template">
<ControlTemplate>
<Panel>
<Border Name="ShadowsFrame"
ClipToBounds="False"
CornerRadius="{TemplateBinding CornerRadius}"
BoxShadow="{TemplateBinding BoxShadow}"/>
<Border Name="Frame"
<Border Name="Frame"
BorderThickness="{TemplateBinding EffectiveBorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
CornerRadius="{TemplateBinding CornerRadius}"
Background="{TemplateBinding Background}"
ClipToBounds="True">
<DockPanel LastChildFill="True">
<Border Name="HeaderFrame" DockPanel.Dock="Top"
BorderThickness="{TemplateBinding HeaderBorderThickness}">
<DockPanel LastChildFill="True">
<ContentPresenter Name="HeaderExtra" DockPanel.Dock="Right" VerticalAlignment="Center"
Content="{TemplateBinding Extra}"
ContentTemplate="{TemplateBinding ExtraTemplate}"/>
<ContentPresenter Name="TitlePresenter"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
VerticalAlignment="Center"/>
</DockPanel>
</Border>
<atom:CardActionPanel Name="{x:Static atom:CardThemeConstants.ActionPanelPart}"
DockPanel.Dock="Bottom"
CornerRadius="{TemplateBinding CornerRadius}"
IsMotionEnabled="{TemplateBinding IsMotionEnabled}"/>
ClipToBounds="False"
BoxShadow="{TemplateBinding BoxShadow}">
</Border>
<DockPanel LastChildFill="True">
<Border Name="HeaderFrame" DockPanel.Dock="Top"
BorderThickness="{TemplateBinding HeaderBorderThickness}">
<DockPanel LastChildFill="True">
<ContentPresenter Name="HeaderExtra" DockPanel.Dock="Right" VerticalAlignment="Center"
Content="{TemplateBinding Extra}"
ContentTemplate="{TemplateBinding ExtraTemplate}" />
<ContentPresenter Name="TitlePresenter"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
VerticalAlignment="Center" />
</DockPanel>
</Border>
<atom:CardActionPanel Name="{x:Static atom:CardThemeConstants.ActionPanelPart}"
DockPanel.Dock="Bottom"
CornerRadius="{TemplateBinding CornerRadius}"
IsMotionEnabled="{TemplateBinding IsMotionEnabled}"
IsVisible="{TemplateBinding ActionsPanelVisible}" />
<Border Name="CoverFrame"
CornerRadius="{TemplateBinding CornerRadius, Converter={StaticResource CornerRadiusFilterConverter}}"
ClipToBounds="True"
DockPanel.Dock="Top">
<ContentPresenter Name="CoverContentPresenter"
Content="{TemplateBinding Cover}"
ContentTemplate="{TemplateBinding CoverTemplate}"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
DockPanel.Dock="Top"/>
<ContentPresenter Name="CardContent"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
</DockPanel>
</Border>
HorizontalContentAlignment="Stretch" />
</Border>
<Border Name="CardContent">
<atom:Skeleton IsLoading="{TemplateBinding IsLoading}"
IsActive="True"
ParagraphRows="4"
IsShowTitle="False"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
</Border>
</DockPanel>
</Panel>
</ControlTemplate>
</Setter>
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="ClipToBounds" Value="False" />
@@ -56,27 +66,28 @@
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadiusLG}}" />
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorBorderSecondary}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorBgContainer}}" />
<Style Selector="^:headerless">
<Style Selector="^ /template/ Border#HeaderFrame">
<Setter Property="IsVisible" Value="False" />
</Style>
</Style>
<Setter Property="BoxShadow" Value="0 1 2 -1 #00000000, 0 3 6 0 #00000000, 0 5 12 4 #00000000"/>
<Setter Property="BoxShadow" Value="0 1 2 -1 #00000000, 0 3 6 0 #00000000, 0 5 12 4 #00000000" />
<Style Selector="^[StyleVariant=Borderless]">
<Setter Property="BoxShadow" Value="{DynamicResource {x:Static atom:SharedTokenKey.BoxShadowsTertiary}}" />
</Style>
<Style Selector="^ /template/ Border#HeaderFrame">
<Setter Property="Background" Value="{DynamicResource {x:Static atom:CardTokenKey.HeaderBg}}" />
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorBorderSecondary}}" />
<Setter Property="BorderBrush"
Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorBorderSecondary}}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#TitlePresenter">
<Setter Property="TextElement.FontWeight"
Value="{DynamicResource {x:Static atom:SharedTokenKey.FontWeightStrong}}" />
</Style>
<Style Selector="^[SizeType=Large]">
<Style Selector="^ /template/ Border#HeaderFrame">
<Setter Property="MinHeight" Value="{DynamicResource {x:Static atom:CardTokenKey.HeaderHeightLG}}" />
@@ -84,12 +95,12 @@
<Setter Property="TextElement.FontSize"
Value="{DynamicResource {x:Static atom:CardTokenKey.HeaderFontSizeLG}}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#CardContent">
<Style Selector="^ /template/ Border#CardContent">
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:CardTokenKey.BodyPaddingLG}}" />
</Style>
</Style>
<Style Selector="^[SizeType=Middle]">
<Style Selector="^ /template/ Border#HeaderFrame">
<Setter Property="MinHeight" Value="{DynamicResource {x:Static atom:CardTokenKey.HeaderHeight}}" />
@@ -97,12 +108,12 @@
<Setter Property="TextElement.FontSize"
Value="{DynamicResource {x:Static atom:CardTokenKey.HeaderFontSize}}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#CardContent">
<Style Selector="^ /template/ Border#CardContent">
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:CardTokenKey.BodyPadding}}" />
</Style>
</Style>
<Style Selector="^[SizeType=Small]">
<Style Selector="^ /template/ Border#HeaderFrame">
<Setter Property="MinHeight" Value="{DynamicResource {x:Static atom:CardTokenKey.HeaderHeightSM}}" />
@@ -110,17 +121,24 @@
<Setter Property="TextElement.FontSize"
Value="{DynamicResource {x:Static atom:CardTokenKey.HeaderFontSizeSM}}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#CardContent">
<Style Selector="^ /template/ Border#CardContent">
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:CardTokenKey.BodyPaddingSM}}" />
</Style>
</Style>
<Style Selector="^[IsHoverable=True]">
<Setter Property="Cursor" Value="Hand" />
<Style Selector="^:pointerover">
<Setter Property="BoxShadow" Value="{DynamicResource {x:Static atom:CardTokenKey.CardShadows}}" />
<Setter Property="BorderThickness" Value="0" />
</Style>
</Style>
<Style Selector="^:not(:headerless)">
<Style Selector="^ /template/ Border#CoverFrame">
<Setter Property="CornerRadius" Value="0" />
</Style>
</Style>
</ControlTheme>
</ResourceDictionary>
@@ -4,7 +4,6 @@ using System.Reactive.Disposables;
using AtomUI.Collections.Pooled;
using AtomUI.Controls.Themes;
using AtomUI.Data;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using Avalonia;
@@ -15,7 +14,6 @@ using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Media;
namespace AtomUI.Controls.CalendarView;
+2
View File
@@ -193,6 +193,7 @@ public class Skeleton : AbstractSkeleton, IControlSharedTokenResourcesHost
{
StartActiveAnimation();
}
IsContentVisible = !IsLoading && (Content != null || ContentTemplate != null);
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
@@ -205,4 +206,5 @@ public class Skeleton : AbstractSkeleton, IControlSharedTokenResourcesHost
IsContentVisible = !IsLoading && (Content != null || ContentTemplate != null);
}
}
}
+12 -9
View File
@@ -40,22 +40,25 @@ public class SkeletonLine : AbstractSkeleton
{
actualWidth = LineWidth.Value;
}
else if (!double.IsInfinity(actualWidth))
{
actualWidth = Math.Min(actualWidth, actualWidth * (LineWidth.Value / 100.0));
}
var actualSize = new Size(actualWidth, availableSize.Height);
var size = base.MeasureOverride(actualSize);
return actualSize.WithHeight(size.Height);
return base.MeasureOverride(actualSize);
}
protected override Size ArrangeOverride(Size finalSize)
{
var size = base.ArrangeOverride(finalSize);
var size = base.ArrangeOverride(finalSize);
var actualWidth = finalSize.Width;
if (!LineWidth.IsPixel)
{
if (!double.IsInfinity(actualWidth))
{
actualWidth = Math.Min(actualWidth, actualWidth * (LineWidth.Value / 100.0));
}
}
if (_rootLayout != null)
{
_rootLayout.Arrange(new Rect(0, 0, DesiredSize.Width, DesiredSize.Height));
_rootLayout.Arrange(new Rect(0, 0, actualWidth, DesiredSize.Height));
}
return size;
}
@@ -22,6 +22,8 @@
</Setter>
<Style Selector="^:is(atom|AbstractSkeleton)">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="Background" Value="{DynamicResource {x:Static atom:SkeletonTokenKey.GradientFromColor}}"/>
<Setter Property="MotionDuration" Value="{DynamicResource {x:Static atom:SkeletonTokenKey.LoadingMotionDuration}}"/>
<Setter Property="LoadingBackgroundStart" Value="{DynamicResource {x:Static atom:SkeletonTokenKey.LoadingBackgroundStart}}"/>