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.
Table of Contents for .Net Maui
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
Post a Comment