B4A Library [Lib] ScrollView2D

Hello,

Does it need a long explanation ? You can scroll in the two directions.

This lib does not work with Android versions < 2.

v1.01:
I fixed a big bug in the original code.
I added the function SmoothScrollTo.

v1.02:
I restarted from a fresh basis because of the many bugs in the original code. I fixed most of them (now, multitouch events and hardware keys are correctly handled) but a few are left and need more work (sometimes the wrong object get the focus and resizing is not perfectly handled). I noticed by the way that the stock scrollview is bugged and does not set the focus correctly if you move your finger very slowly.
Thanks to Erel, I solved the problem with the B4A documentation.
I added a new function: FullScroll.

v1.03:
I fixed all known bugs (including bugs found in ScrollView & HorizontalScrollView);
I added the scrollbars;
I added three new functions:
- ScrollbarsVisibility
- FadingEdges
- GiveFocusToFirstVisible.

v1.1:
I fixed a problem with events that were not fired if declared in a class;
I added two functions: ScrollingIsFinished and DisableTouchEventInterception.

v1.2:
SV2D appears now as a custom view in the designer with all its properties.

v1.3:
I fixed a bug (SV_2 = SV_1 did not work because the inner panel was declared in the wrong class).

Enjoy,
Fred
 

Attachments

  • ScrollView2D v1.3.zip
    120.5 KB · Views: 5,511
  • Java source - ScrollView2D.zip
    17.6 KB · Views: 1,570
Last edited:

johnaaronrose

Active Member
Licensed User
Longtime User
I'm sorry but I don't understand at all what you're trying to do. Upload the full code because this part of the code has no sense to me.
I wonder if you don't make a confusion between moving an image on screen and scrolling it (meaning you see it through a window and scrolls it inside this window). If you want to move an image, look at TouchImageView.

I want to be able to scroll an image. This image only occupies a part of the screen and is NOT at the top left corner. I've attached the relevant module's code.

PS ImagePhoto view is only there so that I can use it for positioning & sizing SV2DPhoto view. I do this because I want to change the positioning & sizing of SV2DPhoto view according to the device's screen details.
 

Attachments

  • View.bas
    7.5 KB · Views: 261

Informatix

Expert
Licensed User
Longtime User
I want to be able to scroll an image. This image only occupies a part of the screen and is NOT at the top left corner. I've attached the relevant module's code.

PS ImagePhoto view is only there so that I can use it for positioning & sizing SV2DPhoto view. I do this because I want to change the positioning & sizing of SV2DPhoto view according to the device's screen details.

Ok, that's clearer now. You forgot to add the ScrollView2D in your layout. An AddView is missing after Initialize.
 

johnaaronrose

Active Member
Licensed User
Longtime User
AddView?

Ok, that's clearer now. You forgot to add the ScrollView2D in your layout. An AddView is missing after Initialize.

OK I now understand a little better. The Initialize sets the ScrollView2D variable to the actual size of the photo, so I've now put that in Sub DisplayDetails as that's where each photo is provided. The AddView sets the screen space (i.e. to that occupied by ImageViewPhoto which I created in the Abstract Designer) for displaying the photo (held in Bitmap Main.Photo). The appropriate revised code is shown below:

B4X:
SV2DPhoto.Initialize(Main.Photo.Width, Main.Photo.Height, "")
   Activity.AddView(SV2DPhoto, ImageViewPhoto.Left, ImageViewPhoto.Top, ImageViewPhoto.Width, ImageViewPhoto.Height)
   SV2DPhoto.Panel.SetBackgroundImage(Main.Photo)
  SV2DPhoto.HorizontalScrollPosition = 0
   SV2DPhoto.VerticalScrollPosition = 0

The photo now displays where it should and allows both horizontal & vertical scrollong on it. I'll have to think about how to cope with orientation change. However, the problem I'm now getting is that the display of other views (i.e. outside that defined by ImageViewPhoto) is now affected by SV2DPhoto. You can see this in ViewRuntime.png in the attached View.zip: underneath Rue des Rosiers (near the top left) it should say Paris (in the LabelCentre view, shown on ViewLayout.png in the attached View.zip) & France (in the LabelCountry view, shown in ViewLayout.png), the ScrollViewInformation (containing scrollable text in LabelInformation) has been pushed downwards. The only reason that I can think of is the above code for SV2DPhoto.HorizontalScrollPosition = 0 & SV2DPhoto.VerticalScrollPosition = 0: do they refer to positions relative to the top left of SV2DPhoto as screen co-ordinates (as per using a ScrollView)? Or is there another reason?

