mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
fix.元素动画系统导致的调整组件闪现问题
This commit is contained in:
@@ -35,4 +35,37 @@ public sealed class DesktopEditOverlayPresenterTests
|
|||||||
Assert.Equal(180, ghost.Width);
|
Assert.Equal(180, ghost.Width);
|
||||||
Assert.Equal(120, ghost.Height);
|
Assert.Equal(120, ghost.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CandidateRectUsesCanvasPlacement()
|
||||||
|
{
|
||||||
|
var presenter = new DesktopEditOverlayPresenter(new CompositionVisualAnimationService(_ => null));
|
||||||
|
var root = Assert.IsType<Canvas>(presenter.Root);
|
||||||
|
|
||||||
|
presenter.SetCandidateRect(new Rect(44, 58, 240, 160));
|
||||||
|
|
||||||
|
var candidate = root.Children.OfType<Border>().Single(child => child is not DesktopEditGhostView);
|
||||||
|
Assert.Equal(44, Canvas.GetLeft(candidate));
|
||||||
|
Assert.Equal(58, Canvas.GetTop(candidate));
|
||||||
|
Assert.Equal(240, candidate.Width);
|
||||||
|
Assert.Equal(160, candidate.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ShowPreservesPreviewAndCandidateCanvasPlacement()
|
||||||
|
{
|
||||||
|
var presenter = new DesktopEditOverlayPresenter(new CompositionVisualAnimationService(_ => null));
|
||||||
|
var root = Assert.IsType<Canvas>(presenter.Root);
|
||||||
|
|
||||||
|
presenter.SetPreviewRect(new Rect(16, 32, 180, 120));
|
||||||
|
presenter.SetCandidateRect(new Rect(24, 40, 200, 140));
|
||||||
|
presenter.Show();
|
||||||
|
|
||||||
|
var ghost = root.Children.OfType<DesktopEditGhostView>().Single();
|
||||||
|
var candidate = root.Children.OfType<Border>().Single(child => child is not DesktopEditGhostView);
|
||||||
|
Assert.Equal(16, Canvas.GetLeft(ghost));
|
||||||
|
Assert.Equal(32, Canvas.GetTop(ghost));
|
||||||
|
Assert.Equal(24, Canvas.GetLeft(candidate));
|
||||||
|
Assert.Equal(40, Canvas.GetTop(candidate));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Threading;
|
||||||
|
|
||||||
|
namespace LanMountainDesktop.DesktopEditing;
|
||||||
|
|
||||||
|
internal static class DesktopEditAnimationRuntime
|
||||||
|
{
|
||||||
|
public static bool CanUseTransitions()
|
||||||
|
{
|
||||||
|
return Application.Current is not null && Dispatcher.UIThread.CheckAccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,7 +52,7 @@ internal sealed class DesktopEditGhostView : Border
|
|||||||
ClipToBounds = true;
|
ClipToBounds = true;
|
||||||
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
|
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
|
||||||
RenderTransform = _scaleTransform;
|
RenderTransform = _scaleTransform;
|
||||||
if (Dispatcher.UIThread.CheckAccess())
|
if (DesktopEditAnimationRuntime.CanUseTransitions())
|
||||||
{
|
{
|
||||||
Transitions = new Transitions
|
Transitions = new Transitions
|
||||||
{
|
{
|
||||||
@@ -301,6 +301,12 @@ internal sealed class DesktopEditGhostView : Border
|
|||||||
|
|
||||||
internal void SetScaleTransitionDuration(TimeSpan duration)
|
internal void SetScaleTransitionDuration(TimeSpan duration)
|
||||||
{
|
{
|
||||||
|
if (!DesktopEditAnimationRuntime.CanUseTransitions())
|
||||||
|
{
|
||||||
|
_scaleTransform.Transitions = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_scaleTransform.Transitions = new Transitions
|
_scaleTransform.Transitions = new Transitions
|
||||||
{
|
{
|
||||||
CreateScaleTransition(ScaleTransform.ScaleXProperty, duration),
|
CreateScaleTransition(ScaleTransform.ScaleXProperty, duration),
|
||||||
@@ -310,6 +316,12 @@ internal sealed class DesktopEditGhostView : Border
|
|||||||
|
|
||||||
internal void SetOpacityTransitionDuration(TimeSpan duration)
|
internal void SetOpacityTransitionDuration(TimeSpan duration)
|
||||||
{
|
{
|
||||||
|
if (!DesktopEditAnimationRuntime.CanUseTransitions())
|
||||||
|
{
|
||||||
|
Transitions = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Transitions = new Transitions
|
Transitions = new Transitions
|
||||||
{
|
{
|
||||||
CreateOpacityTransition(duration)
|
CreateOpacityTransition(duration)
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ internal sealed class DesktopEditOverlayPresenter
|
|||||||
private Rect? _candidateRect;
|
private Rect? _candidateRect;
|
||||||
private bool _isInvalid;
|
private bool _isInvalid;
|
||||||
private bool _isVisible;
|
private bool _isVisible;
|
||||||
private bool _ghostUsesCompositionOffset;
|
|
||||||
private bool _candidateUsesCompositionOffset;
|
|
||||||
private int _dismissVersion;
|
private int _dismissVersion;
|
||||||
|
|
||||||
private readonly SolidColorBrush _candidateBrush = new(Color.Parse("#FF0A84FF"));
|
private readonly SolidColorBrush _candidateBrush = new(Color.Parse("#FF0A84FF"));
|
||||||
@@ -68,7 +66,7 @@ internal sealed class DesktopEditOverlayPresenter
|
|||||||
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative),
|
RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative),
|
||||||
RenderTransform = _candidateScale
|
RenderTransform = _candidateScale
|
||||||
};
|
};
|
||||||
if (Dispatcher.UIThread.CheckAccess())
|
if (DesktopEditAnimationRuntime.CanUseTransitions())
|
||||||
{
|
{
|
||||||
_candidateOutline.Transitions = new Transitions
|
_candidateOutline.Transitions = new Transitions
|
||||||
{
|
{
|
||||||
@@ -102,7 +100,7 @@ internal sealed class DesktopEditOverlayPresenter
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Dispatcher.UIThread.CheckAccess())
|
if (DesktopEditAnimationRuntime.CanUseTransitions())
|
||||||
{
|
{
|
||||||
_root.Transitions = new Transitions
|
_root.Transitions = new Transitions
|
||||||
{
|
{
|
||||||
@@ -170,21 +168,24 @@ internal sealed class DesktopEditOverlayPresenter
|
|||||||
targetGhostScale = 1.03;
|
targetGhostScale = 1.03;
|
||||||
}
|
}
|
||||||
|
|
||||||
_root.Transitions = new Transitions
|
if (DesktopEditAnimationRuntime.CanUseTransitions())
|
||||||
{
|
{
|
||||||
CreateOpacityTransition(PickupDuration)
|
_root.Transitions = new Transitions
|
||||||
};
|
{
|
||||||
_ghostView.SetOpacityTransitionDuration(PickupDuration);
|
CreateOpacityTransition(PickupDuration)
|
||||||
_ghostView.SetScaleTransitionDuration(PickupDuration);
|
};
|
||||||
_candidateScale.Transitions = new Transitions
|
_ghostView.SetOpacityTransitionDuration(PickupDuration);
|
||||||
{
|
_ghostView.SetScaleTransitionDuration(PickupDuration);
|
||||||
CreateScaleTransition(ScaleTransform.ScaleXProperty, PickupDuration),
|
_candidateScale.Transitions = new Transitions
|
||||||
CreateScaleTransition(ScaleTransform.ScaleYProperty, PickupDuration)
|
{
|
||||||
};
|
CreateScaleTransition(ScaleTransform.ScaleXProperty, PickupDuration),
|
||||||
_candidateOutline.Transitions = new Transitions
|
CreateScaleTransition(ScaleTransform.ScaleYProperty, PickupDuration)
|
||||||
{
|
};
|
||||||
CreateOpacityTransition(PickupDuration)
|
_candidateOutline.Transitions = new Transitions
|
||||||
};
|
{
|
||||||
|
CreateOpacityTransition(PickupDuration)
|
||||||
|
};
|
||||||
|
}
|
||||||
_ghostView.SetRestingScale(initialGhostScale);
|
_ghostView.SetRestingScale(initialGhostScale);
|
||||||
_candidateOutline.Opacity = 0;
|
_candidateOutline.Opacity = 0;
|
||||||
_candidateScale.ScaleX = 0.97;
|
_candidateScale.ScaleX = 0.97;
|
||||||
@@ -243,21 +244,24 @@ internal sealed class DesktopEditOverlayPresenter
|
|||||||
var version = ++_dismissVersion;
|
var version = ++_dismissVersion;
|
||||||
_isVisible = false;
|
_isVisible = false;
|
||||||
var settleDuration = isCancel ? CancelSettleDuration : CommitSettleDuration;
|
var settleDuration = isCancel ? CancelSettleDuration : CommitSettleDuration;
|
||||||
_root.Transitions = new Transitions
|
if (DesktopEditAnimationRuntime.CanUseTransitions())
|
||||||
{
|
{
|
||||||
CreateOpacityTransition(settleDuration)
|
_root.Transitions = new Transitions
|
||||||
};
|
{
|
||||||
_ghostView.SetOpacityTransitionDuration(settleDuration);
|
CreateOpacityTransition(settleDuration)
|
||||||
_ghostView.SetScaleTransitionDuration(settleDuration);
|
};
|
||||||
_candidateScale.Transitions = new Transitions
|
_ghostView.SetOpacityTransitionDuration(settleDuration);
|
||||||
{
|
_ghostView.SetScaleTransitionDuration(settleDuration);
|
||||||
CreateScaleTransition(ScaleTransform.ScaleXProperty, settleDuration),
|
_candidateScale.Transitions = new Transitions
|
||||||
CreateScaleTransition(ScaleTransform.ScaleYProperty, settleDuration)
|
{
|
||||||
};
|
CreateScaleTransition(ScaleTransform.ScaleXProperty, settleDuration),
|
||||||
_candidateOutline.Transitions = new Transitions
|
CreateScaleTransition(ScaleTransform.ScaleYProperty, settleDuration)
|
||||||
{
|
};
|
||||||
CreateOpacityTransition(settleDuration)
|
_candidateOutline.Transitions = new Transitions
|
||||||
};
|
{
|
||||||
|
CreateOpacityTransition(settleDuration)
|
||||||
|
};
|
||||||
|
}
|
||||||
var targetScale = _ghostView.HasPreviewImage
|
var targetScale = _ghostView.HasPreviewImage
|
||||||
? 1.00
|
? 1.00
|
||||||
: isCancel ? 0.96 : 1.04;
|
: isCancel ? 0.96 : 1.04;
|
||||||
@@ -292,7 +296,7 @@ internal sealed class DesktopEditOverlayPresenter
|
|||||||
var rect = _previewRect.Value;
|
var rect = _previewRect.Value;
|
||||||
_ghostView.Width = Math.Max(1, rect.Width);
|
_ghostView.Width = Math.Max(1, rect.Width);
|
||||||
_ghostView.Height = Math.Max(1, rect.Height);
|
_ghostView.Height = Math.Max(1, rect.Height);
|
||||||
SetOverlayOffset(_ghostView, new Point(rect.X, rect.Y), ref _ghostUsesCompositionOffset);
|
SetOverlayOffset(_ghostView, new Point(rect.X, rect.Y));
|
||||||
_ghostView.UpdatePreviewMetrics(rect.Width, rect.Height);
|
_ghostView.UpdatePreviewMetrics(rect.Width, rect.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +313,7 @@ internal sealed class DesktopEditOverlayPresenter
|
|||||||
_candidateOutline.IsVisible = true;
|
_candidateOutline.IsVisible = true;
|
||||||
_candidateOutline.Width = Math.Max(1, rect.Width);
|
_candidateOutline.Width = Math.Max(1, rect.Width);
|
||||||
_candidateOutline.Height = Math.Max(1, rect.Height);
|
_candidateOutline.Height = Math.Max(1, rect.Height);
|
||||||
SetOverlayOffset(_candidateOutline, new Point(rect.X, rect.Y), ref _candidateUsesCompositionOffset);
|
SetOverlayOffset(_candidateOutline, new Point(rect.X, rect.Y));
|
||||||
|
|
||||||
var cornerRadius = Math.Clamp(Math.Min(rect.Width, rect.Height) * 0.11, 14, 26);
|
var cornerRadius = Math.Clamp(Math.Min(rect.Width, rect.Height) * 0.11, 14, 26);
|
||||||
_candidateOutline.CornerRadius = new CornerRadius(cornerRadius);
|
_candidateOutline.CornerRadius = new CornerRadius(cornerRadius);
|
||||||
@@ -339,24 +343,11 @@ internal sealed class DesktopEditOverlayPresenter
|
|||||||
return new Rect(rect.X, rect.Y, width, height);
|
return new Rect(rect.X, rect.Y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetOverlayOffset(Control target, Point position, ref bool usesCompositionOffset)
|
private void SetOverlayOffset(Control target, Point position)
|
||||||
{
|
{
|
||||||
if (_visualAnimationService.TrySetOffset(target, position))
|
|
||||||
{
|
|
||||||
Canvas.SetLeft(target, 0);
|
|
||||||
Canvas.SetTop(target, 0);
|
|
||||||
usesCompositionOffset = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usesCompositionOffset)
|
|
||||||
{
|
|
||||||
_visualAnimationService.TryResetOffset(target);
|
|
||||||
usesCompositionOffset = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Canvas.SetLeft(target, position.X);
|
Canvas.SetLeft(target, position.X);
|
||||||
Canvas.SetTop(target, position.Y);
|
Canvas.SetTop(target, position.Y);
|
||||||
|
_visualAnimationService.TryResetOffset(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DoubleTransition CreateScaleTransition(AvaloniaProperty property, TimeSpan duration) =>
|
private static DoubleTransition CreateScaleTransition(AvaloniaProperty property, TimeSpan duration) =>
|
||||||
|
|||||||
Reference in New Issue
Block a user