Xamarin.forms List App With Icon (android Only)
I have an Xamarin Forms project and i try to have a list of Installed applications with the icon. For now i have the Label, but i dont get the image. I use the Dependency Service t
Solution 1:
It is faster & more memory efficient to create a new ImageSource
that loads the icon as its original Drawable
vs. converting to a Bitmap, byte array, etc... Also this works correctly with recycling cells in a ListView, etc...
ImageSource Implementation (exists in a .NetStd/Forms library):
[TypeConverter(typeof(PackageNameSourceConverter))]
publicsealedclassPackageNameSource : ImageSource
{
publicstaticreadonly BindableProperty PackageNameProperty = BindableProperty.Create(nameof(PackageName), typeof(string), typeof(PackageNameSource), default(string));
publicstatic ImageSource FromPackageName(string packageName)
{
returnnew PackageNameSource { PackageName = packageName };
}
publicstring PackageName
{
get { return (string)GetValue(PackageNameProperty); }
set { SetValue(PackageNameProperty, value); }
}
publicoverride Task<bool> Cancel()
{
return Task.FromResult(false);
}
publicoverridestringToString()
{
return$"PackageName: {PackageName}";
}
publicstaticimplicitoperatorPackageNameSource(string packageName)
{
return (PackageNameSource)FromPackageName(packageName);
}
publicstaticimplicitoperatorstring(PackageNameSource packageNameSource)
{
return packageNameSource != null ? packageNameSource.PackageName : null;
}
protectedoverridevoidOnPropertyChanged(string propertyName = null)
{
if (propertyName == PackageNameProperty.PropertyName)
OnSourceChanged();
base.OnPropertyChanged(propertyName);
}
}
TypeConverter Implementation (exists in a .NetStd/Forms library):
[TypeConversion(typeof(PackageNameSource))]
publicsealedclassPackageNameSourceConverter : TypeConverter
{
publicoverrideobjectConvertFromInvariantString(stringvalue)
{
if (value != null)
return PackageNameSource.FromPackageName(value);
thrownew InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(PackageNameSource)));
}
}
IImageSourceHandler, IImageViewHandler Implementation (exists in a Xamarin.Android project):
publicclassPackageNameSourceHandler : IImageSourceHandler, IImageViewHandler
{
publicasync 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);
}
}
Note: Register this at the assembly level:
[assembly: ExportImageSourceHandler(typeof(PackageNameSource), typeof(PackageNameSourceHandler))]
Now in your dependency service return a list of Android applications that includes at least the PackageName, something like an IList<Package>
publicclassPackage
{
publicstring Name { get; set; }
publicstring PackageName { get; set; }
}
Xaml Example:
Now you can bind that IList<Package>
to a ListView
custom cell using this PackageNameSource
:
<ImageWidthRequest="60"HeightRequest="60"><Image.Source><local:PackageNameSourcePackageName="{Binding PackageName}" /></Image.Source></Image>
Post a Comment for "Xamarin.forms List App With Icon (android Only)"