Which control needs to be used to show loading image for Images.

Vaibhav Methuku 165 Reputation points
2025-04-08T09:52:49.4866667+00:00

I'm working with large size images, that will take good amount of time to load the image, So for that thing i want show a dummy image like FFimage loading until the actual image loads, So which control will you suggest for this requirement, I tried with FFimage loading, But not working.

Thanks,
Vaibhav Methuku.

Developer technologies | .NET | .NET MAUI
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Michael Le (WICLOUD CORPORATION) 1,145 Reputation points Microsoft External Staff
    2025-07-09T09:49:43.3233333+00:00

    Hello,

    Combining MAUI's built-in Image control with an ActivityIndicator gives you everything you need:

    <Grid>
        <!-- Standard Image Control -->
        <Image Source="{Binding ImageSource}"
               IsVisible="{Binding IsImageVisible}" />
     
        <!-- Loading Indicator -->
        <ActivityIndicator IsRunning="{Binding IsLoading}"
                          IsVisible="{Binding IsLoading}" />
    </Grid>
    

    I've put together a working example that handles all the common scenarios - loading, success, errors, and even lets users input different image URLs to test with. Here's how it looks:

    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:viewModels="clr-namespace:ImageLoadingTest2.ViewModels"
                 x:Class="ImageLoadingTest2.MainPage">
     
        <ContentPage.BindingContext>
            <viewModels:ImageLoadingViewModel/>
        </ContentPage.BindingContext>
     
        <VerticalStackLayout Padding="20" Spacing="20">
     
            <!-- URL Input -->
            <Entry
                Text="{Binding CurrentImageUrl}"
                Placeholder="Enter image URL"
                FontSize="14" />
     
            <!-- Load Button -->
            <Button
                Text="Load Image"
                Command="{Binding LoadImageCommand}"
                BackgroundColor="DodgerBlue"
                TextColor="White" />
     
            <!-- Image Container with Loading State -->
            <Border
                WidthRequest="300"
                HeightRequest="300"
                BackgroundColor="White"
                Stroke="LightGray"
                StrokeThickness="1">
     
                <Grid>
     
                    <!-- Loading State Background -->
                    <BoxView
                        BackgroundColor="LightGray"
                        Opacity="0.2"
                        IsVisible="{Binding IsLoading}" />
     
                    <!-- Standard Image Control -->
                    <Image
                        x:Name="MainImage"
                        Source="{Binding ImageSource}"
                        Aspect="AspectFit"
                        IsVisible="{Binding IsImageVisible}"
                        BackgroundColor="Transparent" />
     
                    <!-- Loading ActivityIndicator -->
                    <ActivityIndicator
                        IsRunning="{Binding IsLoading}"
                        IsVisible="{Binding IsLoading}"
                        Color="DodgerBlue"
                        HeightRequest="40"
                        WidthRequest="40"
                        HorizontalOptions="Center"
                        VerticalOptions="Center" />
     
                    <!-- Loading Text -->
                    <Label
                        Text="Loading image..."
                        IsVisible="{Binding IsLoading}"
                        FontSize="12"
                        TextColor="Gray"
                        HorizontalOptions="Center"
                        VerticalOptions="End"
                        Margin="0,0,0,20" />
     
                </Grid>
     
            </Border>
     
        </VerticalStackLayout>
    </ContentPage>
    

    I've tried to keep the view model simple:

    public class ImageLoadingViewModel : INotifyPropertyChanged
    {
        private bool isLoading = false;
        private bool isImageVisible = false;
        private ImageSource imageSource;
        private string currentImageUrl = "https://picsum.photos/id/15/4000/3000";
        private readonly HttpClient _httpClient;
     
        public bool IsLoading
        {
            get => isLoading;
            set { isLoading = value; OnPropertyChanged(); }
        }
     
        public bool IsImageVisible
        {
            get => isImageVisible;
            set { isImageVisible = value; OnPropertyChanged(); }
        }
     
        public ImageSource ImageSource
        {
            get => imageSource;
            set { imageSource = value; OnPropertyChanged(); }
        }
     
        public string CurrentImageUrl
        {
            get => currentImageUrl;
            set { currentImageUrl = value; OnPropertyChanged(); }
        }
     
        public ICommand LoadImageCommand { get; }
     
        public ImageLoadingViewModel()
        {
            _httpClient = new HttpClient();
            LoadImageCommand = new Command(async () => await LoadImageAsync());
     
            // Auto-load image on startup
            _ = LoadImageAsync();
        }
     
        private async Task LoadImageAsync()
        {
            try
            {
                // Set loading state immediately - hides current image
                IsImageVisible = false;
                IsLoading = true;
     
                // Download image data to verify it exists and is valid
                using var response = await _httpClient.GetAsync(CurrentImageUrl);
                response.EnsureSuccessStatusCode();
     
                // Read the image data
                var imageData = await response.Content.ReadAsByteArrayAsync();
     
                // Create ImageSource from downloaded data
                ImageSource = ImageSource.FromStream(() => new MemoryStream(imageData));
     
                // Show the image
                IsLoading = false;
                IsImageVisible = true;
            }
            catch (Exception ex)
            {
                // Handle loading errors
                IsLoading = false;
                IsImageVisible = false;
                System.Diagnostics.Debug.WriteLine($"Error loading image: {ex.Message}");
            }
        }
     
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string name = null) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
    

    A simple command implementation:

    public class Command : ICommand
    {
        private readonly Func<Task> _execute;
        private readonly Func<bool> _canExecute;
     
        public Command(Func<Task> execute, Func<bool> canExecute = null)
        {
            _execute = execute;
            _canExecute = canExecute;
        }
     
        public event EventHandler CanExecuteChanged;
     
        public bool CanExecute(object parameter) => _canExecute?.Invoke() ?? true;
     
        public async void Execute(object parameter) => await _execute();
     
        public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
    

    If you prefer, there is a community fork of FFImageLoading called FFImageLoading.Maui that brings some of the familiar API to MAUI.

    I hope this helps you! Let me know if you have questions about any part of the implementation.

    For reference:


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.