You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
6.3 KiB
190 lines
6.3 KiB
using ReactiveUI.Avalonia;
|
|
using Avalonia.Markup.Xaml;
|
|
using AuroraDesk.Presentation.ViewModels.Pages;
|
|
using ReactiveUI;
|
|
using System;
|
|
using System.Reactive.Disposables;
|
|
using System.Reactive.Linq;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Threading;
|
|
using Avalonia.Skia.Lottie;
|
|
using Avalonia.VisualTree;
|
|
using Avalonia.Interactivity;
|
|
|
|
namespace AuroraDesk.Presentation.Views.Pages;
|
|
|
|
public partial class BreathePageView : ReactiveUserControl<BreathePageViewModel>
|
|
{
|
|
private Lottie? _lottieControl;
|
|
private ContentControl? _lottieContainer;
|
|
private bool _isDisposed;
|
|
private IDisposable? _repeatCountSubscription;
|
|
|
|
public BreathePageView()
|
|
{
|
|
InitializeComponent();
|
|
|
|
this.WhenActivated(disposables =>
|
|
{
|
|
// 重置停用标志
|
|
_isDisposed = false;
|
|
|
|
// 查找容器控件
|
|
_lottieContainer = this.FindControl<ContentControl>("LottieContainer");
|
|
|
|
if (_lottieContainer == null || ViewModel == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 创建新的 Lottie 控件实例
|
|
CreateLottieControl(disposables);
|
|
|
|
// 订阅动画路径变化
|
|
var pathSubscription = ViewModel
|
|
.WhenAnyValue(x => x.AnimationPath)
|
|
.Where(path => !string.IsNullOrEmpty(path))
|
|
.DistinctUntilChanged()
|
|
.ObserveOn(AvaloniaScheduler.Instance)
|
|
.Subscribe(path =>
|
|
{
|
|
if (_isDisposed || _lottieControl == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
Dispatcher.UIThread.Post(() =>
|
|
{
|
|
if (!_isDisposed && _lottieControl != null && !string.IsNullOrEmpty(path))
|
|
{
|
|
try
|
|
{
|
|
_lottieControl.Path = path;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[BreathePageView] Failed to set animation path: {ex.GetType().Name} - {ex.Message}");
|
|
}
|
|
}
|
|
}, DispatcherPriority.Normal);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[BreathePageView] Failed to update animation path: {ex.GetType().Name} - {ex.Message}");
|
|
}
|
|
});
|
|
|
|
disposables.Add(pathSubscription);
|
|
|
|
// 页面停用时的清理
|
|
disposables.Add(Disposable.Create(() =>
|
|
{
|
|
_isDisposed = true;
|
|
_repeatCountSubscription?.Dispose();
|
|
_repeatCountSubscription = null;
|
|
DestroyLottieControl();
|
|
}));
|
|
});
|
|
}
|
|
|
|
private void InitializeComponent()
|
|
{
|
|
AvaloniaXamlLoader.Load(this);
|
|
}
|
|
|
|
private void CreateLottieControl(CompositeDisposable disposables)
|
|
{
|
|
if (_lottieContainer == null || ViewModel == null || _isDisposed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
// 获取 baseUri(用于资源加载)
|
|
// 使用程序集资源的基础 URI
|
|
var baseUri = new Uri("avares://AuroraDesk.Presentation/");
|
|
|
|
// 创建新的 Lottie 控件实例
|
|
_lottieControl = new Lottie(baseUri)
|
|
{
|
|
RepeatCount = ViewModel.RepeatCount,
|
|
Stretch = Avalonia.Media.Stretch.Uniform,
|
|
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
|
|
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
|
|
ClipToBounds = false
|
|
};
|
|
|
|
// 设置初始路径
|
|
if (!string.IsNullOrEmpty(ViewModel.AnimationPath))
|
|
{
|
|
_lottieControl.Path = ViewModel.AnimationPath;
|
|
}
|
|
|
|
// 订阅 RepeatCount 变化
|
|
if (ViewModel != null)
|
|
{
|
|
_repeatCountSubscription = ViewModel.WhenAnyValue(x => x.RepeatCount)
|
|
.Subscribe(count =>
|
|
{
|
|
if (_lottieControl != null && !_isDisposed)
|
|
{
|
|
Dispatcher.UIThread.Post(() =>
|
|
{
|
|
if (_lottieControl != null && !_isDisposed)
|
|
{
|
|
_lottieControl.RepeatCount = count;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
if (_repeatCountSubscription != null)
|
|
{
|
|
disposables.Add(_repeatCountSubscription);
|
|
}
|
|
}
|
|
|
|
// 将控件添加到容器
|
|
_lottieContainer.Content = _lottieControl;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[BreathePageView] Failed to create Lottie control: {ex.GetType().Name} - {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private void DestroyLottieControl()
|
|
{
|
|
try
|
|
{
|
|
if (_lottieContainer != null)
|
|
{
|
|
// 清空容器内容,这会触发 Lottie 控件的卸载和资源清理
|
|
Dispatcher.UIThread.Post(() =>
|
|
{
|
|
try
|
|
{
|
|
if (_lottieContainer != null)
|
|
{
|
|
_lottieContainer.Content = null;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[BreathePageView] Failed to clear container: {ex.GetType().Name} - {ex.Message}");
|
|
}
|
|
}, DispatcherPriority.Normal);
|
|
}
|
|
|
|
_lottieControl = null;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[BreathePageView] Failed to destroy Lottie control: {ex.GetType().Name} - {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
|