B4A Library ViewPager - Cleaned up ViewPager

This library is a cleaned up and slightly enhanced version of the AHViewPager library. There are some deprecated objects in AHViewPager that I removed here and it has a slighly better handling now.

Installation:
You will need the Android Support Repository installed in SDK Manager.
The library requires B4A 6.31+
Copy all three files (.xml, .jar, .aar) to your additional libraries folder.


Usage:
Usage is very similar to AHViewPager though I never really explained AHViewPager in detail. So here we go:

There are 3 objects: PageContainer, ViewPager and VPage.

The PageContainer holds the pages of type VPage. You can add and remove pages dynamically.
You will probably do something like this in Activity_Create:
B4X:
Sub Globals
    Private VP As ViewPager
    Private PC As PageContainer
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("layout1")

    'Initialize the PageContainer.
    PC.Initialize

    'Add some pages
    For i = 0 To 10
        PC.AddPage("Page " & i)
    Next

Adding a page does create a VPage object. This object contains a title, can hold a tag object for storing additional data and has a Panel. The Panel is initialized when a page is added but it is not added to any layout so it has no size at this time and a layout can not be loaded immediately. Loading a layout is done in the PageCreated event.

The ViewPager object is added to the layout of your activity, either by code or by designer. You need to connect the ViewPager with the PageContainer:
B4X:
'Set the PageContainer for the ViewPager
VP.PageContainer = PC

There are no tabs in this library. If you want to have tabs for the ViewPager use DSTabLayout from DesignSupport library (see the example, you will need DesignSupport library v2.21+).

The VPage object just represents one page.

To load the contents for the pages you should use the PageCreated Event.
There are two possiblilites to load the layout.

1. Cached
A cached page is only initialized once. You can check with the Page.AlreadyCreated property if the page was created previously.
2. Non-Cached
Non-Cached pages are regenerated every time the PageCreated event is fired.

The advantage of cached pages is that the page content is only created once in the lifetime of the ViewPager. Disadvantage is that it needs more memory to hold all the pages.

B4X:
Sub VP_PageCreated (Position As Int, Page As VPage)
    If Page.AlreadyCreated = True Then
        Log("Page already created => do nothing")
    Else
        Log("New Page => load the layout")
        Page.Panel.LoadLayout("pagelayout")
                [fill the content of your page here]
    End If
End Sub

If you use Cached pages then you don't need to do anything in the PageDestroyed event. The page panel will just be removed from the layout (and readded again on PageCreated automatically).
If you use Non-Cached pages then you have to remove all content from the page panel in PageDestroyed:
B4X:
Sub VP_PageDestroyed (Position As Int, Page As VPage)
    Page.Panel.RemoveAllViews
    Page.AlreadyCreated = False
End Sub
Remember: You should only do this for non-cached pages.

Reference:

Version history:
V1.00
  • Initial release
V1.01
  • Fix: changed packagename to anywheresoftware.b4a.objects to reduce fields size.
V1.10
  • Compiled against newest Support library.
  • Fixed crash when adding items to a page manually
 

Attachments

  • NewViewPagerExample1_0.zip
    9.7 KB · Views: 867
  • ViewPagerLib1_10.zip
    14.2 KB · Views: 791
Last edited:

Mahares

Expert
Licensed User
Longtime User
Markus:
I use the old AHViewPager in some of my projects:
1. What is involved in converting a AHViewpager project into the new and improved ViewPager project?
2. In some of the AHViewPager projects, I have to temporarily delete a page or two depending on the program requirements and then recreate the pages to the original number when needed again. How is this process handled in the ViewPager? Hiding is better than deleting and recreating.
Thank you for providing support to your libraries for a long time. Your work has been very dependable and reliable for many years.
 
Last edited:

corwin42

Expert
Licensed User
Longtime User

The main difference between the AHViewPager and the new ViewPager is the VPage object.

In AHViewPager you had to create a Panel and add it with PC.AddPage(panel, "Title"). You do not need to create the panel anymore. This is done internally when the VPage object is instantiated. So adding a page ist just PageContainer.AddPage("Title").

The VPage is pushed as a parameter in PageCreated and PageDestroyed events. So accessing the page panel is now a bit cleaner:
B4X:
Sub VP_PageCreated (Position As Int, Page As VPage)
    If Page.AlreadyCreated = False Then
        Page.Panel.LoadLayout("pagelayout")
    End If
End Sub

Previously you had to create a local panel object to convert from Object to Panel:
B4X:
Sub VP_PageCreated (Position As Int, Page As Object)
    Dim p As Panel
    p = Page
 
    p.LoadLayout("pagelayout")
End Sub

Additionally if you wanted to cache the page you had to create a global Array variable which holds if a page has already a loaded layout or not. This can now simply be done with the VPage.AlreadyCreated property. This makes the usage much clearer and simpler.

