【问题标题】:Serialize ImageSource in Xamarin.Forms在 Xamarin.Forms 中序列化 ImageSource
【发布时间】:2021-03-31 06:19:39
【问题描述】:

我正在尝试序列化一个成员为ImageSource 类型的类。 班级是:

    public class AppInfo
    {
        public string Name { get; set; }
        public ImageSource Icon { get; set; }
        public bool Is90Hz { get; set; }
    }

我得到这样的类的数据:

        private static IList<AppInfo> GetAppInfos()
        {
            var localAppInfo = new List<AppInfo>();
            var allAppsRaw = DependencyService.Get<IGetAllApps>().GetApps();

            var pm = Android.App.Application.Context.PackageManager;
            if (pm == null)
                return null;

            foreach (var info in allAppsRaw)
            {
                var bitmap = DependencyService.Get<IGetAllApps>().DrawableToBitmap(info.LoadIcon(pm));
                byte[] bitmapData;

                using (var stream = new MemoryStream())
                {
                    bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
                    bitmapData = stream.ToArray();
                }

                var imageSource = ImageSource.FromStream(() => new MemoryStream(bitmapData, 0, bitmapData.Length));

                localAppInfo.Add(new AppInfo { Name = info.LoadLabel(pm), Icon = imageSource, Is90Hz = true });
            }

            return localAppInfo;
        }

问题在于 System.Text.Json 无法序列化该类型。我来回搜索如何将其转换为字节数组或 Base64 字符串,但我有点迷路了。

我将[JsonConverter(typeof(ImageSourceConverter))] 添加到成员并声明我的转换器类如下:

    public class ImageSourceConverter : JsonConverter<ImageSource>
    {
        public override ImageSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
        }

        public override void Write(Utf8JsonWriter writer, ImageSource value, JsonSerializerOptions options)
        {
        }
    }

但我现在有点迷失了......只是无法弄清楚读写方法的逻辑。

*编辑: 最终目标是展示它,目前的做法:

        <ListView Grid.Column="3" x:Name="AppsView" CachingStrategy="RecycleElement" Margin="10,10,10,10">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Horizontal" CompressedLayout.IsHeadless="true">
                            <Image Source="{Binding Icon, Mode=TwoWay}" WidthRequest="40" HeightRequest="40" HorizontalOptions="StartAndExpand"/>
                            <Label Text="{Binding Name, Mode=TwoWay}" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"/>
                            <Switch IsToggled="{Binding Is90Hz, Mode=TwoWay}" HorizontalOptions="EndAndExpand"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage.Content>

【问题讨论】:

  • 我认为没有任何简单的方法可以做到这一点。 ImageSource 并非旨在公开其基础数据。您最好在 AppInfo 类中存储文件路径、url 或 byte[]。

标签: c# json xamarin serialization xamarin.forms


【解决方案1】:

Xamarin.Forms 使用 Image 视图在页面上显示图像。它有几个重要的属性:

Source - 一个 ImageSource 实例,可以是 File、Uri 或 Resource,用于设置要显示的图像。

ImageSource可以使用静态方法为每种类型的图像源获取实例:

  • FromFile - 需要一个可以在每个平台上解析的文件名或文件路径。

  • FromUri - 需要一个 Uri 对象,例如。新的 Uri("http://....") .

  • FromResource - 需要资源标识符来嵌入应用程序或 .NET Standard 库项目中的图像文件,并带有 构建操作:EmbeddedResource。

  • FromStream - 需要一个提供图像数据的流。

所以你可以尝试绑定流:

改变

public ImageSource Icon { get; set; }

public Stream Icon { get; set; }

然后添加流:

var imageSource = new MemoryStream(bitmapData, 0, bitmapData.Length);

localAppInfo.Add(new AppInfo { Name = info.LoadLabel(pm), Icon = imageSource, Is90Hz = true });

在您的 xaml 中:

<Image>
    <Image.Source>
       <StreamImageSource Stream="{Binding Icon}"
    </Image.Source>
</Image>

【讨论】:

    【解决方案2】:

    谢谢,我最终用转换器做了类似的事情。 在我的 xaml 中:

        <ContentPage.Resources>
             <ResourceDictionary>
                  <api:ByteArrayToImageConverter x:Key="Bti"/>
             </ResourceDictionary>
        </ContentPage.Resources>
    
    <Image Source="{Binding Icon, Converter={StaticResource Bti}, Mode=Default}" WidthRequest="37" HeightRequest="37" HorizontalOptions="StartAndExpand"/>
    

    转换器类:

        public class ByteArrayToImageConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                if (value == null)
                    return null;
    
                var imageAsBytes = (byte[])value;
                return ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) =>
                    throw new NotImplementedException();
        }
    

    我只是将照片保存为byte[]

                    var bitmap = DependencyService.Get<IGetAllApps>().DrawableToBitmap(info.LoadIcon(pm));
                    byte[] bitmapData;
    
                    using (var stream = new MemoryStream())
                    {
                        bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
                        bitmapData = stream.ToArray();
                    }
    
                    localAppInfo.Add(new AppInfo
                        {Name = info.LoadLabel(pm), PackageName = info.PackageName, Icon = bitmapData, Is90Hz = true});
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-21
      • 2014-11-14
      • 2021-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多