.NET MAUI:我们还可以拥有特定于平台的XAML吗?

6mzjoqzu  于 2022-12-20  发布在  .NET
关注(0)|答案(1)|浏览(124)

我读到,我们可以在MAUI项目中使用平台特定的C#,但是我需要使用平台特定的XAML文件。在文档中找不到任何东西。

  • 背景:* 在Android上,ListView中的SwipeView在从绑定的ObservableCollection中删除项目时会抛出一个Java错误(“The specified child already have a parent. You must call removeView()on the child's parent first.”),所以我在这里使用了一个CollectionView(没有错误)。在iOS上,当与页面上的其他元素一起使用时,CollectionView确实会延伸到页面下端之外(似乎,在iOS上,CollectionView确实希望占据全屏高度),所以我在这里必须使用ListView。不过在iOS上,上述错误不会发生。
zbsbpyhn

zbsbpyhn1#

您可以为每个平台编写单独的XAML文件来实现这一点。只需编写两个不同版本的XAML,一个用于iOS,一个用于Android。然后,在运行时,根据应用运行的系统示例化正确的版本。

对于整个页面,您可以只为Android和iOS创建一个版本的页面(如果需要,还可以分别为其余平台创建其他版本)。

Android页面

让我们调用Android页面***HelloFromAndroid.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"
             x:Class="MauiSamples.Views.Platform.HelloFromAndroid"
             Title="HelloFromAndroid"
             Shell.PresentationMode="Modal">
    <VerticalStackLayout>
        <Label 
            Text="Hello from Android!"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentPage>

iOS页面

iOS版本将被称为***HelloFromiOS.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"
             x:Class="MauiSamples.Views.Platform.HelloFromiOS"
             Title="HelloFromiOS"
             Shell.PresentationMode="Modal">
    <VerticalStackLayout>
        <Label 
            Text="Hello from iOS!"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentPage>

打开特定于平台的页面

您可以决定在运行时打开哪个版本,也可以使用多目标/条件编译。您可以从代码背后执行此操作,例如***MainPage.xaml.cs***:

运行时决策

private async void OpenHelloView(object sender, EventArgs e)
{
    if (DeviceInfo.Platform == DevicePlatform.Android)
    {
        await Navigation.PushAsync(new HelloFromAndroid());
    }

    if (DeviceInfo.Platform == DevicePlatform.iOS)
    {
        await Navigation.PushAsync(new HelloFromiOS());
    }
}

条件编译

private async void OpenHelloView(object sender, EventArgs e)
{
#if ANDROID
    await Navigation.PushAsync(new HelloFromAndroid());
#elif IOS
    await Navigation.PushAsync(new HelloFromiOS());
#endif
}

此版本是首选方法,因为编译的代码只包含所需的特定于平台的调用。

视图

对于视图,这稍微复杂一些,但也是可能的。
如果需要特定于平台的视图,则不能将其添加到页的XAML中,而需要在运行时从代码隐藏动态示例化它,并将其作为子视图添加到另一个视图或布局中。

Android视图

让我们创建一个名为***ViewAndroid***的视图:

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="MauiSamples.Views.Platform.ViewAndroid">

  <Label
    Text="Hello from Android!"
    VerticalOptions="Center" 
    HorizontalOptions="Center" />

</ContentView>

iOS视图

让我们创建一个名为***ViewiOS***的视图:

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="MauiSamples.Views.Platform.ViewiOS">

  <Label
    Text="Hello from iOS!"
    VerticalOptions="Center" 
    HorizontalOptions="Center" />

</ContentView>

具有平台特定视图的页面

现在,让我们创建一个使用特定于平台的视图的页面。首先,我们创建一些XAML。为了简单起见,我使用了一个空的VerticalStackLayout,我使用x:Name属性给予它命名:

<?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"
             x:Class="MauiSamples.Views.Platform.PageWithPlatformSpecificView"
             Title="PageWithPlatformSpecificView"
             Shell.PresentationMode="Modal">
    <VerticalStackLayout x:Name="VerticalLayout" />
</ContentPage>

现在,我可以从代码隐藏访问VerticalLayout字段并向其添加子元素,这也可以通过运行时决策或条件编译动态完成。

运行时决策
public partial class PageWithPlatformSpecificView : ContentPage
{
    public PageWithPlatformSpecificView()
    {
        InitializeComponent();

        if (DeviceInfo.Platform == DevicePlatform.Android)
        {
            VerticalLayout.Add(new ViewAndroid());
        }
        
        if (DeviceInfo.Platform == DevicePlatform.iOS)
        {
            VerticalLayout.Add(new ViewiOS());
        }
    }
}
条件编译
public partial class PageWithPlatformSpecificView : ContentPage
{
    public PageWithPlatformSpecificView()
    {
        InitializeComponent();

#if ANDROID
        VerticalLayout.Add(new ViewAndroid());
#elif IOS
        VerticalLayout.Add(new ViewiOS());
#endif
    }
}

同样,条件编译是首选方法。

备选办法

从技术上讲,您还可以使用基于文件名的多目标,以便在最终构建中只包含正确版本的XAML。
但是,它需要在 .csproj 文件中进行复杂的设置,才能为XAML文件配置多目标,这是官方不支持的。我在这里为处理特定于平台的资源字典的类似问题写了一个答案:https://stackoverflow.com/a/74338355/4308455

总结

正如您所看到的,使用特定于平台的XAML可以有不同的方法和可能性来实现这一点。它与特定于平台的C#代码并不完全相同,但它在某些情况下可能很有用。我希望这对您和其他具有类似需求的人有所帮助。
如果你感兴趣的话,我自己也尝试过,并将代码添加到了我的MAUI samples repository中。

相关问题