gpt4 book ai didi

c# - 带有图标的 Xamarin.Forms 列表应用程序(仅限 Android)

转载 作者:行者123 更新时间:2023-12-03 22:12:47 25 4
gpt4 key购买 nike

我有一个 Xamarin Forms 项目,我尝试使用图标列出已安装的应用程序。

现在我有标签,但我没有得到图像。

我使用依赖服务来获取应用程序列表。 :

public IEnumerable<IAppListServiceApplication> GetApplications()
{
var apps = Android.App.Application.Context.PackageManager.GetInstalledApplications(PackageInfoFlags.MatchAll);
foreach (var app in apps)
{
var label = app.LoadLabel(Android.App.Application.Context.PackageManager);
if (!label.ToLower().StartsWith("com."))
yield return new AppListServiceApplication
{
Label = label,
PackageName = app.PackageName,
AppIcon = GetAppIcon(app)
};
}
}

但我无法将 Android Drawable 对象转换为 Xamarin Forms 项目中的 ImageSource。这是我现在尝试的:
public ImageSource GetAppIcon(ApplicationInfo app)
{
try
{
var drawable = app.LoadIcon(Android.App.Application.Context.PackageManager);

//return ImageSource.FromStream(() => new MemoryStream(bytes));
Bitmap icon = drawableToBitmap(drawable);

return ImageSource.FromStream(() => MemoryStreamFromBitmap(icon));
}
catch (Exception ex)
{
var message = ex.ToString();
return null;
}


}
MemoryStream MemoryStreamFromBitmap(Bitmap bmp)
{
MemoryStream stream = new MemoryStream();
bmp.Compress(Bitmap.CompressFormat.Png, 0, stream);
return stream;
}
Bitmap drawableToBitmap(Drawable drawable)
{
Bitmap bitmap = null;

if (drawable is BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable)drawable;
if (bitmapDrawable.Bitmap != null)
{
return bitmapDrawable.Bitmap;
}
}
if (drawable is AdaptiveIconDrawable)
{
AdaptiveIconDrawable adaptiveIconDrawable = (AdaptiveIconDrawable)drawable;
if (!(adaptiveIconDrawable.IntrinsicWidth <= 0 || adaptiveIconDrawable.IntrinsicHeight <= 0))
{
bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth, drawable.IntrinsicHeight, Bitmap.Config.Argb8888);
Canvas c = new Canvas(bitmap);
drawable.SetBounds(0, 0, c.Width, c.Height);
drawable.Draw(c);
return bitmap;

}
}

if (drawable.IntrinsicWidth <= 0 || drawable.IntrinsicHeight <= 0)
{
bitmap = Bitmap.CreateBitmap(1, 1, Bitmap.Config.Argb8888); // Single color bitmap will be created of 1x1 pixel
}
else
{
bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth, drawable.IntrinsicHeight, Bitmap.Config.Argb8888);
}

Canvas canvas = new Canvas(bitmap);
drawable.SetBounds(0, 0, canvas.Width, canvas.Height);
drawable.Draw(canvas);
return bitmap;
}

如您所见,我是 xamarin 和 Android 的新手 ^^。
我没有在 Google 上找到如何从 Android 传递 Drawable 以在 Xamarin Forms 中显示它。

如果你能指出正确的方向来引导我如何做到这一点。

坦克

编辑:添加输出错误

我在输出窗口中收到此错误:
ImageLoaderSourceHandler: Image data was invalid: Xamarin.Forms.StreamImageSource
11-05 04:31:19.287 D/skia (10270): --- SkAndroidCodec::NewFromStream returned null

**编辑:** 添加项目

这是 gitHub 中的问题: https://github.com/werddomain/Xamarin-Android-Laucher/tree/master/Forms/AndroidCarLaucher

最佳答案

创建一个新的 ImageSource 更快,内存效率更高将图标加载为其原始 Drawable与转换为位图、字节数组等...这也适用于 ListView 等中的回收单元格...

ImageSource 实现(存在于 .NetStd/Forms 库中):

[TypeConverter(typeof(PackageNameSourceConverter))]
public sealed class PackageNameSource : ImageSource
{
public static readonly BindableProperty PackageNameProperty = BindableProperty.Create(nameof(PackageName), typeof(string), typeof(PackageNameSource), default(string));

public static ImageSource FromPackageName(string packageName)
{
return new PackageNameSource { PackageName = packageName };
}

public string PackageName
{
get { return (string)GetValue(PackageNameProperty); }
set { SetValue(PackageNameProperty, value); }
}

public override Task<bool> Cancel()
{
return Task.FromResult(false);
}

public override string ToString()
{
return $"PackageName: {PackageName}";
}

public static implicit operator PackageNameSource(string packageName)
{
return (PackageNameSource)FromPackageName(packageName);
}

public static implicit operator string(PackageNameSource packageNameSource)
{
return packageNameSource != null ? packageNameSource.PackageName : null;
}

protected override void OnPropertyChanged(string propertyName = null)
{
if (propertyName == PackageNameProperty.PropertyName)
OnSourceChanged();
base.OnPropertyChanged(propertyName);
}
}

TypeConverter 实现(存在于 .NetStd/Forms 库中):
[TypeConversion(typeof(PackageNameSource))]
public sealed class PackageNameSourceConverter : TypeConverter
{
public override object ConvertFromInvariantString(string value)
{
if (value != null)
return PackageNameSource.FromPackageName(value);

throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(PackageNameSource)));
}
}

IImageSourceHandler、IImageViewHandler 实现(存在于 Xamarin.Android 项目中):
public class PackageNameSourceHandler : IImageSourceHandler, IImageViewHandler
{
public async Task<Bitmap> LoadImageAsync(ImageSource imagesource, Context context, CancellationToken cancelationToken = default(CancellationToken))
{
var packageName = ((PackageNameSource)imagesource).PackageName;
using (var pm = Application.Context.PackageManager)
using (var info = pm.GetApplicationInfo(packageName, PackageInfoFlags.MetaData))
using (var drawable = info.LoadIcon(pm))
{
Bitmap bitmap = null;
await Task.Run(() =>
{
bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth, drawable.IntrinsicHeight, Bitmap.Config.Argb8888);
using (var canvas = new Canvas(bitmap))
{
drawable.SetBounds(0, 0, canvas.Width, canvas.Height);
drawable.Draw(canvas);
}
});
return bitmap;
}
}

public Task LoadImageAsync(ImageSource imagesource, ImageView imageView, CancellationToken cancellationToken = default(CancellationToken))
{
var packageName = ((PackageNameSource)imagesource).PackageName;
using (var pm = Application.Context.PackageManager)
{
var info = pm.GetApplicationInfo(packageName, PackageInfoFlags.MetaData);
imageView.SetImageDrawable(info.LoadIcon(pm));
}
return Task.FromResult(true);
}
}

注意:在程序集级别注册:
[assembly: ExportImageSourceHandler(typeof(PackageNameSource), typeof(PackageNameSourceHandler))]

现在,在您的依赖服务中返回至少包含 PackageName 的 Android 应用程序列表,类似于 IList<Package>
public class Package
{
public string Name { get; set; }
public string PackageName { get; set; }
}

Xaml 示例:

现在你可以绑定(bind) IList<Package>ListView使用此 PackageNameSource 的自定义单元格:
<Image WidthRequest="60" HeightRequest="60">
<Image.Source>
<local:PackageNameSource PackageName="{Binding PackageName}" />
</Image.Source>
</Image>

enter image description here

关于c# - 带有图标的 Xamarin.Forms 列表应用程序(仅限 Android),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53137503/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com