View attachment 13428
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
OK I now understand a little better. The Initialize sets the ScrollView2D variable to the actual size of the photo, so I've now put that in Sub DisplayDetails as that's where each photo is provided. The AddView sets the screen space (i.e. to that occupied by ImageViewPhoto which I created in the Abstract Designer) for displaying the photo (held in Bitmap Main.Photo). The appropriate revised code is shown below:

B4X:
SV2DPhoto.Initialize(Main.Photo.Width, Main.Photo.Height, "")
   Activity.AddView(SV2DPhoto, ImageViewPhoto.Left, ImageViewPhoto.Top, ImageViewPhoto.Width, ImageViewPhoto.Height)
   SV2DPhoto.Panel.SetBackgroundImage(Main.Photo)
  SV2DPhoto.HorizontalScrollPosition = 0
   SV2DPhoto.VerticalScrollPosition = 0

The photo now displays where it should and allows both horizontal & vertical scrollong on it. I'll have to think about how to cope with orientation change. However, the problem I'm now getting is that the display of other views (i.e. outside that defined by ImageViewPhoto) is now affected by SV2DPhoto. You can see this in ViewRuntime.png in the attached View.zip: underneath Rue des Rosiers (near the top left) it should say Paris (in the LabelCentre view, shown on ViewLayout.png in the attached View.zip) & France (in the LabelCountry view, shown in ViewLayout.png), the ScrollViewInformation (containing scrollable text in LabelInformation) has been pushed downwards. The only reason that I can think of is the above code for SV2DPhoto.HorizontalScrollPosition = 0 & SV2DPhoto.VerticalScrollPosition = 0: do they refer to positions relative to the top left of SV2DPhoto as screen co-ordinates (as per using a ScrollView)? Or is there another reason?

1) When you create a view and want to place it on screen, you have two mandatory steps: initializing the object (setting values like its size, its appearance, its behavior) and adding it to the layout (AddView). The designer does these two steps for you. Unfortunately, it does not handle views created by a third-party (like ScrollView2D).

When you initialize a ScrollView2D, you can set three parameters. The first two are for the inner panel dimensions. If you don't know in advance these values, there's no problem to set them to 0 and to change them later. In your case, you should resize the inner panel each time you put a picture on it:
SV2D.Panel.Height = new height
SV2D.Panel.Width = new width
It's a better way than reinitializing the ScrollView each time.

2) Your layout problem is not related to the ScrollView2D. It cannot alter views around it (it doesn't even know what's around). And that's true for most views.
HorizontalPosition and VerticalPosition are relative to the top left corner of the ScrollView.
 

Merlot2309

Active Member
Licensed User
Longtime User
Hello,

Thank you so much for this lib.
It works great on a Galaxy Note, I now have a beautiful scrolling 2D table.

Regards,
Helen.
 

johnaaronrose

Active Member
Licensed User
Longtime User
1) When you create a view and want to place it on screen, you have two mandatory steps: initializing the object (setting values like its size, its appearance, its behavior) and adding it to the layout (AddView). The designer does these two steps for you. Unfortunately, it does not handle views created by a third-party (like ScrollView2D).

When you initialize a ScrollView2D, you can set three parameters. The first two are for the inner panel dimensions. If you don't know in advance these values, there's no problem to set them to 0 and to change them later. In your case, you should resize the inner panel each time you put a picture on it:
SV2D.Panel.Height = new height
SV2D.Panel.Width = new width
It's a better way than reinitializing the ScrollView each time.

2) Your layout problem is not related to the ScrollView2D. It cannot alter views around it (it doesn't even know what's around). And that's true for most views.
HorizontalPosition and VerticalPosition are relative to the top left corner of the ScrollView.


Should SV2D.Panel.Width be the width of the photo as allocated on the screen or be the actual width of the photo (generally larger than the width as allocated on the screen)?

