Xamarin:从 PCL(不是来自资源)将图像添加到我的按钮
Xamarin: add image to my button from PCL (not from Resources)
我正在使用 PCL 进行一个 Xamarin.Forms 项目(不是共享项目)。
我在 Android 和 iOS 项目的 Resources 文件夹中都有一些图片。
这有效,图标按预期显示在按钮中:
<Button Image="speaker.png" Grid.Row="0" Grid.Column="0" />
我的 PCL 项目中还有一个文件夹,里面有一些图片:images/icons/speaker.png
我试过这个:
<Button Image="{local:EmbeddedImage TestThree.images.icons.speaker.png}" />
...但这没有用...
我希望这些按钮能够在我的 PCL 项目中显示我的图像文件夹中的图像。
所以我的问题是...
<Button WHAT GOES HERE? Grid.Row="0" Grid.Column="0" />
不起作用的原因是属性绑定到不同的类型。
按钮的图像 属性 需要 "FileImageSource" - Github
图片来源 属性 需要 "ImageSource" - Github
来自 local:EmbeddedImage 我猜你使用的是 Xamarin forms image docs
的扩展
那是行不通的,因为它加载了 "StreamImageSource" 而不是 "FileImageSource"。
实际上你不应该这样做,因为它不会从不同尺寸的图像(@2x、xhdpi 等)加载并且会提供质量差的图像并且不支持多种分辨率。
您可以使用带有 TapGestureRecognizer 的视图容器(Stack 布局等)和在其中居中的图像,或者创建一个自定义渲染器,这确实比它的价值更多。 None 其中显然仍然无法处理多个图像。
正确的解决方案是从基础生成正确大小的图像(我假设是 MDPI Android 或 iOS 的 1X)并将它们放在正确的文件夹和参考中它们在您的工作 Button 示例中。
Button.Image想要FileImageStream的时候,我给他。但是作为项目中的图像,我仍然使用 PCL(或.NET 标准 2.0)库(项目)中的嵌入式资源 PNG 文件。
例如,PCL 项目名称是 "MyProject",我在其子文件夹 "Images\Icons\ok.png" 中放置了一张图像。那么资源名称(例如 ImageSource.FromResource)是 "MyProject.Images.Icons.ok.png"。
此方法将嵌入的资源文件复制到应用程序本地存储中的文件中(仅限第一次)。
public static async Task<string> CopyIcon(string fileName)
{
if (String.IsNullOrEmpty(fileName)) return "";
try
{
// Create (or open if already exists) subfolder "icons" in application local storage
var fld = await FileSystem.Current.LocalStorage.CreateFolderAsync("icons", CreationCollisionOption.OpenIfExists);
if (fld == null) return ""; // Failed to create folder
// Check if the file has not been copied earlier
if (await fld.CheckExistsAsync(fileName) == ExistenceCheckResult.FileExists)
return (await fld.GetFileAsync(fileName))?.Path; // Image copy already exists
// Source assembly and embedded resource path
string imageSrcPath = $"MyProject.Images.Icons.{fileName}"; // Full resource name
var assembly = typeof(FileUtils).GetTypeInfo().Assembly;
// Copy image from resources to the file in application local storage
var file = await fld.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);
using (var target = await file.OpenAsync(PCLStorage.FileAccess.ReadAndWrite))
using (Stream source = assembly.GetManifestResourceStream(imageSrcPath))
await source.CopyToAsync(target); // Copy file stream
return file.Path; // Result is the path to the new file
}
catch
{
return ""; // No image displayed when error
}
}
当我有一个常规文件时,我可以将它用于 FileImageStream (Button.Image)。
第一个选项是从代码中使用它。
public partial class MainPage : ContentPage
{
protected async override void OnAppearing()
{
base.OnAppearing();
btnOk.Image = await FileUtils.CopyIcon("ok.png");
}
}
我也可以在 XAML 中使用它,但我必须创建一个 IMarkupExtension 接口的实现。
[ContentProperty("Source")]
public class ImageFileEx : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
return Task.Run(async () => await FileUtils.CopyIcon(Source)).Result;
}
}
现在我可以直接在 XAML 中指定图像了。
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyProject"
x:Class="MyProject.MainPage"
xmlns:lcl="clr-namespace:MyProject;assembly=MyProject">
<Grid VerticalOptions="Fill" HorizontalOptions="Fill">
<Button Image="{lcl:ImageFileEx Source='ok.png'}" Text="OK" />
</Grid>
</ContentPage>
对于此解决方案,需要 NuGet PCLStorage。
我正在使用 PCL 进行一个 Xamarin.Forms 项目(不是共享项目)。
我在 Android 和 iOS 项目的 Resources 文件夹中都有一些图片。
这有效,图标按预期显示在按钮中:
<Button Image="speaker.png" Grid.Row="0" Grid.Column="0" />
我的 PCL 项目中还有一个文件夹,里面有一些图片:images/icons/speaker.png
我试过这个:
<Button Image="{local:EmbeddedImage TestThree.images.icons.speaker.png}" />
...但这没有用...
我希望这些按钮能够在我的 PCL 项目中显示我的图像文件夹中的图像。
所以我的问题是...
<Button WHAT GOES HERE? Grid.Row="0" Grid.Column="0" />
不起作用的原因是属性绑定到不同的类型。
按钮的图像 属性 需要 "FileImageSource" - Github
图片来源 属性 需要 "ImageSource" - Github
来自 local:EmbeddedImage 我猜你使用的是 Xamarin forms image docs
的扩展那是行不通的,因为它加载了 "StreamImageSource" 而不是 "FileImageSource"。
实际上你不应该这样做,因为它不会从不同尺寸的图像(@2x、xhdpi 等)加载并且会提供质量差的图像并且不支持多种分辨率。
您可以使用带有 TapGestureRecognizer 的视图容器(Stack 布局等)和在其中居中的图像,或者创建一个自定义渲染器,这确实比它的价值更多。 None 其中显然仍然无法处理多个图像。
正确的解决方案是从基础生成正确大小的图像(我假设是 MDPI Android 或 iOS 的 1X)并将它们放在正确的文件夹和参考中它们在您的工作 Button 示例中。
Button.Image想要FileImageStream的时候,我给他。但是作为项目中的图像,我仍然使用 PCL(或.NET 标准 2.0)库(项目)中的嵌入式资源 PNG 文件。 例如,PCL 项目名称是 "MyProject",我在其子文件夹 "Images\Icons\ok.png" 中放置了一张图像。那么资源名称(例如 ImageSource.FromResource)是 "MyProject.Images.Icons.ok.png"。 此方法将嵌入的资源文件复制到应用程序本地存储中的文件中(仅限第一次)。
public static async Task<string> CopyIcon(string fileName)
{
if (String.IsNullOrEmpty(fileName)) return "";
try
{
// Create (or open if already exists) subfolder "icons" in application local storage
var fld = await FileSystem.Current.LocalStorage.CreateFolderAsync("icons", CreationCollisionOption.OpenIfExists);
if (fld == null) return ""; // Failed to create folder
// Check if the file has not been copied earlier
if (await fld.CheckExistsAsync(fileName) == ExistenceCheckResult.FileExists)
return (await fld.GetFileAsync(fileName))?.Path; // Image copy already exists
// Source assembly and embedded resource path
string imageSrcPath = $"MyProject.Images.Icons.{fileName}"; // Full resource name
var assembly = typeof(FileUtils).GetTypeInfo().Assembly;
// Copy image from resources to the file in application local storage
var file = await fld.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);
using (var target = await file.OpenAsync(PCLStorage.FileAccess.ReadAndWrite))
using (Stream source = assembly.GetManifestResourceStream(imageSrcPath))
await source.CopyToAsync(target); // Copy file stream
return file.Path; // Result is the path to the new file
}
catch
{
return ""; // No image displayed when error
}
}
当我有一个常规文件时,我可以将它用于 FileImageStream (Button.Image)。 第一个选项是从代码中使用它。
public partial class MainPage : ContentPage
{
protected async override void OnAppearing()
{
base.OnAppearing();
btnOk.Image = await FileUtils.CopyIcon("ok.png");
}
}
我也可以在 XAML 中使用它,但我必须创建一个 IMarkupExtension 接口的实现。
[ContentProperty("Source")]
public class ImageFileEx : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
return Task.Run(async () => await FileUtils.CopyIcon(Source)).Result;
}
}
现在我可以直接在 XAML 中指定图像了。
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyProject"
x:Class="MyProject.MainPage"
xmlns:lcl="clr-namespace:MyProject;assembly=MyProject">
<Grid VerticalOptions="Fill" HorizontalOptions="Fill">
<Button Image="{lcl:ImageFileEx Source='ok.png'}" Text="OK" />
</Grid>
</ContentPage>
对于此解决方案,需要 NuGet PCLStorage。