Skip to content Skip to sidebar Skip to footer

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>

enter image description here

Post a Comment for "Xamarin.forms List App With Icon (android Only)"