I'm still looking for the cause of the layout problem.

On your Sv2D Example, I've been trying to understand it but am finding it difficult due to the use of dips as it's being run on an unknown device. What is the resolution & density of the device for which you wrote this example?
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
Should SV2D.Panel.Width be the width of the photo as allocated on the screen or be the actual width of the photo (generally larger than the width as allocated on the screen)?

"the actual width of the photo"

On your Sv2D Example, I've been trying to understand it but am finding it difficult due to the use of dips as it's being run on an unknown device. What is the resolution & density of the device for which you wrote this example?

You should always use the dip unit (meaning "device independent pixels").
My SV2D example is designed to be used on any device. The device resolution or density can be anything. That doesn't matter.
 

johnaaronrose

Active Member
Licensed User
Longtime User
"the actual width of the photo"



You should always use the dip unit (meaning "device independent pixels").
My SV2D example is designed to be used on any device. The device resolution or density can be anything. That doesn't matter.

An even more newbie question: I have the photo in a Bitmap named Main.Photo. Should I set SV2DPhoto.Panel.Width = Main.Photo.Width (since that property is presumably measured in pixels) or something different such as using the device's density?

Running Sd2VExample on the emulator with 480x800density1.5, I see one & a half Edit Text views (containing SCROLLVIEW2D) and 3 buttons (containing Horizontal Fullscroll, Vertical Fullscroll & Transform in SV. From the code, I expected to see more. Is that correct?
 

Informatix

Expert
Licensed User
Longtime User
An even more newbie question: I have the photo in a Bitmap named Main.Photo. Should I set SV2DPhoto.Panel.Width = Main.Photo.Width (since that property is presumably measured in pixels) or something different such as using the device's density?

Running Sd2VExample on the emulator with 480x800density1.5, I see one & a half Edit Text views (containing SCROLLVIEW2D) and 3 buttons (containing Horizontal Fullscroll, Vertical Fullscroll & Transform in SV. From the code, I expected to see more. Is that correct?

All dimensions are in pixels, so there's no ambiguity when you use them. When you set a width in dips, the dips are converted and stored as pixels.

Here's a screenshot of the SV2D main screen on my device (854x480). I use only a part of the screen to be sure that the image won't be fully displayed on most devices.
 

Attachments

  • example.jpg
    example.jpg
    36.3 KB · Views: 309

johnaaronrose

Active Member
Licensed User
Longtime User
Displays photo 'compressed' into screen area

I've just returned to trying to make this work, which is why I've not replied earlier. My photos (which I display individually) have resolution 446x559 & 2592x1944, which are both bigger (horizontally & vertically) than my 360x480 emulator that I'm using for testing. They're even bigger relatively, compared to displaying them full screen, when displaying each one on the 210x160 area that I'm using.

I now get each photo in the allocated area. But each photo is 'compressed' into the above mentioned screen area and therefore does not scroll. Code fragments:
in Globals:
B4X:
Dim sv2dPhoto As ScrollView2D
sv2dPhoto.Initialize(0, 0, "")
in Activity_Create:
B4X:
Activity.AddView(sv2dPhoto, ivPhoto.Left, ivPhoto.Top, ivPhoto.Width, ivPhoto.Height)
(where ivPhoto is a non-Visible Image View only used to 'mark', in the Abstract Designer, the area for displaying each photo)
in Sub DisplayDetails:
B4X:
sv2dPhoto.Panel.Width = Main.PhotoBitmap.Width
   sv2dPhoto.Panel.Height = Main.PhotoBitmap.Height
   sv2dPhoto.Panel.SetBackgroundImage(Main.PhotoBitmap)
        sv2dPhoto.HorizontalScrollPosition = 0
   sv2dPhoto.VerticalScrollPosition = 0
   Log("sv2dPhoto("&sv2dPhoto.Left&"," _
                   &sv2dPhoto.Top&"," _
                   &sv2dPhoto.Width&"," _
                   &sv2dPhoto.Height&")") 
   Log("sv2dPhotoPanel("&sv2dPhoto.Panel.Width&"," _
                       &sv2dPhoto.Panel.Height&")")
   Log("ivPhoto("&ivPhoto.Left&"," _
                 &ivPhoto.Top&"," _
                 &ivPhoto.Width&"," _
                        &ivPhoto.Height&")")
   Log("*******************")
   Log("Main.Photo("&Main.PhotoBitmap.Width&","&Main.PhotoBitmap.Height&")")
   Log("*******************")

The results of the above Log statements (for the second photo) are:
sv2dPhoto(0,319,210,159)
sv2dPhotoPanel(2592,1944)
ivPhoto(0,319,210,159)
*******************
 

Informatix

Expert
Licensed User
Longtime User
The results of the above Log statements (for the second photo) are:
sv2dPhoto(0,319,210,159)
sv2dPhotoPanel(2592,1944)
ivPhoto(0,319,210,159)
*******************

All seems fine. Could you send me a project illustrating the problem ?
Anyway, do you really need a picture that big ? You could load it with LoadBitmapSample to save memory (if you don't need to zoom on specific areas of your photo, you can reduce it to the screen size).

Regards,
Fred
 

johnaaronrose

Active Member
Licensed User
Longtime User
Project

All seems fine. Could you send me a project illustrating the problem ?
Anyway, do you really need a picture that big ? You could load it with LoadBitmapSample to save memory (if you don't need to zoom on specific areas of your photo, you can reduce it to the screen size).

Regards,
Fred

The concept is that the activity in question displays all of the photo in a small area & the user then has the option of displaying (using another activity) the photo using the whole screen (with scrolling included).

The photos come from a Blob column in an SQLite3 database table (downloaded from the internet). I guess that I could save each photo in a temporary file & then use LoadBitmapSample but I'd prefer not to. I'm going to populate the Blob column using a PC app (already written & working - cross fingers) with photos which I'll size myself. The large photo I referred to previously is just to test the app by using a photo in much larger resolution than I will actually store in the Blob column.

The app is becoming very complicated & long. So I'll create a Test app from it & try that out: if that has the same problem, I'll post on this thread with the app's .zip file attached. That will have to wait till Sunday/Monday.
 

johnaaronrose

Active Member
Licensed User
Longtime User
Emulator versus device

I've run my app on my ZTE Blade 480x800 density 1.5 Android phone using CyanogenMod 7.2 (Android 2.3. is basis for the Mod) and the scrolling of a photo (in small area) works OK. But not OK on Android Emulator 2.3.3 (i.e. android10) 480x800 density 1.5 created. So it appears that the emulator program or the Android SDK 2.3.3 (on my PC) is at fault.
 

Informatix

Expert
Licensed User
Longtime User
I've run my app on my ZTE Blade 480x800 density 1.5 Android phone using CyanogenMod 7.2 (Android 2.3. is basis for the Mod) and the scrolling of a photo (in small area) works OK. But not OK on Android Emulator 2.3.3 (i.e. android10) 480x800 density 1.5 created. So it appears that the emulator program or the Android SDK 2.3.3 (on my PC) is at fault.

Out of memory ? Increase the heap size of your emulated device. If that becomes OK, that means you use too much memory.
 

johnaaronrose

Active Member
Licensed User
Longtime User
AVD Manager only specifies Device RAM Size. Where is the Heap Size specified?

PS I googled & I found this webpage:
http://www.b4x.com/forum/basic4android-updates-questions/14903-using-android-largeheap.html

The webpage above says to add
SetApplicationAttribute(android:largeHeap,"true")
using the Manifest Editor. Is that correct? If so, is there a Manifest Editor which is part of B4A?

It also says to use android11 or greater.
The SDK Manager shows android1 as 3.0. So I presume that I might as well use android16 (i.e. 4.0). Are there any implications using android16 in B4A in regard to running it on a 2.3.3 Emulator avd or an Android phone running 2.3.3?

PS should I start a new thread for the above questions?
 
Last edited:

johnaaronrose

Active Member
Licensed User
Longtime User
I doubled the Heap Size from 24 to 48. Still same problem with scrolling photo. Also, I should have mentioned that the app doesn't play back audio even though it does on the phone (using theTTS library). Also, I'm now getting a popup titled "Sorry" containing "The application has stopped unexpectedly. Please try again." with 'Force Close' as the only button. Any ideas?
 
Top