繁体   English   中英

在 .NET MAUI 中,有一种方法可以根据设备是横向还是纵向来选择不同的 XAML 视图

[英]In .NET MAUI is there a way to choose a different XAML view based upon whether the device is in Landscape or Portrait

我正在使用 .NET MAUI,我有一个相当复杂的特定视图,如果设备方向是纵向,我宁愿有不同的布局,如果设备方向是横向。

很久以前,我修改了 Android 编程,对于 Android Studio,有一种方法可以在设备横向时选择 XAML 文件,而在设备纵向时选择不同的 XAML 文件。

这对 MAUI 来说可能吗? 如果不是,这方面的最佳做法是什么?

这是我的布局,在横向模式下,我可以在一行中放置 3 个主要部分,但这在纵向模式下不起作用,而在纵向模式下,我希望中间的主要元素位于下一行。

以下是我在 Photoshop 上创建的肖像与风景模型的示例:

在此处输入图像描述

更新解决方案*************** 我正在尝试 FreakyAli 发布的解决方案并且有一个主要工作的原型,所以任何想要根据屏幕方向使用不同的 XAML 布局的人可以使用这种方法。

我在我的解决方案中创建了一个名为“ContentViews”的新文件夹。 我添加了 3 个新的 ContentViews(带有后面代码的 XAML):

  1. 首页风景
  2. 主页肖像
  3. HomePageOrientationViewLoader

HomePageOrientationViewLoader 稍后将直接加载到 HomePage.xaml 文件中。 这是将在纵向模式下加载 HomePagePortrait ContentView 或在横向模式下加载 HomePageLandscape ContentView 的控件。

namespace ScoreKeepersBoard.ContentViews;

public partial class HomePageOrientationViewLoader : ContentView
{

    public ContentView homePagePortraitContentView;
    public ContentView homePageLandscapeContentView;

    public HomePageOrientationViewLoader()
    {
        InitializeComponent();

        homePagePortraitContentView = new HomePagePortrait();
        homePageLandscapeContentView = new HomePageLandscape();
        this.Content = homePageLandscapeContentView;

        DeviceDisplay.Current.MainDisplayInfoChanged += Current_MainDisplayInfoChanged;
        this.Content = DeviceDisplay.Current.MainDisplayInfo.Orientation == DisplayOrientation.Portrait ? homePagePortraitContentView : homePageLandscapeContentView;

    }

    private void Current_MainDisplayInfoChanged(object sender, DisplayInfoChangedEventArgs e)
    {

        if (e.DisplayInfo.Orientation == DisplayOrientation.Landscape)
        {
           // if (this.Content.GetType() is not typeof(HomePageLandscape))
           // {
                this.Content = homePageLandscapeContentView;
           // }
        }
        else if (e.DisplayInfo.Orientation == DisplayOrientation.Portrait)
        {
            // if (this.Content.GetType() is not typeof(HomePagePortrait))
            // {
            this.Content = homePagePortraitContentView;
            // }
        }
        else
        {
            //Whatever you would like to do if the orientation is unknown.
        }

    }
}

HomePageOrientationViewLoader.xaml 文件:

<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ScoreKeepersBoard.ContentViews.HomePageOrientationViewLoader">
    <VerticalStackLayout>
        <Label 
            Text="Welcome to .NET MAUI!"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentView>

这是 HomePagePortrait.xaml.cs 文件:

namespace ScoreKeepersBoard.ContentViews;

public partial class HomePagePortrait : ContentView
{
    public HomePagePortrait()
    {
        InitializeComponent();
    }
}

这是 HomePagePortrait.xaml 文件:

<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ScoreKeepersBoard.ContentViews.HomePagePortrait">
    <VerticalStackLayout>
        <Label 
            Text="Welcome to .NET MAUI portrait"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentView>

这是 HomePageLandscape.xaml.cs 文件:

namespace ScoreKeepersBoard.ContentViews;

public partial class HomePageLandscape : ContentView
{
    public HomePageLandscape()
    {
        InitializeComponent();
    }
}

这是 HomePageLandscape.xaml 文件:

<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ScoreKeepersBoard.ContentViews.HomePageLandscape">
    <VerticalStackLayout>
        <Label 
            Text="Welcome to .NET MAUI landscape"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentView>

