从 .NET MAUI 单一项目覆盖多个目标平台

.NET Multi-platform App UI (.NET MAUI) 单一项目融合了开发应用时通常会遇到的特定于平台的开发体验,并将其整合成为面向 Android、iOS、macOS 和 Windows 的单一共享项目。

无论面向哪个平台,.NET MAUI 单一项目都可提供简化且一致的跨平台开发体验。 .NET MAUI 单一项目提供以下功能:

  • 一个可面向 Android、iOS、macOS、Tizen 和 Windows 的共享项目。
  • 用于运行 .NET MAUI 应用的简化的调试目标选择。
  • 单一项目中的共享资源文件。
  • 指定应用标题、ID 和版本的单一应用清单。
  • 根据需要访问特定于平台的 API 和工具。
  • 单个跨平台应用入口点。

.NET MAUI 单一项目是利用多目标方法实现的,并且使用了 SDK 样式项目。

资源文件

跨平台应用开发的资源管理长期存在问题,因为每个平台都有自己的资源管理方法。 例如,每个平台都有不同的图像要求,使得通常要为每个图像创建不同分辨率的多个版本。 因此,单个图像通常要在不同的分辨率下多次复制,生成的图像要在每个平台上使用不同的文件名和文件夹约定。

.NET MAUI 单一项目允许资源文件存储在单个位置,同时在每个平台上使用。 这包括字体、图像、应用图标、初始屏幕、原始资产和用于设置 .NET MAUI 应用样式的 CSS 文件。 每个图像资源文件都会被用作源图像,在生成时会基于这些源图像针对每个平台生成具有所需分辨率的图像。

注意

.NET MAUI 单一项目中目前不支持 iOS 资产目录。

资源文件通常应放置在 .NET MAUI 应用项目的 Resources 文件夹中,或者 Resources 文件夹的子文件夹中,并且必须正确设置其生成操作。 下表显示了每种资源文件类型的生成操作:

资源 生成操作
应用图标 MauiIcon
字体 MauiFont
映像 MauiImage
初始屏幕 MauiSplashScreen
原始资产 MauiAsset
CSS 文件 MauiCss

注意

XAML 文件也存储在 .NET MAUI 应用项目中,并会在创建项目和项模板时自动为其分配 MauiXaml 生成操作。 但是,通常只会将 XAML 资源字典放置在应用项目的 Resources 文件夹中。

将资源文件添加到 .NET MAUI 应用项目中时,会在项目文件中创建资源的相应条目,但 CSS 文件除外。 下列屏幕截图展示了一个典型的 Resources 文件夹,其中包含每种资源类型的子文件夹:

Image and font resources screenshot.

如果资源已添加到正确的 Resources 子文件夹,则会正确设置资源文件的生成操作。

可以通过编辑应用的项目文件,为每个资源类型指定 Resources 文件夹的子文件夹:

<ItemGroup>
    <!-- Images -->
    <MauiImage Include="Resources\Images\*" />

    <!-- Fonts -->
    <MauiFont Include="Resources\Fonts\*" />

    <!-- Raw assets -->
    <MauiAsset Include="Resources\Raw\*" />
</ItemGroup>

通配符字符 (*) 指示文件夹中的所有文件都将被视为指定的资源类型。 此外,还可能包括子文件夹中的所有文件:

<ItemGroup>
    <!-- Images -->
    <MauiImage Include="Resources\Images\**\*" />
</ItemGroup>

在此示例中,双通配符字符 ('**') 指定 Images 文件夹可以包含子文件夹。 因此,<MauiImage Include="Resources\Images\**\*" /> 指定将 Resources\Images 文件夹或 Images 文件夹的任何子文件夹中的所有文件用作源图像,并将基于这些源图像针对每个平台生成具有所需分辨率的图像。

特定于平台的资源将替代其共享资源对应项。 例如,如果在 Platforms\Android\Resources\drawable-xhdpi\logo.png 中有特定于 Android 的图像,并且还提供了共享的 Resources\Images\logo.svg 图像,则将使用可扩展矢量图形 (SVG) 文件生成所需的 Android 图像,但已作为平台特定图像存在的 XHDPI 图像除外。

应用图标

将图像拖动到项目的 Resources\AppIcon 文件夹,即可将应用图标添加到应用项目中,其中其生成操作将自动设置为 MauiIcon。 这会在项目文件中创建相应的条目:

<MauiIcon Include="Resources\AppIcon\appicon.svg" />

在生成时,将针对目标平台和设备将应用图标的大小调整为正确大小。 然后,将调整大小后的应用图标添加到应用包。 应用图标的大小将调整为多种分辨率,因为它们有多种用途,包括用于表示设备上和应用商店中的应用。

有关详细信息,请参阅将应用图标添加到 .NET MAUI 应用项目

映像

通过将图像拖到项目的 Resources\Images 文件夹中,可以将其添加到应用项目中,其中其生成操作将自动设置为 MauiImage。 这会在项目文件中创建相应的条目:

<MauiImage Include="Resources\Images\logo.svg" />

在生成时,可以将图像大小调整为目标平台和设备的正确分辨率。 然后将生成的图像添加到应用包。

有关详细信息,请参阅将图像添加到 .NET MAUI 应用项目

