完成 CollpaseItem 点击激活区域限制

完成 CollpaseItem 点击激活区域限制
This commit is contained in:
polarboy 2024-08-09 13:44:31 +08:00
parent 754126e5f7
commit e7cf52a5f1
4 changed files with 71 additions and 34 deletions

View File

@ -0,0 +1,20 @@
using Avalonia;
using Avalonia.Controls;
namespace AtomUI.MotionScene;
internal class AnimationTargetPanel : Panel
{
public bool InAnimation { get; set; }
private Size _cacheMeasureSize = default;
protected override Size MeasureOverride(Size availableSize)
{
if (InAnimation && _cacheMeasureSize != default) {
return _cacheMeasureSize;
}
_cacheMeasureSize = base.MeasureOverride(availableSize);
return _cacheMeasureSize;
}
}

View File

@ -1,5 +1,4 @@
using AtomUI.Controls.Utils;
using AtomUI.Data;
using AtomUI.Data;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
@ -176,22 +175,12 @@ public class Collapse : SelectingItemsControl
collapseItem.HeaderBorderThickness = new Thickness(0, 0, 0, headerBorderBottom);
var contentBorderBottom = BorderThickness.Bottom;
if (index == ItemCount - 1 && collapseItem.IsSelected) {
if (index == ItemCount - 1 && (collapseItem.IsSelected || (!collapseItem.IsSelected && collapseItem.InAnimating))) {
contentBorderBottom = 0d;
}
collapseItem.ContentBorderThickness = new Thickness(0, 0, 0, contentBorderBottom);
}
protected override void ContainerIndexChangedOverride(Control container, int oldIndex, int newIndex)
{
base.ContainerIndexChangedOverride(container, oldIndex, newIndex);
}
protected override void ClearContainerForItemOverride(Control element)
{
base.ClearContainerForItemOverride(element);
}
protected override void OnGotFocus(GotFocusEventArgs e)
{
base.OnGotFocus(e);
@ -199,7 +188,7 @@ public class Collapse : SelectingItemsControl
if (e.NavigationMethod == NavigationMethod.Directional) {
Control? containerFromEventSource = GetContainerFromEventSource(e.Source);
if (containerFromEventSource is CollapseItem collapseItem) {
if (!collapseItem.IsAnimating) {
if (!collapseItem.InAnimating) {
e.Handled = UpdateSelectionFromEventSource(e.Source);
}
}
@ -213,7 +202,7 @@ public class Collapse : SelectingItemsControl
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && e.Pointer.Type == PointerType.Mouse) {
Control? containerFromEventSource = GetContainerFromEventSource(e.Source);
if (containerFromEventSource is CollapseItem collapseItem) {
if (!collapseItem.IsAnimating) {
if (!collapseItem.InAnimating && collapseItem.IsPointInHeaderBounds(e.GetPosition(collapseItem))) {
e.Handled = UpdateSelectionFromEventSource(e.Source);
}
}
@ -229,7 +218,7 @@ public class Collapse : SelectingItemsControl
.Any(c => container == c || container.IsVisualAncestorOf(c))) {
Control? containerFromEventSource = GetContainerFromEventSource(e.Source);
if (containerFromEventSource is CollapseItem collapseItem) {
if (!collapseItem.IsAnimating) {
if (!collapseItem.InAnimating && collapseItem.IsPointInHeaderBounds(e.GetPosition(collapseItem))) {
e.Handled = UpdateSelectionFromEventSource(e.Source);
}
}

View File

@ -152,8 +152,10 @@ public class CollapseItem : HeaderedContentControl, ISelectable
private bool _animating = false;
private bool _enableAnimation = true;
private AnimationTargetPanel? _animationTarget;
private Border? _headerDecorator;
internal bool IsAnimating => _animating;
internal bool InAnimating => _animating;
protected override AutomationPeer OnCreateAutomationPeer() => new ListItemAutomationPeer(this);
@ -179,6 +181,8 @@ public class CollapseItem : HeaderedContentControl, ISelectable
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
_animationTarget = e.NameScope.Find<AnimationTargetPanel>(CollapseItemTheme.ContentAnimationTargetPart);
_headerDecorator = e.NameScope.Find<Border>(CollapseItemTheme.HeaderDecoratorPart);
TokenResourceBinder.CreateTokenBinding(this, MotionDurationProperty, GlobalResourceKey.MotionDurationSlow);
SetupIconButton();
_enableAnimation = false;
@ -213,24 +217,27 @@ public class CollapseItem : HeaderedContentControl, ISelectable
private void ExpandItemContent()
{
if (Presenter is null || _animating) {
if (_animationTarget is null || _animating) {
return;
}
Presenter.IsVisible = true;
if (!_enableAnimation) {
_animationTarget.IsVisible = true;
return;
}
LayoutHelper.MeasureChild(Presenter, new Size(Bounds.Width, double.PositiveInfinity), new Thickness());
_animationTarget.IsVisible = true;
LayoutHelper.MeasureChild(_animationTarget, new Size(Bounds.Width, double.PositiveInfinity), new Thickness());
_animating = true;
var director = Director.Instance;
var motion = new ExpandMotion();
motion.ConfigureOpacity(MotionDuration);
motion.ConfigureHeight(MotionDuration);
var motionActor = new MotionActor(Presenter, motion);
var motionActor = new MotionActor(_animationTarget, motion);
motionActor.DispatchInSceneLayer = false;
_animationTarget.InAnimation = true;
motionActor.Completed += (sender, args) =>
{
_animationTarget.InAnimation = false;
_animating = false;
};
director?.Schedule(motionActor);
@ -238,26 +245,29 @@ public class CollapseItem : HeaderedContentControl, ISelectable
private void CollapseItemContent()
{
if (Presenter is null || _animating) {
if (_animationTarget is null || _animating) {
return;
}
if (!_enableAnimation) {
Presenter.IsVisible = false;
_animationTarget.IsVisible = false;
return;
}
_animating = true;
LayoutHelper.MeasureChild(Presenter, new Size(Bounds.Width, double.PositiveInfinity), new Thickness());
LayoutHelper.MeasureChild(_animationTarget, new Size(Bounds.Width, double.PositiveInfinity), new Thickness());
var director = Director.Instance;
var motion = new CollapseMotion();
motion.ConfigureOpacity(MotionDuration);
motion.ConfigureHeight(MotionDuration);
var motionActor = new MotionActor(Presenter, motion);
var motionActor = new MotionActor(_animationTarget!, motion);
motionActor.DispatchInSceneLayer = false;
_animationTarget.InAnimation = true;
motionActor.Completed += (sender, args) =>
{
_animating = false;
Presenter.IsVisible = false;
_animationTarget.InAnimation = false;
_animationTarget.IsVisible = false;
};
director?.Schedule(motionActor);
}
@ -272,4 +282,13 @@ public class CollapseItem : HeaderedContentControl, ISelectable
}
UIStructureUtils.SetTemplateParent(ExpandIcon, this);
}
internal bool IsPointInHeaderBounds(Point position)
{
if (_headerDecorator is not null) {
return _headerDecorator.Bounds.Contains(position);
}
return false;
}
}

View File

@ -1,4 +1,5 @@
using AtomUI.Theme;
using AtomUI.MotionScene;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
@ -22,6 +23,7 @@ internal class CollapseItemTheme : BaseControlTheme
public const string HeaderPresenterPart = "PART_HeaderPresenter";
public const string HeaderDecoratorPart = "PART_HeaderDecorator";
public const string ContentPresenterPart = "PART_ContentPresenter";
public const string ContentAnimationTargetPart = "PART_ContentAnimationTarget";
public CollapseItemTheme() : base(typeof(CollapseItem)) {}
@ -36,15 +38,21 @@ internal class CollapseItemTheme : BaseControlTheme
};
BuildHeader(mainLayout, scope);
var animationPanel = new AnimationTargetPanel()
{
Name = ContentAnimationTargetPart
};
var contentPresenter = new ContentPresenter()
{
Name = ContentPresenterPart,
};
animationPanel.Children.Add(contentPresenter);
TokenResourceBinder.CreateGlobalTokenBinding(contentPresenter, ContentPresenter.BorderBrushProperty, GlobalResourceKey.ColorBorder);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty, CollapseItem.ContentProperty);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentTemplateProperty, CollapseItem.ContentTemplateProperty);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.BorderThicknessProperty, CollapseItem.ContentBorderThicknessProperty);
mainLayout.Children.Add(contentPresenter);
mainLayout.Children.Add(animationPanel);
animationPanel.RegisterInNameScope(scope);
contentPresenter.RegisterInNameScope(scope);
return mainLayout;
});
@ -56,6 +64,7 @@ internal class CollapseItemTheme : BaseControlTheme
{
Name = HeaderDecoratorPart
};
headerDecorator.RegisterInNameScope(scope);
DockPanel.SetDock(headerDecorator, Dock.Top);
TokenResourceBinder.CreateGlobalTokenBinding(headerDecorator, Border.BorderBrushProperty, GlobalResourceKey.ColorBorder);