| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- using Avalonia;
- using Avalonia.Controls;
- using Avalonia.Media;
- using YZWater.Core.Utils;
- namespace YZWater.Avalonia.Controls;
- /// <summary>
- /// 自适应容器控件 - 根据窗口大小自动缩放内容
- /// </summary>
- public class AdaptiveContainer : Decorator
- {
- public static readonly StyledProperty<double> DesignWidthProperty =
- AvaloniaProperty.Register<AdaptiveContainer, double>(nameof(DesignWidth), ResolutionManager.DesignWidth);
- public static readonly StyledProperty<double> DesignHeightProperty =
- AvaloniaProperty.Register<AdaptiveContainer, double>(nameof(DesignHeight), ResolutionManager.DesignHeight);
- public static readonly StyledProperty<bool> MaintainAspectRatioProperty =
- AvaloniaProperty.Register<AdaptiveContainer, bool>(nameof(MaintainAspectRatio), true);
- public static readonly StyledProperty<Stretch> StretchProperty =
- AvaloniaProperty.Register<AdaptiveContainer, Stretch>(nameof(Stretch), Stretch.Uniform);
- public static readonly StyledProperty<double> MinScaleProperty =
- AvaloniaProperty.Register<AdaptiveContainer, double>(nameof(MinScale), 0.5);
- public static readonly StyledProperty<double> MaxScaleProperty =
- AvaloniaProperty.Register<AdaptiveContainer, double>(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<AdaptiveContainer>(DesignWidthProperty, DesignHeightProperty, MaintainAspectRatioProperty, StretchProperty, MinScaleProperty, MaxScaleProperty);
- AffectsArrange<AdaptiveContainer>(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;
- }
- }
|