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;
}
}