Android Question ImageView takes a long time to display

biometrics

Active Member
Licensed User
I display an image with the following code. (reduced for clarity)

B4X:
Sub Globals
    Dim libImage As ImageView
End Sub

Sub PlayImage
    libImage.Bitmap = LoadBitmap(...)
End Sub
When assigning the Bitmap the image immediately displays. This code has been in use for years and years and has never been an issue.

I am now testing a device with Android 5.1.1. When running the compiled code (or in debug mode but not single stepping) after assigning the Bitmap it takes 9 seconds before it shows. But if I single step it displays immediately.

I've tried adding
B4X:
libImage.Invalidate
Sleep(0)
after assigning the Bitmap but it doesn't have an effect.

If I add a 1 millisecond timer at the end of the PlayImage Sub and add a breakpoint in the timer Tick event then it shows immediately. If I remove the breakpoint it takes 9 seconds.

Any ideas what is causing this? Alternatively is there a way to force the draw of the image immediately?
 

biometrics

Active Member
Licensed User
How big is the image? (File size)
I've tried many images incl HD and SD e.g.:

2560x1440 = 1.75 MB
1920x1080 = 900 KB
520x550 = 107 KB

All .jpg.

Note this works fine on all other devices I've used over the year, I'm talking many dozens of Android devices and versions.
 
Last edited:

biometrics

Active Member
Licensed User
Sounds very strange. Please upload a small project with the ImageView and image file.
I doubt that will help as it works on every other device I've used over 8 years from B4A 1.x onwards. It's old code that has always worked. All it does is load an image, nothing complicated at all.

The VideoView works correctly, no delay in starting a video.

This device also has Android 7 which I will test tomorrow, hopefully the problem goes away.
 

biometrics

Active Member
Licensed User
Tip: always better and safer to use LoadBitmapResize.
It's really old code that has always worked fine for us and we only load one full screen image at a time.

That said, I tried LoadBitmapResize earlier and it exhibited the same behaviour.
 

biometrics

Active Member
Licensed User
Turns out it works fine on Android 7.

Problem with 7 is each time you reboot the felUSBSerial library asks for permission whereas on 5 it only asked it once.
 

biometrics

Active Member
Licensed User
I'm still stuck with this problem.

Tried to use a WebView instead but it has issues too.

Are there alternative ImageView libraries I can use?
 

agraham

Expert
Licensed User
The only other one I am aware of is my ScaleImageView which is meant to solve a different problem to yours.

https://www.b4x.com/android/forum/threads/scaleimageview-pan-and-zoom-large-images.102190/

