如何通过XAML/代码实现Avalonia应用90度旋转并解决适配问题?
Avalonia非X11环境下应用90度无拉伸旋转方案
针对你遇到的旋转后拉伸、Flyout未旋转问题,这里提供一个直接有效的实现方案,核心是给整个窗口做视觉旋转,同时适配屏幕尺寸,并统一处理Popup类元素的旋转:
实现步骤
1. 窗口层面设置旋转与尺寸适配
直接在Window上添加RenderTransform实现整体旋转,同时后台代码中交换窗口宽高以匹配旋转后的屏幕比例,避免拉伸:
XAML代码
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="RotateApp.MainWindow" Title="RotatedApp" RenderTransformOrigin="0.5,0.5"> <!-- 窗口中心旋转90度 --> <Window.RenderTransform> <RotateTransform Angle="90"/> </Window.RenderTransform> <!-- 你的主布局内容 --> <Grid> <Button Content="打开Flyout" HorizontalAlignment="Center" VerticalAlignment="Center"> <Button.Flyout> <Flyout> <StackPanel Padding="10"> <TextBlock Text="Flyout内容"/> <Button Content="Flyout按钮" Margin="0,5,0,0"/> </StackPanel> </Flyout> </Button.Flyout> </Button> </Grid> </Window>
C#后台代码
using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Media; using Avalonia.Platform; namespace RotateApp; public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); AdjustWindowForRotation(); // 全局监听Popup打开事件,统一处理Flyout旋转 EventManager.RegisterClassHandler(typeof(Popup), Popup.OpenedEvent, OnPopupOpened); } private void AdjustWindowForRotation() { var primaryScreen = Screens.Primary; var workArea = primaryScreen.WorkingArea; // 旋转后交换窗口宽高,匹配屏幕的高/宽 Width = workArea.Height; Height = workArea.Width; // 让窗口居中显示 Position = new PixelPoint( (workArea.Width - (int)Width) / 2, (workArea.Height - (int)Height) / 2 ); } private void OnPopupOpened(object? sender, RoutedEventArgs e) { if (sender is not Popup popup || popup.Child == null) return; // 给Popup设置和窗口一致的旋转 popup.RenderTransformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative); popup.RenderTransform = new RotateTransform(90); // 修正Popup位置,避免旋转后偏移 if (popup.PlacementTarget is Control target) { var targetScreenPos = target.PointToScreen(new Point(0, 0)); popup.Placement = PlacementMode.Absolute; // 旋转后Popup的宽高会交换,所以这里用Child的高/宽计算偏移 popup.HorizontalOffset = targetScreenPos.X + (target.Bounds.Width / 2) - (popup.Child.Bounds.Height / 2); popup.VerticalOffset = targetScreenPos.Y + (target.Bounds.Height / 2) - (popup.Child.Bounds.Width / 2); } } }
2. 关键细节说明
- 避免拉伸:通过交换窗口的宽高为屏幕的高/宽,确保旋转后的窗口尺寸完全适配屏幕,不会出现拉伸变形。
- Flyout旋转:Flyout本质是通过
Popup实现的,不属于主布局的视觉树,所以需要全局监听Popup.Opened事件,给每个弹出的Popup添加相同的旋转变换,并调整位置修正偏移。 - 非X11兼容性:该方案基于Avalonia内置的
RenderTransform,不依赖X11系统特性,在Windows、macOS等非X11环境下均可正常工作。
内容的提问来源于stack exchange,提问作者dwjbosman
相关产品推荐
相关产品推荐

