B4A Library AHViewPager library - Sliding panels now perfect

This library is a B4A implementation of the ViewPager object provided by the compatibility class from google. With this library it is possible to add sliding panels to your apps.

AHPageContainer - This object is a container for the pages of the AHViewPager. You should add Panels to this object.

AHViewPager - This is the main object which provides the sliding panels.

All the Tabs objects are deprecated now. You can use them but I don't enhance them anymore. For nice looking Tabs please use the DSTabLayout object of the DesignSupport library.
Alternatively you can use the TabStripViewPager.


Installation:
  • From V3.00 on the library requires B4A 6.0 or later.
  • This library depends on the Android Support library so you need to install the Android Support repository in the Extras section with SDK Manager.
  • Copy the AHViewPager.xml and AHViewPager.jar files to your additional libraries folder.
Example project:

For an example project for this library see the Design Support Library.

Your support:
Creating libraries and wrappers for existing library projects is a lot of work. The use of this library is totally free and you even don't need to mention in your app that you use it.
But if you use this library in your projects and you think it is useful to you please consider to make a donation:

Thanks very much for your support.

Version History:

1.00:
- initial version

1.01:
- Added AHViewPagerFixedTabs object for a fixed tab indicator
- Fixed a bug that it was impossible to get the canvas of a panel which was added to the container (It was impossible to display charts on a page)
- Example for AHViewPagerFixedTabs tab indicator

1.02: (Never released)
- Fixes problem with tab height (Line is now always on the bottom)

1.03:
- Fixes problem with Line sometimes not updating correctly on Android 4.0+
- Fix UppercaseTitle property

2.0:
- Complete Rewrite of the Swipey tabs code to fix some bugs with newer android versions.

2.01:
- New property for the AHViewPager object: PagingEnabled - Enables or disables paging for the ViewPager.

2.02:
- New events PageScrolled and PageScrollStateChanged (with SCROLLSTATE constants)
See post 227 for details

2.20:
- Use raiseEventfromUI() in most events
- New SupportTabs object
- New SupportTitles object
- Support for Designer (as a Custom View)
- some minor internal changes and bug fixes

2.21:
- Use raiseEvent() for PageCreated and PageDestroyed event again to prevent double UI refreshes
- Added @RaiseSynchronousEvents annotation to GotoPage() (to make it better compatible with rapid debugger.

3.00:
- Support for Designer Custom Properties.
- Uses maven repository to access support library. (B4A 6.0 or later required)

Attention: V2.20 has an API change which makes the ViewPager incompatible with older versions. The AHPageContainer parameter is removed from the Initialize() method. Initialize2() has the old signature. If you use Initialize() (or add the View to the Designer as a custom view) then you have to set the container object with ViewPager.PageContainer = <YourContainer>

The examples use the old Initialize method, so they are broken. I was too lazy to fix them because I recommend the tab indicator from the Design Support library for a nice looking Material Design app.
 

Attachments

  • screenshot-1336034831196.png
    screenshot-1336034831196.png
    10.1 KB · Views: 8,302
  • screenshot-1336034966953.png
    screenshot-1336034966953.png
    9.9 KB · Views: 7,568
  • AHViewPager2_21.zip
    39.8 KB · Views: 2,542
  • AHViewPager3_00.zip
    74.9 KB · Views: 2,497
Last edited:

JakeBullet70

Well-Known Member
Licensed User
Longtime User
I have looked but cannot find it.
Is there anyway to add small icons / bitmaps to the tabs?
 

gjoisa

Active Member
Licensed User
Longtime User
I tried to use the library and followed your instructions . While compiling , I am getting an error message . I am attaching the error message screenshot . I tried your example without modifying . Still getting the same error . Help me .
 

Attachments

  • Error.png
    Error.png
    22.7 KB · Views: 216

corwin42

Expert
Licensed User
Longtime User
I tried to use the library and followed your instructions . While compiling , I am getting an error message . I am attaching the error message screenshot . I tried your example without modifying . Still getting the same error . Help me .

Did you install the .xml and .jar files in your CustomLibs Folder?
 

corwin42

Expert
Licensed User
Longtime User

treehousefrog

Member
Licensed User
Longtime User
Hey, thanks for the great library :-D

I've found that when turning pages there is occasionally a little 'stutter' (about one in every three times). I think this could be to do with the pages getting destroyed and created. Is there any way I could potentially make this smoother? I was thinking I could prevent the pages getting destroyed and created so often (I'm only holding some text and tiny images on them) but I can't find a way to do this...? Do you have any suggestions? Thanks a lot :)

Many thanks and best wishes,