Adding/Removing pages should be almost the same as in AHViewPager library. In the new ViewPager you have to call PageContainer.DataChanged after adding or removing pages manually to inform the ViewPager object of the change.

Be aware that the new ViewPager does not contain any Tabstrip objects. You should use the DSTabLayout object of DesignSupport library. (It requires DesignSupport Library v2.21 which can be found here)
 
Last edited:

Mahares

Expert
Licensed User
Longtime User
This library is a cleaned up and slightly enhanced version of the AHViewPager library

Running the sample code, I get this error right off the bat:
B4A version: 6.50
Parsing code. (0.00s)
Compiling code. (0.03s)
Compiling layouts code. (0.03s)
Organizing libraries. (3.59s)
Generating R file. Error
C:\Android\Basic4Android\MiscPrograms2016\ViewPagerCorwin42Lib100\NewViewPager\Objects\bin\extra\res3\res\values-v23\values-v23.xml:4: error: Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Inverse'.

C:\Android\Basic4Android\MiscPrograms2016\ViewPagerCorwin42Lib100\NewViewPager\Objects\bin\extra\res3\res\values-v23\values-v23.xml:34: error: Error retrieving parent for item: No resource found that matches the given name 'android:Widget.Material.Button.Colored'.

C:\Android\Basic4Android\MiscPrograms2016\ViewPagerCorwin42Lib100\NewViewPager\Objects\bin\extra\res3\res\values-v24\values-v24.xml:3: error: Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Borderless.Colored'.

C:\Android\Basic4Android\MiscPrograms2016\ViewPagerCorwin42Lib100\NewViewPager\Objects\bin\extra\res3\res\values-v24\values-v24.xml:4: error: Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Colored'.

I have all these installed:
The 3 lib files installed: .jar, xml and aar
DesignSupport Library v2.21 installed
Android Support Repository installed Rev 41
6.50 B4A
SDK 25 , 24 and SDK 23
android-support-v7-appcompat.jar
AppCompat 3.30
 

corwin42

Expert
Licensed User
Longtime User
I have all these installed:
The 3 lib files installed: .jar, xml and aar
DesignSupport Library v2.21 installed
Android Support Repository installed Rev 41
6.50 B4A
SDK 25 , 24 and SDK 23
android-support-v7-appcompat.jar
AppCompat 3.30

Use API25 android.jar (Configure Pathes in B4A IDE).

android-support-v7-appcompat.jar is not needed anymore.
 

Mahares

Expert
Licensed User
Longtime User
Use API25 android.jar (Configure Pathes in B4A IDE)
Thanks Markus. That corrected the problem.
I really liked your original AHViewPager. I hope this will exceed it. When I tested your original AHviewPager example a few years ago the total folder was only 1.4 MB. Now, with this new one the folder size is 6.9 MB. If you go to the device settings and check the size of the small example you provided installed, it shows a very high 11.5 MB. I always have a tendency to shy away from libraries that use many other resources and other libraries and the project balloons. I know devices have gotten faster and the core lib has gotten bigger. Having said all that, I like to try it.
 
Last edited:

corwin42

Expert
Licensed User
Longtime User

The apk sizes for the example are here 1932kB for the new ViewPager version and 1940kB for the AHViewPager version. So they are quite the same. The problem is that the support libraries are getting bigger and bigger.
You can still use AHViewPager if you want but the apps will get bigger with it, too because of the growing support library. The difference between the two ViewPagers is not that big. I just wanted to create a new clean version which has all stuff to create Material Design apps with AppCompat and DesignSupport libraries.
 

gravel

Member
Licensed User
Longtime User
I should perhaps post a general question as this is probably not specifically a ViewPager issue, but ...

I've a 3 page DSTabLayout with an UltimateListView in each of the ViewPager pages. It behaves perfectly with normal scrolling behaviour. But testing abnormal behaviour (fast frequent scrolling) I find I can induce a crash giving an EGL_CONTEXT_LOST during rendering error.

Is this an inherent problem or is there something I can do about it do you think?

The example from the first post will crash with the same error also .. eventually!
 

corwin42

Expert
Licensed User
Longtime User

With which Android version do you get this error?
I don't think that there will be a workaround.
 

gravel

Member
Licensed User
Longtime User
With which Android version do you get this error?
I've tried it on a 6.0.1 device (the one that the log came from - Cyanogenmod) and on a really low end 4.4.4 device.

I don't think that there will be a workaround.

You do have to scroll VERY vigorously to provoke it, but if that is the case then I'll have to reconsider how I do it.
 

wimpie3

Well-Known Member
Licensed User
Longtime User
I have noticed there is some kind of lag between the events SCROLLSTATE_SETTLING and SCROLLSTATE_IDLE. The viewpager has already settled in for about 500ms before SCROLLSTATE_IDLE is called. Is there a way to influence this, like changing the scroll speed?
 

corwin42