我的项目有一个名为 HomePage 的初始主页内容页面。 我们正在将 HomePageOrientationViewLoader ContentView 作为自定义控件加载到 HomePage Content Page 的 xaml 中。 请注意,我必须定义 ContentView 所在的命名空间,并在 xaml 文件中定义控件时使用它:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:controls="clr-namespace:ScoreKeepersBoard.ContentViews"
             x:Class="ScoreKeepersBoard.Views.HomePage"
             Title="HomePage">
    <VerticalStackLayout>
        <Label 
            Text="Welcome to .NET MAUI Home Page Content Page"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />

       <controls:HomePageOrientationViewLoader></controls:HomePageOrientationViewLoader>
        
    </VerticalStackLayout>
</ContentPage>

这是主页背后的代码

namespace ScoreKeepersBoard.Views;

public partial class HomePage : ContentPage
{
    public HomePage(HomeViewModel homeViewModel)
    {
        
        InitializeComponent();
    }         
}

当项目以纵向模式在我的 iphone 模拟器上运行时:

在此处输入图像描述

您将看到显示的第二个 label 显示“欢迎使用 .NET MAUI 肖像”,这是肖像内容视图的视图,当我切换到风景时:

在此处输入图像描述

您将看到显示的第二个 label 显示“欢迎使用 .NET MAUI 横向”,这是横向内容视图中的视图。

问题

  1. 这适用于我的 iPhone 模拟器,但是当我切换到我的 Android 像素 5 模拟器并切换我的切换手机方向时,它不起作用并且插入换行符,不会触发 HomePageOrientationViewLoader 中定义的代码。 新注意事项:我在 Android 实体手机上试过这个,它正在工作,所以它一定是模拟器。

  2. 我需要将它用于一个非平凡的示例,该示例的视图 model 将保存体育比赛得分、计时等数据。我想我只需要将视图 model 的 singleton 注入每个视图,它们将只是分享,如果方向切换,其他内容视图将加载,视图 model 将绑定到适当的控件?

  3. FreakyAli 最初建议的代码有这个检查:

     if (e.DisplayInfo.Orientation == DisplayOrientation.Landscape) { if (this.Content.GetType() is not typeof(HomePageLandscape)) { this.Content = homePageLandscapeContentView; } }

但是“typeof(HomePageLandscape)”部分给我一个错误,并说需要一个常数。

除此之外,不同方向的不同视图正在工作,我非常感谢 FreakyAli,我相信我会弄清楚为什么 Android 模拟器没有触发方向切换代码。 但建议会很棒。

理想情况下,这就是我处理这种情况的方式:

在我的构造函数中,我会得到 DisplayInfoChanged 事件,如果此信息发生变化,它会通知我,我还会根据当前方向分配我当前的 ContentView:

DeviceDisplay.Current.MainDisplayInfoChanged += Current_MainDisplayInfoChanged;
this.Content = DeviceDisplay.Current.MainDisplayInfo.Orientation == DisplayOrientation.Portrait ? potraitView : landscapeView;

这里的 PortraitView 是一个 ContentView,它是当我的设备处于纵向和反之亦然时我将显示的视图。

然后按如下方式处理方向的运行时变化:

private void Current_MainDisplayInfoChanged(object sender, DisplayInfoChangedEventArgs e)
{
        if(e.DisplayInfo.Orientation==DisplayOrientation.Landscape)
        {
            if(this.Content.GetType() is not typeof(LandscapeView))
            {
                this.Content = landscapeView;
            }
        }
        else if (e.DisplayInfo.Orientation == DisplayOrientation.Portrait)
        {
            if (this.Content.GetType() is not typeof(PortraitView))
            {
                this.Content = portraitView;
            }
        }
        else
        {
            //Whatever you would like to do if the orientation is unknown.
        }
}

希望这对你有帮助!

执行此操作的正确方法是通过 ContentViews,其中您有 2 个 ContentView,一个用于纵向,一个用于横向。 您有另一个 ContentView,用于根据方向选择横向或纵向加载。 我创建了一个教程,将所有部分放在一起: https://codeshadowhand.com.net-maui-different-layouts-for-portrait-vs-landscape/ 非常感谢 FreakyAli 为我指明了正确的方向!! !

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM