mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-26 11:10:34 +08:00
Refactor Popup motion
This commit is contained in:
@@ -17,32 +17,11 @@ internal static class MotionInvoker
|
||||
});
|
||||
}
|
||||
|
||||
public static async Task InvokeAsync(MotionActorControl actor,
|
||||
AbstractMotion motion,
|
||||
Action? aboutToStart = null,
|
||||
Action? completedAction = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
await motion.RunAsync(actor, aboutToStart, completedAction, cancellationToken);
|
||||
}
|
||||
|
||||
public static void InvokeInPopupLayer(SceneMotionActorControl actor,
|
||||
AbstractMotion motion,
|
||||
Action? aboutToStart = null,
|
||||
Action? completedAction = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Dispatcher.UIThread.Invoke(async () =>
|
||||
{
|
||||
await InvokeInPopupLayerAsync(actor, motion, aboutToStart, completedAction, cancellationToken);
|
||||
});
|
||||
}
|
||||
|
||||
public static async Task InvokeInPopupLayerAsync(SceneMotionActorControl actor,
|
||||
AbstractMotion motion,
|
||||
Action? aboutToStart = null,
|
||||
Action? completedAction = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var sceneLayer = PrepareSceneLayer(motion, actor);
|
||||
var compositeDisposable = new CompositeDisposable();
|
||||
@@ -59,10 +38,9 @@ internal static class MotionInvoker
|
||||
actor.NotifySceneShowed();
|
||||
actor.IsVisible = false;
|
||||
|
||||
await Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
// 主要等待正常窗体显示出来再隐藏对话层,不然感觉会闪屏
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(100), cancellationToken);
|
||||
await motion.RunAsync(actor, aboutToStart, () =>
|
||||
{
|
||||
if (completedAction is not null)
|
||||
|
||||
@@ -346,10 +346,12 @@ public class Flyout : PopupFlyoutBase
|
||||
}
|
||||
|
||||
IsOpen = true;
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
await Popup.OpenAsync();
|
||||
HandlePopupOpened(placementTarget);
|
||||
Popup.MotionAwareOpen(() =>
|
||||
{
|
||||
HandlePopupOpened(placementTarget);
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
@@ -375,11 +377,7 @@ public class Flyout : PopupFlyoutBase
|
||||
}
|
||||
|
||||
IsOpen = false;
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
await Popup.CloseAsync();
|
||||
HandlePopupClosed();
|
||||
});
|
||||
Dispatcher.UIThread.InvokeAsync(() => { Popup.MotionAwareClose(HandlePopupClosed); });
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -226,10 +226,7 @@ public class Popup : AvaloniaPopup,
|
||||
{
|
||||
if (popupHostProvider.PopupHost != pointerEventArgs.Root)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
await CloseAsync();
|
||||
});
|
||||
MotionAwareClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -464,24 +461,20 @@ public class Popup : AvaloniaPopup,
|
||||
};
|
||||
}
|
||||
|
||||
public async Task OpenAsync()
|
||||
public void MotionAwareOpen(Action? opened = null)
|
||||
{
|
||||
// AbstractPopup is currently open
|
||||
if (IsOpen || _openAnimating || _closeAnimating)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsMotionEnabled)
|
||||
{
|
||||
Open();
|
||||
await Task.CompletedTask;
|
||||
opened?.Invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
_openAnimating = true;
|
||||
|
||||
var tsc = new TaskCompletionSource();
|
||||
|
||||
Open();
|
||||
|
||||
var popupRoot = Host as PopupRoot;
|
||||
@@ -492,17 +485,14 @@ public class Popup : AvaloniaPopup,
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
popupRoot.Opacity = 1.0;
|
||||
RunOpenAnimation(popupRoot, tsc);
|
||||
RunOpenAnimation(popupRoot, opened);
|
||||
});
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
RunOpenAnimation(popupRoot, tsc);
|
||||
}
|
||||
await tsc.Task;
|
||||
RunOpenAnimation(popupRoot, opened);
|
||||
}
|
||||
|
||||
private void RunOpenAnimation(PopupRoot popupRoot, TaskCompletionSource tsc)
|
||||
private void RunOpenAnimation(PopupRoot popupRoot, Action? opened = null)
|
||||
{
|
||||
var placementTarget = GetEffectivePlacementTarget();
|
||||
var popupOffset = popupRoot.PlatformImpl!.Position;
|
||||
@@ -536,34 +526,34 @@ public class Popup : AvaloniaPopup,
|
||||
{
|
||||
_shadowLayer?.Open();
|
||||
popupRoot.Show();
|
||||
opened?.Invoke();
|
||||
_isNeedWaitFlipSync = false;
|
||||
_openAnimating = false;
|
||||
_openAnimating = false;
|
||||
if (RequestCloseWhereAnimationCompleted)
|
||||
{
|
||||
RequestCloseWhereAnimationCompleted = false;
|
||||
Dispatcher.UIThread.InvokeAsync(async () => { await CloseAsync(); });
|
||||
Dispatcher.UIThread.InvokeAsync(() => { Close(); });
|
||||
}
|
||||
tsc.SetResult();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async Task CloseAsync()
|
||||
public void MotionAwareClose(Action? closed = null)
|
||||
{
|
||||
if (_closeAnimating)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_openAnimating)
|
||||
{
|
||||
RequestCloseWhereAnimationCompleted = true;
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsOpen)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsMotionEnabled)
|
||||
@@ -571,11 +561,11 @@ public class Popup : AvaloniaPopup,
|
||||
_shadowLayer?.Close();
|
||||
_isNeedDetectFlip = true;
|
||||
Close();
|
||||
await Task.CompletedTask;
|
||||
closed?.Invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
_closeAnimating = true;
|
||||
var tsc = new TaskCompletionSource();
|
||||
|
||||
var motion = new ZoomBigOutMotion(MotionDuration);
|
||||
|
||||
@@ -600,22 +590,20 @@ public class Popup : AvaloniaPopup,
|
||||
motionTarget.DesiredSize);
|
||||
|
||||
motionActor.SceneParent = topLevel;
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
MotionInvoker.InvokeInPopupLayer(motionActor, motion, () =>
|
||||
{
|
||||
_shadowLayer?.Close();
|
||||
popupRoot.Hide();
|
||||
popupRoot.Opacity = 0;
|
||||
}, () =>
|
||||
{
|
||||
_closeAnimating = false;
|
||||
_isNeedDetectFlip = true;
|
||||
Close();
|
||||
tsc.SetResult();
|
||||
closed?.Invoke();
|
||||
});
|
||||
});
|
||||
await tsc.Task;
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
|
||||
@@ -397,11 +397,8 @@ public class ToolTip : ContentControl,
|
||||
{
|
||||
TemplateApplied += DeferSetupArrowDecoratedBox;
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
await _popup.OpenAsync();
|
||||
});
|
||||
|
||||
_popup.MotionAwareOpen();
|
||||
}
|
||||
|
||||
private void DeferSetupArrowDecoratedBox(object? sender, TemplateAppliedEventArgs args)
|
||||
@@ -460,21 +457,20 @@ public class ToolTip : ContentControl,
|
||||
var args = new RoutedEventArgs(ToolTipClosingEvent);
|
||||
adornedControl.RaiseEvent(args);
|
||||
}
|
||||
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
|
||||
if (_popup is not null)
|
||||
{
|
||||
if (_popup is not null)
|
||||
_popup.MotionAwareClose(() =>
|
||||
{
|
||||
await _popup.CloseAsync();
|
||||
_popup.SetPopupParent(null);
|
||||
_popup.PlacementTarget = null;
|
||||
if (_popup is IPopupHostProvider popupHostProvider)
|
||||
{
|
||||
popupHostProvider.PopupHostChanged -= HandlePopupHostChanged;
|
||||
}
|
||||
}
|
||||
_subscriptions?.Dispose();
|
||||
});
|
||||
_subscriptions?.Dispose();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void SetToolTipColor(Control control)
|
||||
|
||||
Reference in New Issue
Block a user