Expert
Licensed User
Longtime User
The viewpager has already settled in for about 500ms before SCROLLSTATE_IDLE is called. Is there a way to influence this, like changing the scroll speed?
No, you can't change this.
 

GuyBooth

Active Member
Licensed User
Longtime User

I have been using AHViewPager in one app for several years now without any problems, but when I try to update it to use this new version, I cannot get it to work.
In a simple example (loading by code not from the designer, without the appcompat and other addins in corwin's example), I can make it work. But when I transport the code into my not-simple-at-all app I simply cannot get the _PageCreated event to fire, and therefore cannot move to the next stage of loading a layout into my app.
Exactly what is supposed to cause _Page_Created to fire? What triggers it? I thought it was the PC.Addpage method, but in my app nothing happens.
 

Mashiane

Expert
Licensed User
Longtime User
B4X:
Sub VP_PageCreated (Position As Int, Page As Object)
    Dim p As Panel
    p = Page

    p.LoadLayout("pagelayout")
End Sub

So, this basically means that if you want different layouts per page, you need to detect the position of the layout to add the layout that you want at that position?
 

corwin42

Expert
Licensed User
Longtime User
So, this basically means that if you want different layouts per page, you need to detect the position of the layout to add the layout that you want at that position?

The Signature of the VP_PageCreated is wrong.
It is like this:
B4X:
Sub VP_PageCreated (Position As Int, Page As VPage)
    Log("PageCreated: " & Position)
    If Page.AlreadyCreated = True Then
        Log("Page already created => do nothing")
    Else
        Log("New Page => load the layout")
        'We load a simple layout file here.
        Page.Panel.LoadLayout("pagelayout")
        Page.Panel.Color = Colors.RGB(Rnd(0,256), Rnd(0,256), Rnd(0,256))
        Label1.Text = Page.Title
    End If
End Sub

The second parameter is a VPage object. You can access the pages content panel with Page.Panel as in the above example.

To your question: Yes.
 

roberto64

Active Member
Licensed User
Longtime User
Hi, someone can help me to solve this problem, I created a menu with a ViewPager and PageContainer as an example that I attach, what I would like to do and that once chosen a vice menu you must clean PageContainer and once selected an entry from menu must open another mask.
regards
 

Attachments

  • MemSms.zip
    109.4 KB · Views: 384

ermiakhan

Member
B4X:
B4A Version: 9.80
Java Version: 8
Parsing code.    (0.00s)
Building folders structure.    (0.01s)
Compiling code.    (0.03s)
Compiling layouts code.    (0.03s)
Organizing libraries.    (0.00s)
    (AndroidX SDK)
Generating R file.    Error
d:\7\sdk\sdk\sdk\tools\..\extras\b4a_remote\androidx\appcompat\appcompat\1.1.0\unpacked-appcompat-1.1.0\res\values\values.xml:1722: error: Attribute "icon" has already been defined
d:\7\sdk\sdk\sdk\tools\..\extras\b4a_remote\androidx\appcompat\appcompat\1.1.0\unpacked-appcompat-1.1.0\res\values\values.xml:1929: error: Attribute "fontVariationSettings" has already been defined
d:\7\sdk\sdk\sdk\tools\..\extras\b4a_remote\androidx\appcompat\appcompat\1.1.0\unpacked-appcompat-1.1.0\res\values\values.xml:2597: error: Attribute "iconTint" has already been defined
d:\7\sdk\sdk\sdk\tools\..\extras\b4a_remote\androidx\appcompat\appcompat\1.1.0\unpacked-appcompat-1.1.0\res\values\values.xml:2675: error: Attribute "closeIcon" has already been defined
d:\7\sdk\sdk\sdk\tools\..\extras\b4a_remote\androidx\appcompat\appcompat\1.1.0\unpacked-appcompat-1.1.0\res\values\values.xml:2863: error: Attribute "menu" has already been defined

ideas?
 

Zlgo

Member
Hi
I just want to try example "NewPageExample" but it crash at beginning with this report:

** Activity (main) Create, isFirst = true **
Panel size is unknown. Layout may not be loaded correctly.
Panel size is unknown. Layout may not be loaded correctly.
Error occurred on line: 57 (Main)
java.lang.IllegalStateException: The pager's adapter has to implement ViewPagerTabProvider.
at de.amberhome.viewpager.internal.ViewPagerTabs.setViewPager(ViewPagerTabs.java:157)
at de.amberhome.viewpager.AHViewPagerTabs.Initialize(AHViewPagerTabs.java:30)
at com.viewpager.com.main._activity_create(main.java:427)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
at com.viewpager.com.main.afterFirstLayout(main.java:105)
at com.viewpager.com.main.access$000(main.java:17)
at com.viewpager.com.main$WaitForLayout.run(main.java:83)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
** Activity (main) Resume **

This I run on B4A ver. 9.9
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…