嵌入资源
通过Internet访问位图很方便,但有时候并不是最佳选择。该过程需要互联网连接,确保位图未被移动,并有一段时间下载。为了快速且有保证地访问位图,它们可以直接绑定到应用程序中。
如果需要访问非特定于平台的映像,则可以将位图作为嵌入资源包含在共享的可移植类库项目中,并使用ImageSource.From?Resource方法访问它们。 ResourceBitmapCode解决方案演示了如何执行此操作。
此解决方案中的ResourceBitmapCode PCL项目有一个名为Images的文件夹,它包含两个位图,名为ModernUserInterface.jpg(一个非常大的位图)和ModernUserInterface256.jpg(相同的图片,但宽度为256像素)。
将任何类型的嵌入资源添加到PCL项目时,请确保将资源的构建操作设置为EmbeddedResource。这很关键。
在代码中,将Image元素的Source属性设置为从静态ImageSource.FromResource方法返回的ImageSource对象。此方法需要资源ID。 resource ID包括程序集名称后跟句点,然后是文件夹名称后跟一个otherperiod,然后是文件名,其中包含文件扩展名的另一个句点。对于此示例,用于访问ResourceBitmapCode程序中两个位图中较小位图的资源ID为:
ResourceBitmapCode.Images.ModernUserInterface256.jpg
此程序中的代码引用较小的位图,并将Image元素上的HorizontalOptions和VerticalOptions设置为Center:
-
public class ResourceBitmapCodePage : ContentPage
-
{
-
public ResourceBitmapCodePage()
-
{
-
Content = new Image
-
{
-
Source = ImageSource.FromResource(
-
"ResourceBitmapCode.Images.ModernUserInterface256.jpg"),
-
VerticalOptions = LayoutOptions.Center,
-
HorizontalOptions = LayoutOptions.Center
-
};
-
}
-
}
如您所见,此实例中的位图未展开以填充页面:
如果符合以下情况,则不会拉伸位图以填充其容器:
-
它小于容器,并且
-
未设置Image元素的VerticalOptions和HorizontalOptions属性
填充,或者如果Image是StackLayout的子级。
如果注释掉VerticalOptions和HorizontalOptions设置,或者引用大位图(文件名末尾没有“256”),图像将再次拉伸以填充容器。
如果未展开位图以适合其容器,则必须以特定大小显示该位图。那个大小是多少?
在iOS和Android上,位图以像素大小显示。换句话说,通过位图的像素和视频显示的像素之间的一对一映射来渲染位图。用于这些屏幕截图的iPhone 6模拟器的屏幕宽度为750像素,您可以看到位图的256像素宽度约为宽度的三分之一。这里的Android手机是Nexus 5,其像素宽度为1080,位图大约是宽度的四分之一。
但是,在Windows运行时平台上,位图显示在与设备无关的单元中 - 在此示例中,为256个与设备无关的单元。用于这些屏幕截图的诺基亚Lumia 925的像素宽度为768,与iPhone 6大致相同。但是,这款Windows 10 Mobile手机在独立于设备的设备中的屏幕宽度为341,您可以看到ren?dered位图比其他平台宽得多。
有关调整位图大小的讨论将在下一节继续讨论。
您如何引用从XAML存储为嵌入资源的位图?不幸的是,没有ResourceImageSource类。如果有,您可能会尝试在Image.Source标记之间在XAML中实例化该类。但那不是一个选择。
您可以考虑使用x:FactoryMethod来调用ImageSource.FromResource,但这不起作用。正如当前实现的那样,ImageSource.FromResource方法要求位图资源与调用该方法的代码位于同一程序集中。当您使用x:FactoryMethod调用ImageSource.FromResource时,将从Xamarin.Forms.Xaml程序集进行调用。
什么是有效的是一个非常简单的XAML标记扩展。这是一个名为StackedBitmap的项目中的一个:
-
namespace StackedBitmap
-
{
-
[ContentProperty ("Source")]
-
public class ImageResourceExtension : IMarkupExtension
-
{
-
public string Source { get; set; }
-
public object ProvideValue (IServiceProvider serviceProvider)
-
{
-
if (Source == null)
-
return null;
-
return ImageSource.FromResource(Source);
-
}
-
}
-
}
ImageResourceExtension有一个名为Source的属性,您可以将其设置为资源ID。 ProvideValue方法只使用Source属性调用ImageSource.FromResource。 对于单属性标记扩展常见,Source也是该类的content属性。 这意味着当您使用大括号语法进行XAML标记扩展时,您不需要显式包含“Source =”。
但请注意:您无法将此ImageResourceExtension类移动到诸如Xama?rin.FormsBook.Toolkit之类的库中。 该类必须是包含要加载的嵌入式源的同一程序集的一部分,通常是应用程序的可移植类库。
这是StackedBitmap项目中的XAML文件。 Image元素与StackLayout共享两个Label元素:
-
<ContentPage xmlns=""
-
xmlns:x=""
-
xmlns:local="clr-namespace:StackedBitmap "
-
x:Class="StackedBitmap.StackedBitmapPage">
-
-
<StackLayout>
-
<Label Text="320 x 240 Pixel Bitmap"
-
FontSize="Medium"
-
VerticalOptions="CenterAndExpand"
-
HorizontalOptions="Center" />
-
-
<Image Source="{local:ImageResource StackedBitmap.Images.Sculpture_320x240.jpg}"
-
BackgroundColor="Aqua"
-
SizeChanged="OnImageSizeChanged" />
-
<Label x:Name="label"
-
FontSize="Medium"
-
VerticalOptions="CenterAndExpand"
-
HorizontalOptions="Center" />
-
</StackLayout>
-
</ContentPage>
本地前缀是指StackedBitmap程序集中的StackedBitmap命名空间。 Image元素的Source属性设置为ImageResource标记扩展,它引用存储在PCL项目的Images文件夹中的位图并标记为EmbeddedResource。 位图宽320像素,高240像素。 Image还设置了BackgroundColor属性; 这将允许我们在StackLayout中查看Image的整个大小。
Image元素的SizeChanged事件设置为代码隐藏文件中的处理程序:
-
public partial class StackedBitmapPage : ContentPage
-
{
-
public StackedBitmapPage()
-
{
-
InitializeComponent();
-
}
-
void OnImageSizeChanged(object sender, EventArgs args)
-
{
-
Image image = (Image)sender;
-
label.Text = String.Format("Render size = {0:F0} x {1:F0}",
-
image.Width, image.Height);
-
}
-
}
Image元素的大小由StackLayout垂直约束,因此位图以其像素大小(在iOS和Android上)和在Windows Phone上与设备无关的单位显示。 Label以与设备无关的单位显示Image元素的大小,这些单元在每个平台上都有所不同:
底部Label显示的Image元素的宽度包括aqua背景,并且等于设备无关单元中页面的宽度。 您可以使用Fill或As?pectFill的Aspect设置来使位图填充整个aqua区域。
如果您希望Image元素的大小与设备独立单元中的渲染位图大小相同,则可以将Image的HorizontalOptions属性设置为Fill的默认值以外的值:
-
<Image Source="{local:ImageResource StackedBitmap.Images.Sculpture_320x240.jpg}"
-
HorizontalOptions="Center"
-
BackgroundColor="Aqua"
-
SizeChanged="OnImageSizeChanged" />
现在,底部Label仅显示渲染位图的宽度。 Aspect支架的设置无效:
让我们将这个渲染的图像大小称为其自然大小,因为它基于正在显示的位图的大小。
iPhone 6的像素宽度为750像素,但正如您在第5章中运行WhatSize程序时发现的那样,应用程序感知屏幕宽度为375.设备有两个像素?独立单元,因此位图的宽度为显示320像素,宽度为160个单位。
Nexus 5的像素宽度为1080,但应用程序感知宽度为360,因此与设备无关的单元有三个像素,因为107个单元的图像宽度确认。
在iOS和Android设备上,当以自然大小显示位图时,位图的像素与显示器的像素之间存在一对一的映射。但是,在Windows运行时设备上,情况并非如此。用于这些屏幕截图的诺基亚Lumia 925的像素宽度为768.运行Windows 10 Mobile操作系统时,设备独立单元有2.25像素,因此应用程序感知屏幕宽度为341。但320× 240像素位图以320×240个与设备无关的单元的大小显示。
当您从各个平台项目访问位图时,Windows运行时和其他两个平台之间的这种不一致实际上是有益的。正如您将看到的,iOS和Android包含一项功能,可让您为不同的设备分辨率提供不同大小的位图。在效果上,这允许您在与设备无关的单元中指定位图大小,这意味着Windows设备与这些方案一致。
但是当使用与平台无关的位图时,您可能希望在所有三个平台上确定位图的大小,这需要更深入地了解主题。
阅读(4949) | 评论(0) | 转发(0) |