簡體   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