字体

将 True Type 格式字体 (TTF) 或 Open Type (OTF) 字体拖动到项目的 Resources\Fonts 文件夹,即可将它们添加到应用项目中,其中其生成操作将自动设置为 MauiFont。 这会在项目文件中为每个字体创建相应的条目:

<MauiFont Include="Resources\Fonts\OpenSans-Regular.ttf" />

在生成时,字体将复制到应用包。

有关详细信息,请参阅字体

初始屏幕

通过将图像拖动到项目的 Resources\Splash 文件夹,可以将初始屏幕添加到应用项目中,其中其生成操作将自动设置为 MauiSplashScreen。 这会在项目文件中创建相应的条目:

<ItemGroup>
  <MauiSplashScreen Include="Resources\Splash\splashscreen.svg" />
</ItemGroup>

在生成时,初始屏幕图像的大小将调整为适合目标平台和设备的正确大小。 然后会将调整大小后的初始屏幕添加到应用包中。

有关详细信息,请参阅将初始屏幕添加到 .NET MAUI 应用项目

原始资产

将原始资产文件(如 HTML、JSON 和视频)拖动到项目的 Resources\Raw 文件夹中,即可将其添加到应用项目中,其中其生成操作将自动设置为 MauiAsset。 这会在项目文件中为每个资产创建相应的条目:

<MauiAsset Include="Resources\Raw\index.html" />

然后,控件可以根据需要使用原始资产:

<WebView Source="index.html" />

在生成时,原始资产将复制到应用包。 有关禁用资产打包的信息,请参阅禁用资产文件打包

CSS 文件

可以使用级联样式表 (CSS) 文件对 .NET MAUI 应用进行部分样式设置。 将 CSS 文件拖动到项目的任意文件夹,并在“属性”窗口将其生成操作设置为“MauiCss”,即可将此类文件添加到应用项目中。

CSS 文件必须由 StyleSheet 类加载,然后才能添加到 ResourceDictionary

<Application ...>
    <Application.Resources>
        <StyleSheet Source="/Resources/styles.css" />
    </Application.Resources>
</Application>

有关详细信息,请参阅使用 CSS 对应用进行样式设置

应用部件清单

每个平台都使用自己的本机应用清单文件来指定应用标题、ID、版本等信息。 .NET MAUI 单一项目支持在项目文件中的单个位置指定此常见应用数据。

要指定项目的共享应用清单数据,请在“解决方案资源管理器”中打开该项目的快捷菜单,然后选择“属性”。 然后,可以在“MAUI 共享”>“常规”中指定应用标题、ID 和版本:

.NET MAUI app manifest screenshot.

在生成时,共享应用清单数据与本机应用清单文件中特定于平台的数据合并,以生成应用包的清单文件。 有关详细信息,请参阅 .NET MAUI - MAUI 共享中的项目配置

特定于平台的代码

.NET MAUI 应用项目包含一个 Platforms 文件夹,其中每个子文件夹表示 .NET MAUI 可以面向的平台。

Platform folders screenshot.

每个平台的文件夹包含特定于平台的资源,以及在每个平台上启动应用的代码:

Platform-specific code screenshot.

在生成时,生成系统仅包含为该特定平台生成时每个文件夹中的代码。 例如,在为 Android 进行生成时,Platforms\Android 文件夹中的文件将内置到应用包中,但其他 Platforms 文件夹中的文件则不会。 此方法使用多目标来从单个项目中面向多个平台。 可以将多目标与分部类和分部方法结合使用,以通过跨平台代码调用本机平台功能。 有关详细信息,请参阅调用平台代码

除了此默认多目标方法之外,.NET MAUI 应用还可以基于自己的文件名和文件夹条件进行多目标化。 这样,便可以构建 .NET MAUI 应用项目,而不必将平台代码放入 Platform 文件夹的子文件夹中。 有关详细信息,请参阅配置多目标

还可以将多目标与条件编译相结合,以便代码面向特定平台:

#if ANDROID
                  handler.NativeView.SetBackgroundColor(Colors.Red.ToNative());
#elif IOS
                  handler.NativeView.BackgroundColor = Colors.Red.ToNative();
                  handler.NativeView.BorderStyle = UIKit.UITextBorderStyle.Line;
#elif WINDOWS
                  handler.NativeView.Background = Colors.Red.ToNative();
#endif

有关条件编译的详细信息,请参阅条件编译

应用入口点

虽然 Platforms 文件夹包含在每个平台上启动应用的特定于平台的代码,但 .NET MAUI 应用包含一个单一跨平台应用入口点。 每个平台入口点都会对应用项目中的静态 MauiProgram 类调用 CreateMauiApp 方法,并返回 MauiApp,即应用的入口点。

MauiProgram 类必须至少提供一个要运行的应用:

namespace MyMauiApp;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>();

        return builder.Build();
    }
}  

App 类派生自 Application 类:

namespace MyMauiApp;

public class App : Application
{
    public App()
    {
        InitializeComponent();

        MainPage = new AppShell();
    }
}

在前面的示例中,已将 MainPage 属性设置为 AppShell 对象。 AppShell 是描述应用视觉层次结构的子类化 Shell 类。 有关详细信息,请参阅创建 .NET MAUI Shell 应用