加载为缩放、主题、高对比度等定制的图像和资产
应用可以加载为 显示比例系数、主题、高对比度和其他运行时上下文定制的图像资源文件(或其他资产文件)。 可以从命令性代码或 XAML 标记中引用这些图像,例如图像的 Source 属性。 它们还可以显示在应用包清单源文件(Package.appxmanifest
文件)中 - 例如,作为 Visual Studio 清单设计器的“视觉对象资产”选项卡上应用图标的值 - 或显示在磁贴和 toast 上。 通过在图像的文件名中使用限定符并在 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
访问的文件与 Web 隔离舱中的文件 ms-appx
相同。
<WebView x:Name="myXAMLWebViewElement" Source="ms-appx-web:///Pages/default.html"/>
this.myXAMLWebViewElement.Source = new Uri("ms-appx-web:///Pages/default.html");
对于这些示例中所示的任何方案,请使用推断 UriKind 的 Uri 构造函数重载。 指定有效的绝对 URI(包括方案和颁发机构),或者仅让颁发机构默认为应用包,如上例所示。
请注意这些示例 URI 中的方案(“”ms-appx
或“ms-appx-web
”)后跟“://
”,后跟绝对路径。 在绝对路径中,前导“/
”会导致路径从包的根目录解释。
注意
ms-resource
(适用于字符串资源)和 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 事件。
为了响应此事件,可以使用 ResourceManager 默认使用的 ResourceContext 帮助重新加载映像。
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);
}