Adam
 

corwin42

Expert
Licensed User
Longtime User
It's hard to tell from where the "stutter" comes.

It depends on device Android version (before 4.0 hardware acceleration is by default off so sliding pages is not so smooth) and your implementation.

I normally do the initialization of a page in the PageCreated event and store in an activity variable (sub globals) if the page is already initialized.
 

ducphu

Active Member
Licensed User
Longtime User
Hi all,

I looked at the example and see that
B4X:
Activity.AddView(tabs, 0, 0, FILL_PARENT, WRAP_CONTENT)

Then
B4X:
Activity.AddView(line, 0, 35dip, Activity.Width, 2dip)

May I know why we choose 35dip? I want to put the line just below the tabs. I tried
B4X:
Activity.AddView(line, 0, tabs.Height, Activity.Width, 2dip)
but it doesnt work. Maybe because of WRAP_CONTENT.

Then I'm thinking of change WRAP_CONTENT to let say 5%y. But then the tabs' title is not at the centre. I cant find .Gravity property. Is there any solution for this ?
 

corwin42

Expert
Licensed User
Longtime User
Setting the tabs height is really tricky because the line is not always at the bottom of the tabs view. In xml you always use wrap_content and the container for the tabs just has the correct height. This is not really possible with B4A.

I don't have an overall solution for this. I'm thinking about a rework of this library with updated tabs code. Hopefully it will work better, then.
 

Xardoz

Member
Licensed User
Longtime User
Update: Resolved
Typo: Button1.Initialize("Button2")


Still learning B4A, love this libary, but I am trying to add controls to panel through code.

Can not find a clear example (For me anyways :) )

I am trying to add button2 to the first panel

B4X:
Sub Activity_Create(FirstTime As Boolean)

    'Add a Button at the bottom of the page for jumping directly to a page.
    Button1.Initialize("Button1")
    Button1.Gravity = Gravity.CENTER
    Activity.AddView(Button1, 88dip, Activity.Height - 44dip, Activity.Width - 88dip - 88dip, 40dip)

    'Initialize the panels we use for the pages and put them in the container
    container.Initialize
    'For i = 0 To 3
    Dim pan As Panel
    '
    '    pan = CreatePanel("Page " & i)
    '    container.AddPage(pan,"Page " & i)
    '    gPageNumber = i+1
    'Next
    pan = CreatePanel("Times" )
        container.AddPage(pan, "Times")
        Button1.Initialize("Button2")
        Button2.Gravity = Gravity.CENTER
        pan.AddView(Button2,88dip, Activity.Height - 44dip, Activity.Width - 88dip - 88dip, 40dip)
    pan = CreatePanel("Parts" )
        container.AddPage(pan,"Parts")
    pan = CreatePanel("Notes" )
        container.AddPage(pan,"Notes")
    gPageNumber =3

    'Now we have a container with our panels just add it to the pager object
    pager.Initialize(container, "Pager")

    'As we want to show the tabs page indicator, we initialize it
    fixedTabs.Initialize(pager)
    'fixedTabs.TextSize = 8
    'fixedTabs.TextColor = Colors.Cyan
    'fixedTabs.LineColor = Colors.Green
    'fixedTabs.LineColorSelected = Colors.Red
    'fixedTabs.LineHeightSelected = 2dip
    'fixedTabs.LineHeight = 8dip
    fixedTabs.UpperCaseTitle = True
    Activity.AddView(fixedTabs, 0, 0, 100%x, 60dip)

    'Now we can add the pager to the activity
    Activity.AddView(pager, 0, 60dip, Activity.Width, Activity.Height-108dip)
    SetButtonText

    'Add some menus for adding and removing pages
    Activity.AddMenuItem("Add new Page", "NewPage")
    Activity.AddMenuItem("Delete current Page", "DeletePage")
End Sub

** Activity (main) Pause, UserClosed = false **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Page created 0
Page created 1
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Page created 0
Page created 1
** Activity (main) Pause, UserClosed = false **
** Activity (main) Create, isFirst = true **
java.lang.RuntimeException: Object should first be initialized (Button).
Did you forget to call Activity.LoadLayout?
at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:46)
at anywheresoftware.b4a.objects.TextViewWrapper.setGravity(TextViewWrapper.java:55)
at de.amberhome.viewpagerexample.main._activity_create(main.java:303)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:174)
at de.amberhome.viewpagerexample.main.afterFirstLayout(main.java:98)
at de.amberhome.viewpagerexample.main.access$100(main.java:16)
at de.amberhome.viewpagerexample.main$WaitForLayout.run(main.java:76)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5059)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
at dalvik.system.NativeStart.main(Native Method)
java.lang.RuntimeException: Object should first be initialized (Button).
Did you forget to call Activity.LoadLayout?
** Activity (main) Pause, UserClosed = false **
 
