Implementing Multiple Image Picker in .NET MAUI for Android and iOS



Implementing Multiple Image Picker in .NET MAUI for Android and iOS

In this blog, we’ll build a multi-image picker for Android and iOS using .NET MAUI. This functionality will allow users to select multiple images from their device gallery and display them in a CollectionView.

 A special thank you to Awneesh Thakur for your contribution! Your insights have helped shape this exploration, and I appreciate your contribution to the .NET MAUI community.

Join our exclusive WhatsApp group for Xamarin and .NET MAUI developers to connect with experts, share insights, and get help with your projects. Whether you're a beginner or an experienced developer, this group is the perfect place to enhance your skills and collaborate with the community.

1. UI Design for Image Picker

The user interface includes a button to initiate the image selection and a CollectionView to display the selected images.

XAML Code


<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="DemoMultiplePicture.MainPage">

    <ScrollView>
        <VerticalStackLayout Padding="30,0" Spacing="25">
            <Button
                x:Name="CounterBtn"
                Text="Click me" 
                Clicked="OnCounterClicked"
                HorizontalOptions="Fill" />
                
            <CollectionView x:Name="colView">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <Frame Padding="20" HeightRequest="200" WidthRequest="200" BackgroundColor="White">
                            <Image Source="{Binding Images}" Aspect="AspectFill" HeightRequest="200" WidthRequest="200"/>
                        </Frame>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </VerticalStackLayout>
    </ScrollView>

</ContentPage>
    

Explanation: - A ScrollView wraps the layout to allow scrolling if needed. - The Button triggers the image selection when clicked. - A CollectionView dynamically binds and displays the selected images using data templates.

2. Shared Code Logic

The shared code manages dependency injection, button click events, and image binding logic.

Code: MainPage.xaml.cs


public partial class MainPage : ContentPage
{
    INativeImagePicker _INativeImagePicker;

    public MainPage()
    {
        InitializeComponent();
        _INativeImagePicker = MauiApplication.Current.Services.GetRequiredService<INativeImagePicker>();
    }

    List<ImagesFile> _imgList;

    public List<ImagesFile> ImgList
    {
        get { return _imgList; }
        set { _imgList = value; }
    }

    private async void OnCounterClicked(object sender, EventArgs e)
    {
       await SelectMultiplePicturesAsync();
    }

    public async Task SelectMultiplePicturesAsync()
    {
        try
        {
            var selectedImages = await _INativeImagePicker.PickImagesAsync();
            ImgList = new List<ImagesFile>();

            if (selectedImages != null && selectedImages.Count > 0)
            {
                foreach (var data in selectedImages)
                {
                    ImageSource image = ImageSource.FromStream(() => new MemoryStream(data));
                    ImgList.Add(new ImagesFile { Images = image });
                }
            }

            colView.ItemsSource = ImgList;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error selecting files: {ex.Message}");
        }
    }
}

public class ImagesFile
{
    public ImageSource Images { get; set; }
}

public interface INativeImagePicker
{
    Task<List<byte[]>> PickImagesAsync();
}
    

Explanation: - INativeImagePicker defines a cross-platform interface for the image picker functionality. - The SelectMultiplePicturesAsync method: - Invokes the native picker using dependency injection. - Processes the selected images and binds them to the CollectionView.

3. iOS Implementation

On iOS, we use the PHPicker API to handle multi-image selection.

Code: NativeImagePicker.cs


[assembly: Microsoft.Maui.Controls.Dependency(typeof(DemoMultiplePicture.Platforms.iOS.NativeImagePicker))]

namespace DemoMultiplePicture.Platforms.iOS
{
    public class NativeImagePicker : INativeImagePicker
    {
        public Task<List<byte[]>> PickImagesAsync()
        {
            var taskCompletionSource = new TaskCompletionSource<List<byte[]>>();

            var config = new PHPickerConfiguration
            {
                SelectionLimit = 0,
                Filter = PHPickerFilter.ImagesFilter
            };

            var picker = new PHPickerViewController(config);
            picker.Delegate = new PickerDelegate(taskCompletionSource);

            var rootController = UIApplication.SharedApplication.KeyWindow?.RootViewController;
            while (rootController?.PresentedViewController != null)
            {
                rootController = rootController.PresentedViewController;
            }
            rootController?.PresentViewController(picker, true, null);

            return taskCompletionSource.Task;
        }

        private class PickerDelegate : PHPickerViewControllerDelegate
        {
            private readonly TaskCompletionSource<List<byte[]>> _taskCompletionSource;

            public PickerDelegate(TaskCompletionSource<List<byte[]>> taskCompletionSource)
            {
                _taskCompletionSource = taskCompletionSource;
            }

            public override async void DidFinishPicking(PHPickerViewController picker, PHPickerResult[] results)
            {
                var images = new List<byte[]>();

                foreach (var result in results)
                {
                    if (result.ItemProvider.HasItemConformingTo("public.image"))
                    {
                        var data = await result.ItemProvider.LoadDataRepresentationAsync("public.image");
                        if (data != null)
                        {
                            images.Add(data.ToArray());
                        }
                    }
                }

                picker.DismissViewController(true, null);
                _taskCompletionSource.SetResult(images);
            }
        }
    }
}
    

Explanation: - PHPickerConfiguration specifies the selection limit and media type. - PickerDelegate processes selected images and converts them to byte arrays.

4. Android Implementation

On Android, we use the Intent.ACTION_OPEN_DOCUMENT to enable multi-image selection.

Code: NativeImagePicker.cs


[assembly: Microsoft.Maui.Controls.Dependency(typeof(DemoMultiplePicture.Platforms.Android.NativeImagePicker))]

namespace DemoMultiplePicture.Platforms.Android
{
    public class NativeImagePicker : INativeImagePicker
    {
        private const int PickImagesRequestCode = 1000;

        public Task<List<byte[]>> PickImagesAsync()
        {
            var task = ImagePickerHelper.GetImagePickerTask();

            var intent = new Intent(Intent.ActionOpenDocument);
            intent.SetType("image/*");
            intent.PutExtra(Intent.ExtraAllowMultiple, true);
            intent.AddCategory(Intent.CategoryOpenable);

            Platform.CurrentActivity.StartActivityForResult(intent, PickImagesRequestCode);

            return task;
        }
    }

    public static class ImagePickerHelper
    {
        private static TaskCompletionSource<List<byte[]>> _taskCompletionSource;

        public static Task<List<byte[]>> GetImagePickerTask()
        {
            _taskCompletionSource = new TaskCompletionSource<List<byte[]>>();
            return _taskCompletionSource.Task;
        }

        public static void SetResult(List<byte[]> result)
        {
            _taskCompletionSource?.TrySetResult(result);
        }

        public static void SetException(Exception ex)
        {
            _taskCompletionSource?.TrySetException(ex);
        }
    }
}
    

Explanation: - Intent is configured to allow multiple image selection. - Helper methods manage the asynchronous task completion.

5. Conclusion

This blog demonstrates how to create a multi-image picker in .NET MAUI using platform-specific APIs for Android and iOS. By leveraging the power of .NET MAUI, we can achieve a unified user experience across platforms while keeping the core logic shared.



Comments

Popular posts from this blog

Push Notifications in .NET MAUI: A Comprehensive Guide

Push Notification using Firebase in xamarin form (Android and IOS)

School UI Design using xamarin form