Android Question HorizontalScrollView Image Performance

RichardN

Active Member
Licensed User
I have to present a small (40-50) number of JPG portrait files in a Horizontal ScrollView (hsv1). The images are all portrait orientation, of similar size but are of slightly differing aspect ratios.

With the code below (using LoadBitmapResize) the images fit perfectly within the view but the scrolling action is jerky giving a poor user experience. If I employ LoadBitmapResample and play with the GRAVITY property the scrolling is now perfectly smooth but the images are either cropped or distorted. There does not appear to be any combination of methods to produce the desired result with smooth scrolling.

What is the correct method to use?

B4X:
Dim Img as ImageView
hsv1.Panel.Width = Activity.Width * PictureNames.Size
   
For c = 0 To PictureNames.Size -1   

    Img.Initialize("")
    Img.Gravity = Gravity.CENTER
        
    Img.Bitmap = LoadBitmapResize(AppDir, PictureNames.Get(c), Activity.Width, Activity.Height, True)
        
    hsv1.Panel.AddView(Img,c * Activity.Width,0,Activity.Width,Activity.Height)
        
Next
 

RichardN

Active Member
Licensed User
Thanks Erel,

I have tried as you suggested using the xCLV with lazy loading in the VisibleRangeChanged event and the experience is better but still NOT very good. To my surprise the 1200 bitmap example you offered above scrolls smoothly on my device so I investigated further.

I was about to offer an example for you to try when I discovered that when using my code with 25 random .jpg files of identical dimensions, the scroll performance is perfect. However with the .jpg files I was previously using.... the file size was similar but all the aspect ratios were slightly different.

Perhaps the repetitive LoadBitmapResize operation when working with bitmaps with different aspect ratios is stealing too much processor power and screen lag results?
 

RichardN

Active Member
Licensed User
Attached is an example using jpg portrait images of dissimilar dimensions. The images vary in size by maybe ~200px vertically and vary in file-size from 50Kb to 260Kb. On my Samsung S9 test device the scroll action is NOT as smooth as in other examples that use bitmaps of identical dimensions and of a single colour.

Is there an answer to this ?

The project with images is a tiny bit too big to upload: find it here..... http://www.rjnoble.plus.com/photo_album.zip
 
Last edited:

Erel

Administrator
Staff member
Licensed User
Tip:
B4X:
Dim GetFiles As List
   GetFiles.Initialize2(File.ListFiles(AppDir))
   
   Private c As Short, ThisFile As String
   
   For c = 0 To GetFiles.Size -1
       
       ThisFile = GetFiles.Get(c)
       If ThisFile.Contains(".jpg") Then FileList.Add(ThisFile)
       
   Next
Can be written like this:
B4X:
For Each ThisFile As String In File.ListFiles(AppDir)
   If ThisFile.Contains(".jpg") Then FileList.Add(ThisFile)
Next
You are creating huge images. A full screen image on a high scale screen is a very large image. You need to scale the images down. You can choose all kinds of factors, a good one to start with is XUI.Scale.

B4X:
'ScaleDown is a global float variable that is set with: ScaleDown = xui.Scale
Sub CustomListView1_VisibleRangeChanged (FirstIndex As Int, LastIndex As Int)
   Dim ExtraSize As Int = 2
   For i = 0 To CustomListView1.Size - 1
       Dim p As B4XView = CustomListView1.GetPanel(i)
       Dim iv As ImageView
       
       Dim id As ImageData = CustomListView1.GetValue(i)
       
       If i >= Max(0, FirstIndex - ExtraSize) And i <=  Min(LastIndex + ExtraSize, CustomListView1.Size - 1) Then
           If p.NumberOfViews = 0 Then
               iv.Initialize("")
               iv.Gravity = Gravity.FILL
               p.AddView(iv, 0, 0, CustomListView1.AsView.Width,CustomListView1.AsView.Height)
           Else
               iv = p.GetView(0)
           End If
       
           If id.Bitmap.IsInitialized = False Then
               id.Bitmap = xui.LoadBitmapResize(AppDir, id.FileName, iv.Width / ScaleDown, iv.Height / ScaleDown, True)
           End If
           SetImageAndCenter(iv, id.Bitmap)
       Else
           If p.NumberOfViews = 0 Then Continue
           iv = p.GetView(0)
           iv.Bitmap = Null
           If id.Bitmap.IsInitialized Then
               id.Bitmap = Null
           End If
       End If
   Next
End Sub

Sub SetImageAndCenter (iv As ImageView, bmp As B4XBitmap)
   Dim Parent As B4XView = iv.Parent
   iv.SetLayoutAnimated(0, Parent.Width / 2 - bmp.Width * ScaleDown / 2, Parent.Height / 2 - bmp.Height * ScaleDown / 2, _
       bmp.Width * ScaleDown, bmp.Height * ScaleDown)
   iv.Bitmap = bmp
End Sub
Make sure to test it in release mode.
 

RichardN

Active Member
Licensed User
Thanks Erel, I see what you have done.

This is actually the most robust implementation of lazy loading I have seen so far.
 
Top