using Avalonia; using Avalonia.Controls; using Avalonia.Media; using YZWater.Core.Utils; namespace YZWater.Avalonia.Controls; /// /// 自适应容器控件 - 根据窗口大小自动缩放内容 /// public class AdaptiveContainer : Decorator { public static readonly StyledProperty DesignWidthProperty = AvaloniaProperty.Register(nameof(DesignWidth), ResolutionManager.DesignWidth); public static readonly StyledProperty DesignHeightProperty = AvaloniaProperty.Register(nameof(DesignHeight), ResolutionManager.DesignHeight); public static readonly StyledProperty MaintainAspectRatioProperty = AvaloniaProperty.Register(nameof(MaintainAspectRatio), true); public static readonly StyledProperty StretchProperty = AvaloniaProperty.Register(nameof(Stretch), Stretch.Uniform); public static readonly StyledProperty MinScaleProperty = AvaloniaProperty.Register(nameof(MinScale), 0.5); public static readonly StyledProperty MaxScaleProperty = AvaloniaProperty.Register(nameof(MaxScale), 2.0); public double DesignWidth { get => GetValue(DesignWidthProperty); set => SetValue(DesignWidthProperty, value); } public double DesignHeight { get => GetValue(DesignHeightProperty); set => SetValue(DesignHeightProperty, value); } public bool MaintainAspectRatio { get => GetValue(MaintainAspectRatioProperty); set => SetValue(MaintainAspectRatioProperty, value); } public Stretch Stretch { get => GetValue(StretchProperty); set => SetValue(StretchProperty, value); } public double MinScale { get => GetValue(MinScaleProperty); set => SetValue(MinScaleProperty, value); } public double MaxScale { get => GetValue(MaxScaleProperty); set => SetValue(MaxScaleProperty, value); } static AdaptiveContainer() { AffectsMeasure(DesignWidthProperty, DesignHeightProperty, MaintainAspectRatioProperty, StretchProperty, MinScaleProperty, MaxScaleProperty); AffectsArrange(DesignWidthProperty, DesignHeightProperty, MaintainAspectRatioProperty, StretchProperty, MinScaleProperty, MaxScaleProperty); } protected override Size MeasureOverride(Size availableSize) { var child = Child; if (child == null) { return new Size(0, 0); } // 让子元素按照设计尺寸测量 var designSize = new Size(DesignWidth, DesignHeight); child.Measure(designSize); // 计算可用空间 var availableWidth = availableSize.Width; var availableHeight = availableSize.Height; // 如果可用空间是无限的,使用设计尺寸 if (double.IsInfinity(availableWidth)) { availableWidth = DesignWidth; } if (double.IsInfinity(availableHeight)) { availableHeight = DesignHeight; } // 返回可用空间(实际缩放在 Arrange 阶段处理) return new Size(availableWidth, availableHeight); } protected override Size ArrangeOverride(Size finalSize) { var child = Child; if (child == null) { return finalSize; } // 计算缩放比例 var scaleX = finalSize.Width / DesignWidth; var scaleY = finalSize.Height / DesignHeight; var scale = Stretch switch { Stretch.Fill => new ScaleTransform(scaleX, scaleY), Stretch.Uniform => new ScaleTransform(Math.Min(scaleX, scaleY), Math.Min(scaleX, scaleY)), Stretch.UniformToFill => new ScaleTransform(Math.Max(scaleX, scaleY), Math.Max(scaleX, scaleY)), _ => new ScaleTransform(1, 1) }; // 限制缩放范围 var uniformScale = Math.Max(MinScale, Math.Min(MaxScale, scale.ScaleX)); // 更新分辨率管理器 ResolutionManager.Instance.UpdateResolution(finalSize.Width, finalSize.Height); // 计算实际尺寸 var actualWidth = DesignWidth * uniformScale; var actualHeight = DesignHeight * uniformScale; // 计算居中偏移 var offsetX = (finalSize.Width - actualWidth) / 2; var offsetY = (finalSize.Height - actualHeight) / 2; // 应用变换 child.RenderTransform = new ScaleTransform(uniformScale, uniformScale); child.RenderTransformOrigin = new RelativePoint(0, 0, RelativeUnit.Absolute); // 排列子元素 child.Arrange(new Rect(offsetX, offsetY, DesignWidth, DesignHeight)); return finalSize; } }