Last edited:

korn

Member
Licensed User
Longtime User
i am using imagetouchview over different pages of ahviewpager. the vertical touch responds to imagetouchview, but horizontal touch action changes pages of ahviewpager.

is it possible to only allow touch action from edges of the screen, to change pages of ahviewpager. just similar to ahnavigationdrawer.
 

corwin42

Expert
Licensed User
Longtime User
i am using imagetouchview over different pages of ahviewpager. the vertical touch responds to imagetouchview, but horizontal touch action changes pages of ahviewpager.

is it possible to only allow touch action from edges of the screen, to change pages of ahviewpager. just similar to ahnavigationdrawer.

No, thats not possible.
 

AHilberink

Active Member
Licensed User
Longtime User
Hi,

Great Job!! Is it possible to use your sliding on a TabHost instead of the Activity itselves?

Best regards,
André
 

corwin42

Expert
Licensed User
Longtime User

alexwekell

Member
Licensed User
Longtime User
How do I continuously check for what the current panel is? I want to change a label to different text once the panel is changed.
 

Mahares

Expert
Licensed User
Longtime User
B4X:
Dim pager As AHViewPager

Sub Pager_PageChanged (Position As Int)     'for AHviewPager
  If Position = 0  then   
    Label1.text="Alex"
  Else
    Label1.text="wekell"
  End if
End Sub
 

alexwekell

Member
Licensed User
Longtime User
B4X:
Dim pager As AHViewPager

Sub Pager_PageChanged (Position As Int)     'for AHviewPager
  If Position = 0  then 
    Label1.text="Alex"
  Else
    Label1.text="wekell"
  End if
End Sub

Tried that, doesn't seem to change my text correctly:

B4X:
Sub pager_pagechanged (Position As Int)
    Log ("Page Changed to " & Position)
  
    CurrentPage = Position
  
    If Position = 1 Then
    stepslabel.Text = "2. Place the heel of one hand on the victim's breastbone, exactly between the nipples."
    Else If Position = 2 Then
    stepslabel.Text = "3. Place your second hand on top of the first hand, palm-down."
    End If
End Sub

B4X:
  'This creates a page of the given type
Sub CreatePanel(PanelType As Int, Title As String) As Panel
    Dim pan As Panel
    Dim pi As PanelInfo
  
    pi.Initialize
    pi.LayoutLoaded = False
    pi.PanelType = PanelType

    pan.Initialize("")
    Select PanelType
        Case TYPE_LISTVIEW

stepslabel.Initialize("")

SetNinePatchDrawable(stepslabel, "label_bg")
stepslabel.Typeface = RobotoLight
stepslabel.Text = "1. Place the victim on his or her back. Make sure he or she is lying as flat as possible - this will prevent injury while you're doing chest compressions."
pan.AddView(stepslabel, 10dip, 30%y, 100%x-20dip,  40%y-10dip)

          
      
    End Select
  
    pan.Tag = pi
    Return pan
End Sub

The only text changed was in position 4 to this text:

B4X:
"3. Place your second hand on top of the first hand, palm-down."
 

Mahares

Expert
Licensed User
Longtime User
I tried the below code on one of my AHviewpager projects and it works the way it is supposed to as demonstrated by the log:
B4X:
Sub Pager_PageChanged (Position As Int)
    If Position = 1  Then  
       stepslabel.Text = "2. Place the heel of one hand on the victim's breastbone, exactly between the nipples."    
       Log(stepslabel.Text)
    End If
    If Position=2 Then
      stepslabel.Text = "3. Place your second hand on top of the first hand, palm-down."
       Log(stepslabel.Text)
    End If
End Sub
If this is not what you are after, perhaps Corwin42 (Markus) or someone else can straighten both of us out.
 

alexwekell

Member
Licensed User
Longtime User
I tried the below code on one of my AHviewpager projects and it works the way it is supposed to as demonstrated by the log:
B4X:
Sub Pager_PageChanged (Position As Int)
    If Position = 1  Then 
       stepslabel.Text = "2. Place the heel of one hand on the victim's breastbone, exactly between the nipples."   
       Log(stepslabel.Text)
    End If
    If Position=2 Then
      stepslabel.Text = "3. Place your second hand on top of the first hand, palm-down."
       Log(stepslabel.Text)
    End If
End Sub
If this is not what you are after, perhaps Corwin42 (Markus) or someone else can straighten both of us out.

