在 xamarin 中滚动 CollectionView 图片时它滞后,该怎么办?

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

当我在 CollectionView 中滚动时,它开始滞后,可能是在加载下一张图片。我能用它做什么?我该如何优化它?

这里是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>

这是我的代码:

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

如果您的图片非常大,超过 100KB(每张),那么您可以考虑为具有不同文件名和更小尺寸(例如 10-20KB)的相同图片创建缩略图。

这将提高您应用的速度。

要调整图像大小,您可以使用以下代码。该功能将保持原始图像的纵横比。此外,代码会将原始图像设置为 72dpi。结果将是一个经过优化的小文件,可以呈现给您的视图。

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;
}

如果您的图片很大,请尝试将其调整为您需要的尺寸,也许它会解决这个问题,下面是很好的参考。

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

这是调整大小的工作代码:

 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;
    }