应用可以加载为 显示比例系数、主题、高对比和其他运行时上下文量身定制的图像资源文件(或其他资产文件)。 可以从命令性代码或 XAML 标记中引用这些图像,例如图像的 Source属性。 它们还可以出现在应用包清单源文件(Package.appxmanifest
文件)中,例如,作为 Visual Studio 清单设计器中“视觉资产”选项卡上的应用图标的值,或出现在磁贴和通知上。 通过在图像文件名中使用限定符,并在需要时借助ResourceContext动态加载它们,可以加载最适合用户的运行时设置的显示比例、主题、高对比度、语言和其他上下文的图像文件。
图像资源包含在映像资源文件中。 还可以将图像视为资产,以及包含图像的文件作为资产文件;可以在项目的 \Assets 文件夹中找到这些类型的资源文件。 有关如何在图像资源文件名称中使用限定符的背景信息,请参阅 针对语言、缩放和其他限定符定制资源。
图像的一些常见限定符是 缩放、主题、对比度,以及 目标大小。
评估图像资源的缩放、主题和对比度
限定符的 scale
默认值为 scale-100
。 因此,这两个变体是等效的(它们都提供 100 级图像或比例因子 1)。
\Assets\Images\logo.png
\Assets\Images\logo.scale-100.png
可以在文件夹名称而不是文件名中使用限定符。 如果您的每个限定符都包含多个资产文件,那将是更好的策略。 为了便于说明,这两个变体等效于上述两个变体。
\Assets\Images\logo.png
\Assets\Images\scale-100\logo.png
接下来是一个示例,说明如何为不同的显示比例、主题和高对比度设置提供图像资源(命名 /Assets/Images/logo.png
)的变体。 此示例使用文件夹命名。
\Assets\Images\contrast-standard\theme-dark
\scale-100\logo.png
\scale-200\logo.png
\Assets\Images\contrast-standard\theme-light
\scale-100\logo.png
\scale-200\logo.png
\Assets\Images\contrast-high
\scale-100\logo.png
\scale-200\logo.png
从 XAML 标记和代码引用图像或其他资产
图像资源的名称或标识符是其路径和文件名,去除了所有限定符。 如果您根据上一部分中的任何示例命名文件夹和/或文件,那么您将拥有一个图像资源,其名称(绝对路径)为 /Assets/Images/logo.png
。 下面介绍如何在 XAML 标记中使用该名称。
<Image x:Name="myXAMLImageElement" Source="ms-appx:///Assets/Images/logo.png"/>
请注意,由于您引用的是来自应用程序包中的文件,因此需要使用 ms-appx
URI 方案。 请参阅 URI 方案。 下面是在命令性代码中引用同一映像资源的方式。
this.myXAMLImageElement.Source = new BitmapImage(new Uri("ms-appx:///Assets/Images/logo.png"));
您可以使用 ms-appx
从应用包中加载任意文件。
var uri = new System.Uri("ms-appx:///Assets/anyAsset.ext");
var storagefile = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(uri);
ms-appx-web
方案访问与 ms-appx
相同的文件,但在 Web 环境中。
<WebView x:Name="myXAMLWebViewElement" Source="ms-appx-web:///Pages/default.html"/>
this.myXAMLWebViewElement.Source = new Uri("ms-appx-web:///Pages/default.html");
对于这些示例中所示的任何方案,请使用 Uri 构造函数 重载来推断 UriKind。 指定有效的绝对 URI(包括模式和权限),或者让权限默认为应用程序包,正如上面的例子所示。
请注意在这些示例 URI 中,方案(“ms-appx
”或“ms-appx-web
”)后面跟着“://
”,然后是一个绝对路径。 在绝对路径中,前导“/
”会导致路径从包的根目录解析。
注释
ms-resource
URI 方案(对于字符串资源)和ms-appx(-web)
(对于图像和其他资产)URI 方案执行自动限定符匹配,以查找最适合当前上下文的资源。
ms-appdata
URI 方案(用于加载应用数据)不执行任何此类自动匹配。但你可以响应 ResourceContext.QualifierValues 的内容,在 URI 中使用完整的物理文件名显式加载应用数据中的相应资源。 有关应用数据的信息,请参阅 “存储和检索设置”和其他应用数据。 Web URI 方案(例如,http
https
和ftp
)也不执行自动匹配。 有关在这种情况下要做什么的信息,请参阅 在云中托管和加载图像。
如果图像文件保留在项目结构中的位置,则绝对路径是一个不错的选择。 如果希望能够移动图像文件,并确保它相对于其引用的 XAML 标记文件保持在相同的位置,那就可以考虑使用相对于包含标记文件的路径,而不是绝对路径。 如果这样做,则不需要使用 URI 方案。 在这种情况下,你仍会受益于自动限定符匹配,但这仅仅是因为你在 XAML 标记中使用了相对路径。
<Image Source="Assets/Images/logo.png"/>
另请参阅 磁贴和 toast 对语言、缩放和高对比度的支持。
根据目标尺寸验证图像资源
可以将 scale
和 targetsize
限定符用于同一图像资源的不同变体,但不能在资源的单个变体上同时使用它们。 此外,需要定义至少一个没有限定符的 TargetSize
变体。 该变体必须为其定义一个值 scale
,或者让它默认为 scale-100
。 因此,资源的这两个变体 /Assets/Square44x44Logo.png
有效。
\Assets\Square44x44Logo.scale-200.png
\Assets\Square44x44Logo.targetsize-24.png
这两个变体有效。
\Assets\Square44x44Logo.png // defaults to scale-100
\Assets\Square44x44Logo.targetsize-24.png
但此变体无效。
\Assets\Square44x44Logo.scale-200_targetsize-24.png
请参阅应用程序包清单中的图像文件
如果您根据上一部分中的两个有效示例之一命名文件夹和/或文件,那么您将拥有一个应用程序图标图像资源,其名称(作为相对路径)为Assets\Square44x44Logo.png
。 在应用包清单中,只需按名称引用资源。 无需使用任何 URI 方案。
这就是你需要做的,OS 将执行自动限定符匹配,以查找最适合当前上下文的资源。 有关应用包清单中可本地化或以这种方式限定的所有项的列表,请参阅 可本地化的清单项。
确定图像资源的布局方向
请参阅 镜像映像。
加载与特定语言或其他上下文相关的图像
有关本地化应用的价值主张的详细信息,请参阅 全球化和本地化。
默认 ResourceContext(从 ResourceContext.GetForCurrentView获取)包含每个限定符名称的限定符值,表示默认运行时上下文(换句话说,当前用户和计算机的设置)。 图像文件的匹配是基于它们名称中的限定符,并对照运行时上下文中的限定符值。
但是,有时你可能希望应用程序覆盖系统设置,并在查找要加载的匹配图像时明确指定语言、缩放或其他限定符值。 例如,你可能想要准确控制加载高对比度图像的时间和哪些。
为此,可以构造新的 ResourceContext (而不是使用默认资源),重写其值,然后在图像查找中使用该上下文对象。
var resourceContext = new Windows.ApplicationModel.Resources.Core.ResourceContext(); // not using ResourceContext.GetForCurrentView
resourceContext.QualifierValues["Contrast"] = "high";
var namedResource = Windows.ApplicationModel.Resources.Core.ResourceManager.Current.MainResourceMap[@"Files/Assets/Logo.png"];
var resourceCandidate = namedResource.Resolve(resourceContext);
var imageFileStream = resourceCandidate.GetValueAsStreamAsync().GetResults();
var bitmapImage = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
bitmapImage.SetSourceAsync(imageFileStream);
this.myXAMLImageElement.Source = bitmapImage;
若要在全局级别实现相同的效果, 可以在 默认 ResourceContext 中重写限定符值。 但是,我们建议您调用 ResourceContext.SetGlobalQualifierValue。 您通过调用 SetGlobalQualifierValue 一次性设置这些值,然后在每次使用它进行查找时,这些值都会在默认的 ResourceContext 中生效。 默认情况下, ResourceManager 类使用默认 ResourceContext。
Windows.ApplicationModel.Resources.Core.ResourceContext.SetGlobalQualifierValue("Contrast", "high");
var namedResource = Windows.ApplicationModel.Resources.Core.ResourceManager.Current.MainResourceMap[@"Files/Assets/Logo.png"];
this.myXAMLImageElement.Source = new Windows.UI.Xaml.Media.Imaging.BitmapImage(namedResource.Uri);
更新图像以响应限定符值更改事件
你的正在运行的应用可以响应系统设置中的更改,这些更改会影响默认资源上下文中的限定符值。 任一这些系统设置都会在 ResourceContext.QualifierValues上触发 MapChanged 事件。
为了响应此事件,可以使用默认 ResourceContext(默认情况下 ResourceManager 使用)来重新加载映像。
public MainPage()
{
this.InitializeComponent();
...
// Subscribe to the event that's raised when a qualifier value changes.
var qualifierValues = Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().QualifierValues;
qualifierValues.MapChanged += new Windows.Foundation.Collections.MapChangedEventHandler<string, string>(QualifierValues_MapChanged);
}
private async void QualifierValues_MapChanged(IObservableMap<string, string> sender, IMapChangedEventArgs<string> @event)
{
var dispatcher = this.myImageXAMLElement.Dispatcher;
if (dispatcher.HasThreadAccess)
{
this.RefreshUIImages();
}
else
{
await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => this.RefreshUIImages());
}
}
private void RefreshUIImages()
{
var namedResource = Windows.ApplicationModel.Resources.Core.ResourceManager.Current.MainResourceMap[@"Files/Assets/Logo.png"];
this.myImageXAMLElement.Source = new Windows.UI.Xaml.Media.Imaging.BitmapImage(namedResource.Uri);
}