Nope, formatted it like yours and it didn't work, however the log is confirming that the panels are changing:

B4X:
Sub pager_pagechanged (Position As Int)
    Log ("Page Changed to " & Position)
   
    stepslabel.Text = ("")
    CurrentPage = Position
   
    If Position = 1 Then
    stepslabel.Text = "2. Place the heel of one hand on the victim's breastbone, exactly between the nipples."
    End If
   
    If Position = 2 Then
    stepslabel.Text = "3. Place your second hand on top of the first hand, palm-down."
    End If
   
End Sub

Log:

B4X:
LogCat connected to: B4A-Bridge: LGE Nexus 5-358239053304616
--------- beginning of /dev/log/main
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Service (service1) Create **
** Service (service1) Start **
Connected to B4A-Bridge (Wifi)
** Activity (main) Pause, UserClosed = false **
** Activity (main) Create, isFirst = false **
** Activity (main) Resume **
WakeLock already held.
** Activity (main) Pause, UserClosed = false **
** Activity (main) Create, isFirst = false **
** Activity (main) Resume **
WakeLock already held.
** Activity (main) Pause, UserClosed = false **
Installing file.
PackageAdded: package:com.EmergencyDirect.SOS
** Activity (main) Create, isFirst = true **
Index time: 177 ms (141 Items)
(Main, 156) FullScreen or IncludeTitle properties in layout file do not match the activity attributes settings. (warning #1004)
** Activity (main) Resume **
map ready
Page created 0
Page created 1
Page Changed to 1
Page created 2
Page Changed to 2
Page destroyed 0
Page created 3
Page Changed to 3
Page destroyed 1
Page created 4
Page Changed to 4
Page destroyed 2
Page Changed to 3
Page created 2
Page Changed to 2
Page created 1
Page destroyed 4
Page Changed to 1
Page created 0
Page destroyed 3
** Activity (main) Pause, UserClosed = false **
** Activity (main) Resume **
Installing file.
** Activity (main) Pause, UserClosed = false **
sending message to waiting queue (CallSubDelayed - HeartBeat)
sending message to waiting queue (CallSubDelayed - HeartBeat)
sending message to waiting queue (CallSubDelayed - HeartBeat)
sending message to waiting queue (CallSubDelayed - HeartBeat)
sending message to waiting queue (CallSubDelayed - HeartBeat)
sending message to waiting queue (CallSubDelayed - HeartBeat)
sending message to waiting queue (CallSubDelayed - HeartBeat)
sending message to waiting queue (CallSubDelayed - HeartBeat)
PackageAdded: package:com.EmergencyDirect.SOS
** Activity (main) Create, isFirst = true **
Index time: 181 ms (141 Items)
(Main, 156) FullScreen or IncludeTitle properties in layout file do not match the activity attributes settings. (warning #1004)
** Activity (main) Resume **
map ready
Page created 0
Page created 1
Page Changed to 1
Page created 2
Page Changed to 2
Page destroyed 0
Page created 3
Page Changed to 3
Page destroyed 1
Page created 4
Page Changed to 4
Page destroyed 2
Page Changed to 3
Page created 2
Page Changed to 2
Page created 1
Page destroyed 4
Page Changed to 1
Page created 0
Page destroyed 3
Page Changed to 2
Page destroyed 0
Page created 3
Page Changed to 3
Page destroyed 1
Page created 4
Page Changed to 4
Page destroyed 2
Page Changed to 3
Page created 2
Page Changed to 2
Page created 1
Page destroyed 4
Page Changed to 1
Page created 0
Page destroyed 3
Page Changed to 0
Page destroyed 2
Page Changed to 1
Page created 2
Page Changed to 2
Page destroyed 0
Page created 3
Page Changed to 3
Page destroyed 1
Page created 4
Page Changed to 4
Page destroyed 2
Page Changed to 3
Page created 2
Page Changed to 2
Page created 1
Page destroyed 4
Page Changed to 1
Page created 0
Page destroyed 3
Page Changed to 0
Page destroyed 2
Page Changed to 1
Page created 2
Page Changed to 2
Page destroyed 0
Page created 3
running waiting messages (8)
** Activity (main) Resume **
 

AHilberink

Active Member
Licensed User
Longtime User
Hi,

I need to do an action on change of the page.
Sub Pager_PageChanged (Position As Int) is called after the change: The new page is already active.

My use:
I put information from a SQL database on a page. I want to write this information back once the user changes to the next page.

Is there something like "Sub Pager_PageLeave" so I can use the fields of the leaving page to write to my database?

Does anyone has a solution?

Best regards,
André
 
Top