As indicated in the first post of that thread I did a lot of work with ImageView but found it ultimately unsatisfactory for my purpose. However I did not see the effect you are seeing but I have only used it on Android 6 and later. Is what you are seeing restricted to a single device type and Android version? I have found that behaviour can vary between different devices that have nominally the same Android version - USB serial was notorious for this on early Androids and nearly cost me my sanity :(
 

biometrics

Active Member
Licensed User
The only other one I am aware of is my ScaleImageView which is meant to solve a different problem to yours.

https://www.b4x.com/android/forum/threads/scaleimageview-pan-and-zoom-large-images.102190/

As indicated in the first post of that thread I did a lot of work with ImageView but found it ultimately unsatisfactory for my purpose. However I did not see the effect you are seeing but I have only used it on Android 6 and later. Is what you are seeing restricted to a single device type and Android version? I have found that behaviour can vary between different devices that have nominally the same Android version - USB serial was notorious for this on early Androids and nearly cost me my sanity :(
Yip, it's a single device and version of Android. Android 7 works fine on the same device.

I was actually testing your library but this app generates UI components in code, not the designer. Using the designer your library was working well. When I removed the view and did it in code only I couldn't get it to display where I wanted, full screen. It always ended up zoomed down in the centre. Uf you can assist with using it via code only I'd really appreciate it. Basically I want to do:

Dim yourimageview
Activity.AddView(yourimageview, 0, 0, 100%X, 100%Y)
yourimageview.loadimage ...

Alternatively:

yourimageview.left = 0
yourimageview.top = 0
yourimageview.width = 100%X
yourimageview.height = 100%Y
 

agraham

Expert
Licensed User
It should work with code only, I used it as such before I made it a CustomView in version 2. It should be trivial to try it on the demo by deleting the LoadLayout line and adding it by code. In fact I've just done it on an otherwise working copy of the demo. Add two lines and comment two out.

B4X:
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Viewer")
    ScaleImageView1.Initialize("ScaleImageView1")
    Activity.AddView(ScaleImageView1, 0, 0 ,100%x, 100%y)
 
    'gestures.SetOnGestureListener(Panel1, "Panel1")
End Sub
The panel is commented out as a crude work around for a runtime error as I just wanted to check that the view worked - and it does
 

biometrics

Active Member
Licensed User
It should work with code only, I used it as such before I made it a CustomView in version 2. It should be trivial to try it on the demo by deleting the LoadLayout line and adding it by code. In fact I've just done it on an otherwise working copy of the demo. Add two lines and comment two out.

B4X:
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Viewer")
    ScaleImageView1.Initialize("ScaleImageView1")
    Activity.AddView(ScaleImageView1, 0, 0 ,100%x, 100%y)
 
    'gestures.SetOnGestureListener(Panel1, "Panel1")
End Sub
The panel is commented out as a crude work around for a runtime error as I just wanted to check that the view worked - and it does
That's pretty much what I did but the image was centered and about 50% of the display.

I'll try it again tomorrow.
 

biometrics

Active Member
Licensed User
It should work with code only, I used it as such before I made it a CustomView in version 2. It should be trivial to try it on the demo by deleting the LoadLayout line and adding it by code. In fact I've just done it on an otherwise working copy of the demo. Add two lines and comment two out.

B4X:
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Viewer")
    ScaleImageView1.Initialize("ScaleImageView1")
    Activity.AddView(ScaleImageView1, 0, 0 ,100%x, 100%y)
 
    'gestures.SetOnGestureListener(Panel1, "Panel1")
End Sub
The panel is commented out as a crude work around for a runtime error as I just wanted to check that the view worked - and it does
I don't see you loading an image. Try that.
 

biometrics

Active Member
Licensed User
The demo is unchanged apart from the code in Activity_Create. The image is loaded in Activity_Resume

I repeat - I have just tried it and it works the same when added by code and when added by the Designer.
Thanks for confirming. Will try again tomorrow.
 

biometrics

Active Member
Licensed User
The demo is unchanged apart from the code in Activity_Create. The image is loaded in Activity_Resume

I repeat - I have just tried it and it works the same when added by code and when added by the Designer.
I see I was working in the wrong Activity.

I've got the code identical to yours now. No matter what the value of Starter.ViewerZoom is I always get this:



It's not full screen. This is a 1920x1080 .jpg on a 1920x1080 LG display.

I've reduced the code to the minimum:

B4X:
#Region  Activity Attributes
   #FullScreen: True
   #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
   Dim ScaleImageView1 As ScaleImageView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   ScaleImageView1.Initialize("ScaleImageView1")
   Activity.AddView(ScaleImageView1, 0, 0, 100%x, 100%y)   
End Sub

Sub Activity_Resume
   ScaleImageView1.ImageFile = Starter.ViewerFolder & Starter.ViewerFilename
   Dim loops As Int = 1
   Do Until ScaleImageView1.IsReady
       Sleep(100)
       loops = loops + 1
       If loops > 100 Then ' give it up to 10 seconds
           Exit
       End If       
   Loop
   ' restore scale and centre location
   ScaleImageView1.SetScaleAndCenter(Starter.ViewerZoom, Starter.ViewerX, Starter.ViewerY, 1)
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
If I switch back to using the Designer then it works and is full screen at Starter.ViewerZoom = 0.

B4X:
#Region  Activity Attributes
   #FullScreen: True
   #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
   Dim ScaleImageView1 As ScaleImageView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("Viewer")
End Sub

Sub Activity_Resume
   ScaleImageView1.ImageFile = Starter.ViewerFolder & Starter.ViewerFilename
   Dim loops As Int = 1
   Do Until ScaleImageView1.IsReady
       Sleep(100)
       loops = loops + 1
       If loops > 100 Then ' give it up to 10 seconds
           Exit
       End If       
   Loop
   ' restore scale and centre location
   ScaleImageView1.SetScaleAndCenter(Starter.ViewerZoom, Starter.ViewerX, Starter.ViewerY, 1)
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
 

biometrics

Active Member
Licensed User
The demo is unchanged apart from the code in Activity_Create. The image is loaded in Activity_Resume

I repeat - I have just tried it and it works the same when added by code and when added by the Designer.
Another example. In this case I'm getting rid of the toolbar to go full screen. Starter.ViewerZoom = 0.

Using code

B4X:
#Region  Activity Attributes
   #FullScreen: True
   #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
   Dim ScaleImageView1 As ScaleImageView
End Sub

Sub Activity_Create(FirstTime As Boolean)
  Dim jo As JavaObject = Activity
  jo.RunMethod("setSystemUiVisibility", Array As Object(5894))
  Activity.Width = -1
  Activity.Height = -1      
  
  'Activity.LoadLayout("Viewer")
   ScaleImageView1.Initialize("ScaleImageView1")
   Activity.AddView(ScaleImageView1, 0, 0, 100%x, 100%y)  
End Sub

Sub Activity_Resume
   ScaleImageView1.ImageFile = Starter.ViewerFolder & Starter.ViewerFilename
   Dim loops As Int = 1
   Do Until ScaleImageView1.IsReady
       Sleep(100)
       loops = loops + 1
       If loops > 100 Then ' give it up to 10 seconds
           Exit
       End If      
   Loop
   ' restore scale and centre location
   ScaleImageView1.SetScaleAndCenter(Starter.ViewerZoom, Starter.ViewerX, Starter.ViewerY, 1)
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Result:



Using the Designer

B4X:
#Region  Activity Attributes
   #FullScreen: True
   #IncludeTitle: False
#End Region

Sub Process_Globals

End Sub

Sub Globals
   Dim ScaleImageView1 As ScaleImageView
End Sub

Sub Activity_Create(FirstTime As Boolean)
  Dim jo As JavaObject = Activity
  jo.RunMethod("setSystemUiVisibility", Array As Object(5894))
  Activity.Width = -1
  Activity.Height = -1      
  
  Activity.LoadLayout("Viewer")
   'ScaleImageView1.Initialize("ScaleImageView1")
   'Activity.AddView(ScaleImageView1, 0, 0, 100%x, 100%y)  
End Sub

Sub Activity_Resume
   ScaleImageView1.ImageFile = Starter.ViewerFolder & Starter.ViewerFilename
   Dim loops As Int = 1
   Do Until ScaleImageView1.IsReady
       Sleep(100)
       loops = loops + 1
       If loops > 100 Then ' give it up to 10 seconds
           Exit
       End If      
   Loop
   ' restore scale and centre location
   ScaleImageView1.SetScaleAndCenter(Starter.ViewerZoom, Starter.ViewerX, Starter.ViewerY, 1)
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Result:

 
Last edited:
Top