diff --git a/UntamedMusicPlayer/MainWindow.xaml b/UntamedMusicPlayer/MainWindow.xaml
index bfb5a6c..d073893 100644
--- a/UntamedMusicPlayer/MainWindow.xaml
+++ b/UntamedMusicPlayer/MainWindow.xaml
@@ -31,14 +31,14 @@
+ Duration="0:0:0.6">
-
+
+ To="0" Duration="0:0:0.6"/>
private DateTimeOffset _shellFrameMarginAnimationStart;
private double _shellFrameMarginFrom;
private double _shellFrameMarginTo;
+ private double _shellFrameMarginAnimationDuration;
// 热键 ID
private const int HOTKEY_ID_VOLUME_UP = 1;
@@ -96,9 +97,10 @@ public sealed partial class MainWindow : WindowEx, IRecipient
private void OnRootPlayBarChanged(object? sender, PropertyChangedEventArgs e)
{
if (
- e.PropertyName
- is nameof(RootPlayBarViewModel.IsDetail)
- or nameof(RootPlayBarViewModel.IsFullScreen)
+ Settings.IsAutoHidePlaybackControlBar
+ && e.PropertyName
+ is nameof(RootPlayBarViewModel.IsDetail)
+ or nameof(RootPlayBarViewModel.IsFullScreen)
)
{
if (Data.RootPlayBarViewModel!.IsDetail && Data.RootPlayBarViewModel.IsFullScreen)
@@ -110,7 +112,7 @@ public sealed partial class MainWindow : WindowEx, IRecipient
RootGrid.PointerMoved -= RootGrid_PointerMoved;
if (_isPlayBarHidden)
{
- AnimateShellFrameBottomMargin(117);
+ AnimateShellFrameBottomMargin(117, 300);
ShowPlayBarStoryboard.Begin();
_isPlayBarHidden = false;
StopPlayBarTimer();
@@ -129,7 +131,7 @@ public sealed partial class MainWindow : WindowEx, IRecipient
{
if (_isPlayBarHidden)
{
- AnimateShellFrameBottomMargin(117);
+ AnimateShellFrameBottomMargin(117, 300);
ShowPlayBarStoryboard.Begin();
_isPlayBarHidden = false;
}
@@ -154,7 +156,7 @@ public sealed partial class MainWindow : WindowEx, IRecipient
&& !_isPlayBarHidden
)
{
- AnimateShellFrameBottomMargin(0);
+ AnimateShellFrameBottomMargin(0, 600);
HidePlayBarStoryboard.Begin();
_isPlayBarHidden = true;
}
@@ -186,7 +188,7 @@ public sealed partial class MainWindow : WindowEx, IRecipient
}
}
- private void AnimateShellFrameBottomMargin(double targetBottom)
+ private void AnimateShellFrameBottomMargin(double targetBottom, double durationMs)
{
var currentBottom = ShellFrame.Margin.Bottom;
if (Math.Abs(currentBottom - targetBottom) < 0.1)
@@ -203,6 +205,7 @@ public sealed partial class MainWindow : WindowEx, IRecipient
_shellFrameMarginFrom = currentBottom;
_shellFrameMarginTo = targetBottom;
+ _shellFrameMarginAnimationDuration = durationMs;
_shellFrameMarginAnimationStart = DateTimeOffset.Now;
_shellFrameMarginAnimationTimer.Start();
@@ -213,10 +216,15 @@ public sealed partial class MainWindow : WindowEx, IRecipient
object args
)
{
- const double durationMs = 300;
var elapsedMs = (DateTimeOffset.Now - _shellFrameMarginAnimationStart).TotalMilliseconds;
- var progress = Math.Clamp(elapsedMs / durationMs, 0d, 1d);
- var easedProgress = 1 - Math.Pow(1 - progress, 3);
+ var progress = Math.Clamp(elapsedMs / _shellFrameMarginAnimationDuration, 0d, 1d);
+
+ // 显示 (To > From): EaseOut (1 - (1-x)^3)
+ // 隐藏 (To < From): EaseIn (x^3)
+ var easedProgress =
+ _shellFrameMarginTo > _shellFrameMarginFrom
+ ? 1 - Math.Pow(1 - progress, 3)
+ : Math.Pow(progress, 3);
var currentBottom =
_shellFrameMarginFrom + ((_shellFrameMarginTo - _shellFrameMarginFrom) * easedProgress);
diff --git a/UntamedMusicPlayer/Models/Settings.cs b/UntamedMusicPlayer/Models/Settings.cs
index a187206..aa29cff 100644
--- a/UntamedMusicPlayer/Models/Settings.cs
+++ b/UntamedMusicPlayer/Models/Settings.cs
@@ -204,7 +204,22 @@ public static class Settings
}
}
}
- #endregion
+
+ ///
+ /// 是否在全屏模式下自动隐藏播放控制栏
+ ///
+ public static bool IsAutoHidePlaybackControlBar
+ {
+ get;
+ set
+ {
+ if (field != value)
+ {
+ field = value;
+ _localSettingsService.SaveSettingAsync(nameof(IsAutoHidePlaybackControlBar), value);
+ }
+ }
+ }
///
/// 是否启用均衡器
@@ -237,6 +252,7 @@ public static class Settings
}
}
}
+ #endregion
public static async Task InitializeAsync()
{
@@ -266,6 +282,9 @@ public static class Settings
IsWindowBackgroundFollowsCover = await _localSettingsService.ReadSettingAsync(
nameof(IsWindowBackgroundFollowsCover)
);
+ IsAutoHidePlaybackControlBar = await _localSettingsService.ReadSettingAsync(
+ nameof(IsAutoHidePlaybackControlBar)
+ );
if (NotFirstUsed)
{
@@ -292,6 +311,7 @@ public static class Settings
var lightColor = Color.FromArgb(255, 252, 252, 252);
TintColor =
App.Current.RequestedTheme == ApplicationTheme.Dark ? darkColor : lightColor;
+ IsAutoHidePlaybackControlBar = true;
}
InitializedLaterAsync();
}
diff --git a/UntamedMusicPlayer/Strings/en-us/Resources.resw b/UntamedMusicPlayer/Strings/en-us/Resources.resw
index 97acdf6..0860811 100644
--- a/UntamedMusicPlayer/Strings/en-us/Resources.resw
+++ b/UntamedMusicPlayer/Strings/en-us/Resources.resw
@@ -213,6 +213,9 @@
Refresh libraries
+
+ Automatically hide the playback control bar in full screen mode
+
Exclusive mode (Experimental)
diff --git a/UntamedMusicPlayer/Strings/zh-cn/Resources.resw b/UntamedMusicPlayer/Strings/zh-cn/Resources.resw
index 7c3b964..fd73602 100644
--- a/UntamedMusicPlayer/Strings/zh-cn/Resources.resw
+++ b/UntamedMusicPlayer/Strings/zh-cn/Resources.resw
@@ -213,6 +213,9 @@
刷新库
+
+ 在全屏模式下自动隐藏播控栏
+
独占模式 (实验性)
diff --git a/UntamedMusicPlayer/Styles/ColorStyle.xaml b/UntamedMusicPlayer/Styles/ColorStyle.xaml
index 6df0a2b..a714edd 100644
--- a/UntamedMusicPlayer/Styles/ColorStyle.xaml
+++ b/UntamedMusicPlayer/Styles/ColorStyle.xaml
@@ -1,14 +1,12 @@
-
-
diff --git a/UntamedMusicPlayer/ViewModels/SettingsViewModel.cs b/UntamedMusicPlayer/ViewModels/SettingsViewModel.cs
index 75a37ce..53d804e 100644
--- a/UntamedMusicPlayer/ViewModels/SettingsViewModel.cs
+++ b/UntamedMusicPlayer/ViewModels/SettingsViewModel.cs
@@ -194,6 +194,18 @@ public sealed partial class SettingsViewModel
_dynamicBackgroundService.IsEnabled = value;
}
+ ///
+ /// 是否在全屏模式下自动隐藏播放控制栏
+ ///
+ [ObservableProperty]
+ public partial bool IsAutoHidePlaybackControlBar { get; set; } =
+ Settings.IsAutoHidePlaybackControlBar;
+
+ partial void OnIsAutoHidePlaybackControlBarChanged(bool value)
+ {
+ Settings.IsAutoHidePlaybackControlBar = value;
+ }
+
///
/// 版本信息
///
diff --git a/UntamedMusicPlayer/Views/LocalAlbumDetailPage.xaml.cs b/UntamedMusicPlayer/Views/LocalAlbumDetailPage.xaml.cs
index be4b4d3..1a8e16d 100644
--- a/UntamedMusicPlayer/Views/LocalAlbumDetailPage.xaml.cs
+++ b/UntamedMusicPlayer/Views/LocalAlbumDetailPage.xaml.cs
@@ -158,7 +158,7 @@ public sealed partial class LocalAlbumDetailPage : Page
backgroundScaleFactorNode,
progressNode
);
- ExpressionNode backgroundOpacityAnimation = progressNode;
+ ExpressionNode backgroundOpacityAnimation = progressNode * 0.7f;
backgroundVisual.StartAnimation("Scale.Y", backgroundScaleAnimation);
backgroundVisual.StartAnimation("Opacity", backgroundOpacityAnimation);
diff --git a/UntamedMusicPlayer/Views/LocalArtistDetailPage.xaml.cs b/UntamedMusicPlayer/Views/LocalArtistDetailPage.xaml.cs
index 0383fb6..b190bdf 100644
--- a/UntamedMusicPlayer/Views/LocalArtistDetailPage.xaml.cs
+++ b/UntamedMusicPlayer/Views/LocalArtistDetailPage.xaml.cs
@@ -181,7 +181,7 @@ public sealed partial class LocalArtistDetailPage : Page
backgroundScaleFactorNode,
progressNode
);
- ExpressionNode backgroundOpacityAnimation = progressNode;
+ ExpressionNode backgroundOpacityAnimation = progressNode * 0.7f;
backgroundVisual.StartAnimation("Scale.Y", backgroundScaleAnimation);
backgroundVisual.StartAnimation("Opacity", backgroundOpacityAnimation);
diff --git a/UntamedMusicPlayer/Views/LyricPage.xaml b/UntamedMusicPlayer/Views/LyricPage.xaml
index 0d02883..87b3617 100644
--- a/UntamedMusicPlayer/Views/LyricPage.xaml
+++ b/UntamedMusicPlayer/Views/LyricPage.xaml
@@ -69,14 +69,14 @@
+ Duration="0:0:0.6">
+ To="0" Duration="0:0:0.6"/>
diff --git a/UntamedMusicPlayer/Views/LyricPage.xaml.cs b/UntamedMusicPlayer/Views/LyricPage.xaml.cs
index bccc739..bc8ac07 100644
--- a/UntamedMusicPlayer/Views/LyricPage.xaml.cs
+++ b/UntamedMusicPlayer/Views/LyricPage.xaml.cs
@@ -32,6 +32,8 @@ public sealed partial class LyricPage : Page, IDisposable
private DateTimeOffset _contentGridMarginAnimationStart;
private double _contentGridMarginFrom;
private double _contentGridMarginTo;
+ private double _contentGridMarginAnimationDuration;
+
private CancellationTokenSource? _coverLoadWaitCts;
public LyricPage()
@@ -142,9 +144,10 @@ public sealed partial class LyricPage : Page, IDisposable
private void OnRootPlayBarChanged(object? sender, PropertyChangedEventArgs e)
{
if (
- e.PropertyName
- is nameof(RootPlayBarViewModel.IsDetail)
- or nameof(RootPlayBarViewModel.IsFullScreen)
+ Settings.IsAutoHidePlaybackControlBar
+ && e.PropertyName
+ is nameof(RootPlayBarViewModel.IsDetail)
+ or nameof(RootPlayBarViewModel.IsFullScreen)
)
{
if (Data.RootPlayBarViewModel!.IsDetail && Data.RootPlayBarViewModel.IsFullScreen)
@@ -156,7 +159,7 @@ public sealed partial class LyricPage : Page, IDisposable
RootGrid.PointerMoved -= RootGrid_PointerMoved;
if (_isTitleBarHidden)
{
- AnimateContentGridTopMargin(0);
+ AnimateContentGridTopMargin(0, 300);
ShowTitleBarStoryboard.Begin();
_isTitleBarHidden = false;
StopTitleBarTimer();
@@ -174,7 +177,7 @@ public sealed partial class LyricPage : Page, IDisposable
{
if (_isTitleBarHidden)
{
- AnimateContentGridTopMargin(0);
+ AnimateContentGridTopMargin(0, 300);
ShowTitleBarStoryboard.Begin();
_isTitleBarHidden = false;
}
@@ -199,7 +202,7 @@ public sealed partial class LyricPage : Page, IDisposable
&& !_isTitleBarHidden
)
{
- AnimateContentGridTopMargin(-33);
+ AnimateContentGridTopMargin(-33, 600);
HideTitleBarStoryboard.Begin();
_isTitleBarHidden = true;
}
@@ -231,7 +234,7 @@ public sealed partial class LyricPage : Page, IDisposable
}
}
- private void AnimateContentGridTopMargin(double targetTop)
+ private void AnimateContentGridTopMargin(double targetTop, double durationMs)
{
var currentTop = ContentGrid.Margin.Top;
if (Math.Abs(currentTop - targetTop) < 0.1)
@@ -248,6 +251,7 @@ public sealed partial class LyricPage : Page, IDisposable
_contentGridMarginFrom = currentTop;
_contentGridMarginTo = targetTop;
+ _contentGridMarginAnimationDuration = durationMs;
_contentGridMarginAnimationStart = DateTimeOffset.Now;
_contentGridMarginAnimationTimer.Start();
@@ -255,10 +259,15 @@ public sealed partial class LyricPage : Page, IDisposable
private void ContentGridMarginAnimationTick(DispatcherQueueTimer sender, object args)
{
- const double durationMs = 300;
var elapsedMs = (DateTimeOffset.Now - _contentGridMarginAnimationStart).TotalMilliseconds;
- var progress = Math.Clamp(elapsedMs / durationMs, 0d, 1d);
- var easedProgress = 1 - Math.Pow(1 - progress, 3);
+ var progress = Math.Clamp(elapsedMs / _contentGridMarginAnimationDuration, 0d, 1d);
+
+ // 显示 (To > From): EaseOut
+ // 隐藏 (To < From): EaseIn
+ var easedProgress =
+ _contentGridMarginTo > _contentGridMarginFrom
+ ? 1 - Math.Pow(1 - progress, 3)
+ : Math.Pow(progress, 3);
var currentTop =
_contentGridMarginFrom
@@ -413,6 +422,7 @@ public sealed partial class LyricPage : Page, IDisposable
visual.Scale = new Vector3(initialScaleX, initialScaleY, 1f);
var compositor = visual.Compositor;
+
var scaleAnimation = compositor.CreateVector3KeyFrameAnimation();
scaleAnimation.InsertKeyFrame(1f, Vector3.One);
scaleAnimation.Duration = TimeSpan.FromMilliseconds(450);
diff --git a/UntamedMusicPlayer/Views/OnlineAlbumDetailPage.xaml.cs b/UntamedMusicPlayer/Views/OnlineAlbumDetailPage.xaml.cs
index 06b07ae..e9cea5e 100644
--- a/UntamedMusicPlayer/Views/OnlineAlbumDetailPage.xaml.cs
+++ b/UntamedMusicPlayer/Views/OnlineAlbumDetailPage.xaml.cs
@@ -157,7 +157,7 @@ public sealed partial class OnlineAlbumDetailPage : Page
backgroundScaleFactorNode,
progressNode
);
- ExpressionNode backgroundOpacityAnimation = progressNode;
+ ExpressionNode backgroundOpacityAnimation = progressNode * 0.7f;
backgroundVisual.StartAnimation("Scale.Y", backgroundScaleAnimation);
backgroundVisual.StartAnimation("Opacity", backgroundOpacityAnimation);
diff --git a/UntamedMusicPlayer/Views/OnlineArtistDetailPage.xaml.cs b/UntamedMusicPlayer/Views/OnlineArtistDetailPage.xaml.cs
index 52aeccd..ae3055d 100644
--- a/UntamedMusicPlayer/Views/OnlineArtistDetailPage.xaml.cs
+++ b/UntamedMusicPlayer/Views/OnlineArtistDetailPage.xaml.cs
@@ -170,7 +170,7 @@ public sealed partial class OnlineArtistDetailPage : Page
backgroundScaleFactorNode,
progressNode
);
- ExpressionNode backgroundOpacityAnimation = progressNode;
+ ExpressionNode backgroundOpacityAnimation = progressNode * 0.7f;
backgroundVisual.StartAnimation("Scale.Y", backgroundScaleAnimation);
backgroundVisual.StartAnimation("Opacity", backgroundOpacityAnimation);
var contentVisual = ElementCompositionPreview.GetElementVisual(ContentContainer);
diff --git a/UntamedMusicPlayer/Views/OnlinePlayListDetailPage.xaml.cs b/UntamedMusicPlayer/Views/OnlinePlayListDetailPage.xaml.cs
index 41c67a4..dee9d8c 100644
--- a/UntamedMusicPlayer/Views/OnlinePlayListDetailPage.xaml.cs
+++ b/UntamedMusicPlayer/Views/OnlinePlayListDetailPage.xaml.cs
@@ -148,7 +148,7 @@ public sealed partial class OnlinePlayListDetailPage : Page
backgroundScaleFactorNode,
progressNode
);
- ExpressionNode backgroundOpacityAnimation = progressNode;
+ ExpressionNode backgroundOpacityAnimation = progressNode * 0.7f;
backgroundVisual.StartAnimation("Scale.Y", backgroundScaleAnimation);
backgroundVisual.StartAnimation("Opacity", backgroundOpacityAnimation);
diff --git a/UntamedMusicPlayer/Views/PlayListDetailPage.xaml.cs b/UntamedMusicPlayer/Views/PlayListDetailPage.xaml.cs
index 35d8b2b..fb31c78 100644
--- a/UntamedMusicPlayer/Views/PlayListDetailPage.xaml.cs
+++ b/UntamedMusicPlayer/Views/PlayListDetailPage.xaml.cs
@@ -148,7 +148,7 @@ public sealed partial class PlayListDetailPage : Page
backgroundScaleFactorNode,
progressNode
);
- ExpressionNode backgroundOpacityAnimation = progressNode;
+ ExpressionNode backgroundOpacityAnimation = progressNode * 0.7f;
backgroundVisual.StartAnimation("Scale.Y", backgroundScaleAnimation);
backgroundVisual.StartAnimation("Opacity", backgroundOpacityAnimation);
diff --git a/UntamedMusicPlayer/Views/SettingsPage.xaml b/UntamedMusicPlayer/Views/SettingsPage.xaml
index 6405dec..fbe1faa 100644
--- a/UntamedMusicPlayer/Views/SettingsPage.xaml
+++ b/UntamedMusicPlayer/Views/SettingsPage.xaml
@@ -285,6 +285,10 @@
+
+
+
+