Lukas Planespotter
Lukas Planespotter

Reputation: 39

When scrolling in CollectionView pictures in xamarin its laging, what to do?

When i am scrolling in CollectionView it starts to lag, probably loading of next pictures. What can i do with that? How can i optimize it?

Here is XAML:

<Grid BackgroundColor="#00aeef">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <CollectionView x:Name="myCollectionView" Grid.Row="0">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout>
                        <Frame Padding="0" BackgroundColor="#00d2ff" Margin="20" CornerRadius="30">
                            <StackLayout Padding="20">
                                <Label Text="{Binding Airline}" TextColor ="White" FontSize="30" HorizontalOptions="Center"/>
                                <Image Source="{Binding Url}" HeightRequest="200"/>
                                <Label Text="{Binding Plane, StringFormat='Plane: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Airline, StringFormat='Airline: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Livery, StringFormat='Livery: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Registration, StringFormat='Reg: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Airport, StringFormat='Airport: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Date, StringFormat='Date: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Comment, StringFormat='Comment: {0}'}" TextColor ="White" FontSize="15"/>
                            </StackLayout>
                        </Frame>
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </Grid>

And here is my code:

public ShowPlanes()
    {
        InitializeComponent();
        var db = new SQLiteConnection(_dbPath);
        var data = db.Table<Airplane>().ToList();
        myCollectionView.ItemsSource = data;
        NavigationPage.SetHasNavigationBar(this, false);
    }

Upvotes: 1

Views: 695

Answers (4)

Haider Ali Faizi
Haider Ali Faizi

Reputation: 1

I check your code and I experiment it by different ways and finally, I am able why it is lagging. By adding scrollview and also remember to fix width of image also. Can you try this code:

<Grid BackgroundColor="#00aeef">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
<scrollview>
        <CollectionView x:Name="myCollectionView" Grid.Row="0">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout>
                        <Frame Padding="0" BackgroundColor="#00d2ff" Margin="20" CornerRadius="30">
                            <StackLayout Padding="20">
                                <Label Text="{Binding Airline}" TextColor ="White" FontSize="30" HorizontalOptions="Center"/>
                                <Image Source="{Binding Url}" HeightRequest="200" WidthRequest="200"/>
                                <Label Text="{Binding Plane, StringFormat='Plane: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Airline, StringFormat='Airline: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Livery, StringFormat='Livery: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Registration, StringFormat='Reg: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Airport, StringFormat='Airport: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Date, StringFormat='Date: {0}'}" TextColor ="White" FontSize="15"/>
                                <Label Text="{Binding Comment, StringFormat='Comment: {0}'}" TextColor ="White" FontSize="15"/>
                            </StackLayout>
                        </Frame>
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
</scrollview>
    </Grid>

Upvotes: 0

Lukas Planespotter
Lukas Planespotter

Reputation: 39

This is working code for resizing:

 var bitmap = SKBitmap.Decode(Path);
        int h = bitmap.Height;
        int w = bitmap.Width;
        int newWidth = w;
        int newHeight = h;            
        
        if (h > 1080 || w > 1080)
        {
            int rectHeight = 1080;
            int rectWidth = 1080;

            //aspect ratio calculation   
            float W = w;
            float H = h;
            float aspect = W / H;                
            await DisplayAlert("aspect", aspect.ToString() + w.ToString() + h.ToString(), "OK");

            //new dimensions by aspect ratio
            newWidth = (int)(rectWidth * aspect);
            newHeight = (int)(newWidth / aspect);
            await DisplayAlert("aspect", "h " + newHeight.ToString() + " w " + newWidth.ToString(), "OK");

            //if one of the two dimensions exceed the box dimensions
            if (newWidth > rectWidth || newHeight > rectHeight)
            {
                //depending on which of the two exceeds the box dimensions set it as the box dimension and calculate the other one based on the aspect ratio
                if (newWidth > newHeight)
                {
                    newWidth = rectWidth;
                    newHeight = (int)(newWidth / aspect);                        
                }
                else
                {
                    newHeight = rectHeight;
                    newWidth = (int)(newHeight * aspect);                        
                }
            }                              
        }
                
            
        var resizedImage = bitmap.Resize(new SKImageInfo(newWidth, newHeight), SKBitmapResizeMethod.Lanczos3);
        var image = resizedImage.Encode(SKEncodedImageFormat.Jpeg, 80);
        var path = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);            
        var filepath = System.IO.Path.Combine(path, fileName);
        string finalPath = filepath;
        using (var stream = File.OpenWrite(filepath))            
            image.SaveTo(stream);            
        return finalPath;
    }

Upvotes: 1

Prayag
Prayag

Reputation: 472

if your images are large try resizing it to your required size may be it will solve it below is very good reference.

https://learn.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/xamformsimageresize/

Upvotes: 1

Isidoros Moulas
Isidoros Moulas

Reputation: 697

If your images are quite big like over 100KB (each) then you may consider creating thumbnails to the same images with a different filename and smaller size like 10-20KB.

This will increase your app's speed.

To resize the image you can use the following code. The function will keep the aspect ratio of the original image. Also, the code will set to 72dpi the original image. The result will be a small optimized file ready for rendering to your view.

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
...

 public static void CreatePreviewImage(string imageFullFilename, string previewFullFilename)
 {
            ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);
            // Create an Encoder object based on the GUID  
            // for the Quality parameter category.  
            System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
            // Create an EncoderParameters object.  
            // An EncoderParameters object has an array of EncoderParameter  
            // objects. In this case, there is only one  
            // EncoderParameter object in the array.  
            EncoderParameters myEncoderParameters = new EncoderParameters(1);
            EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 75L); //default
            myEncoderParameters.Param[0] = myEncoderParameter;

            Bitmap originalimage = (Bitmap)System.Drawing.Image.FromFile(imageFullFilename, true);
            originalimage.SetResolution(72, 72);

            int w = originalimage.Width;
            int h = originalimage.Height;
            int pw = 0;
            int ph = 0;

            h = originalimage.Height * w / originalimage.Width;

            if (w > h)
            {
                pw = 200;
                ph = h * pw / w;
            }
            else
            {
                ph = 200;
                pw = w * ph / h;
            }

            Bitmap previewImage = ImageHandlers.ResizeImage(originalimage, pw, ph);
            previewImage.Save(previewFullFilename, jpgEncoder, myEncoderParameters);
 }

 public static Bitmap ResizeImage(Image image, int width, int height)
        {
            var h = image.Height;
            var w = image.Width;
            if (w > h)
            {
                height = h * width / w;
            } else if( h < w )
            {
                width = w * height / h;
            }

            var destRect = new Rectangle(0, 0, width, height);
            var destImage = new Bitmap(width, height);

            destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

            using (var graphics = Graphics.FromImage(destImage))
            {
                graphics.CompositingMode = CompositingMode.SourceCopy;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

                using (var wrapMode = new ImageAttributes())
                {
                    wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                    graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
                }
            }

            return destImage;
        }

public static ImageCodecInfo GetEncoder(ImageFormat format)
{
    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
    foreach (ImageCodecInfo codec in codecs)
       {
           if (codec.FormatID == format.Guid)
           {
               return codec;
           }
       }
    return null;
}

Upvotes: 1

Related Questions