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,092
  • screenshot-1336034966953.png
    screenshot-1336034966953.png
    9.9 KB · Views: 7,346
  • AHViewPager2_21.zip
    39.8 KB · Views: 2,349
  • AHViewPager3_00.zip
    74.9 KB · Views: 2,265
Last edited:

M6SOFT

Member
Licensed User
Longtime User
Thank You for great library.
I have one question. As i understand ViewPager internally managed pages in memory. The default setting will store 1 page either side of the current page. I have 4 pages and need to keep all.
Is it possible to set pager.setOffscreenPageLimit(4)?
 

Inman

Well-Known Member
Licensed User
Longtime User
Will it be possible for you to implement an option to get the Container, from a Pager? Something like pager.getContainer()?

I will explain the need. In a project I am working on, the entire ViewPager needs to be declared locally. The Pager is added to a panel and then at a later stage, within a function, this panel is made available. I can get the Pager from the panel using panel.GetView(0). But I am not sure how to get the Container from the Pager.

Can this be done?

EDIT:

Ok I found a workaround, which was to store the Container in Pager.tag. I was worried that you might be using pager's tag property for some internal purpose but thankfully that was not the case and this works well.

Is this the only possible way?
 
Last edited:

corwin42

Expert
Licensed User
Longtime User
Thank You for great library.
I have one question. As i understand ViewPager internally managed pages in memory. The default setting will store 1 page either side of the current page. I have 4 pages and need to keep all.
Is it possible to set pager.setOffscreenPageLimit(4)?

Should be possible with reflection:

B4X:
Sub SetOffscreenLimit(Pager As Object, Value As Int)
    Dim r As Reflector
   
    r.Target = Pager
    r.Target = r.RunMethod("getObject")
    r.RunMethod4("setOffscreenPageLimit", Array As Object(Value), Array As String("java.lang.int"))
End Sub

I haven't tested the above code but it should work.
 

corwin42

Expert
Licensed User
Longtime User
Ok I found a workaround, which was to store the Container in Pager.tag. I was worried that you might be using pager's tag property for some internal purpose but thankfully that was not the case and this works well.

Is this the only possible way?

Looks like a good solution. It would be possible with reflection, too but it would be much more complicated.
 

sdujolo

Member
Licensed User
Longtime User
I can´t get Sub ChkBoxClearTag_CheckedChange(Checked As Boolean) to work. The Sub btnAddUser_Click and Sub btnDelRow_Click is working.
ChkBoxClearTag.Initialize("")
pan.AddView(ChkBoxClearTag, 85%x - 50dip, 100%y - 70dip, 100dip, 40dip)
ChkBoxClearTag.Text = "Clear Tag"

btnDelRow.Initialize("btnDelRow")
pan.AddView(btnDelRow, 50%x - 50dip, 100%y - 70dip, 100dip, 40dip)
btnDelRow.Text = "Delete user"
btnAddUser.Initialize("btnAddUser")
pan.AddView(btnAddUser, 15%x - 50dip, 100%y - 70dip, 100dip, 40dip)
btnAddUser.Text = "New user"
 

shashkiranr

Active Member
Licensed User
Longtime User
Hi Corwin,

How do you get the page numbers by inputting the titles of the page. I am checking if page already exists by using the title, but after this i am not able to move to the respective page which has the title since i do not know the page number.

Kindly let me know your inputs.

Regards,
Shashi Kiran
 

corwin42

Expert
Licensed User
Longtime User
You can loop over all pages that are added so far to the AHPageContainer.
For a AHPageContainer PC you can do the following:

B4X:
For i = 0 To PC.Count - 1
   Log("Pagetitle: " & PC.GetTitle(i)
Next
 

ernschd

Active Member
Licensed User
Longtime User
Hello,

i created a layout with the designer and i wanted to use it with this lib.
Here's the code (which is working fine):
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Dim Pan(5) As Panel
    For i = 0 To 5           
        Pan(i).Initialize("")   
        Pan(i).LoadLayout("myLayout")
        container.AddPageAt(Pan(i), "Title " & i, i)
        eText.Hint = "Number " & i
    Next    

    pager.Initialize(container, "Pager")   
    tabs.Initialize(pager)
    tabs.LineHeight = 5dip
    tabs.UpperCaseTitle = True
    Activity.AddView(tabs, 0dip, 0dip, 100%x, 100%y)
    Activity.AddView(pager, 0dip, 35dip, Activity.Width, Activity.Height - 35dip)   
   
    pager.CurrentPage = 0
End Sub

Now i like to insert text in the EditText (eText), but it's only filled the View in the last panel.
Also the Click-Events for all Views on all pages except the last one aren't working.
Is there a easy way to work with layouts? Or do i have to create the Views as an Array?
 

ernschd

Active Member
Licensed User
Longtime User
As far i'am able to work with the EditText with the Sender object.
But there's still the problem that i can't get the State of an inserted Label.

So i tried to use the reflection library:
B4X:
Sub Globals
    Dim reflect As Reflector
    Dim lblTest As Label
End Sub
                     
Sub Activity_Create(FirstTime As Boolean)
    Dim Pan(5) As Panel
    For i = 0 To 5       
        Pan(i).Initialize("")
        Pan(i).LoadLayout("myLayout")
        container.AddPageAt(Pan(i), "Title " & i, i)
        eText.Hint = "Number " & i
     
        lblTest.Initialize("lblTest")
        lblTest.Color = Colors.Blue
        lblTest.Text = "Test" & i
        lblTest.Tag = i
        Pan(i).AddView(lblTest, 10dip, 10dip, 200dip, 300dip)
        reflect.Target = lblTest
        reflect.SetOnClickListener("lblTest_Click")
    Next 

    pager.Initialize(container, "Pager")
    tabs.Initialize(pager)
    tabs.LineHeight = 5dip
    tabs.UpperCaseTitle = True
    Activity.AddView(tabs, 0dip, 0dip, 100%x, 100%y)
    Activity.AddView(pager, 0dip, 35dip, Activity.Width, Activity.Height - 35dip)

    pager.CurrentPage = 0
End Sub

Sub lblTest_Click
    Log("lblTest_Click")
End Sub


But when i click on the created label, i get a exception:
java.lang.Exception: Sub lbltest_click signature does not match expected signature.

What's wrong with my code?

EDIT (Solved):
I forgot the viewtag in the OnClick-Event:
B4X:
Sub lblTest_Click(lblTest1 As Object)
    Log("lblTest_Click")
End Sub
 
Last edited:

klaus

Expert
Licensed User
Longtime User
I don't think that your code does work properly.
You should put Dim lblTest As Label inside the For / Next Loop !
And then :
B4X:
Sub lblTest_Click
    Dim lbl As Label
    lbl = Sender
    Select lbl.Tag
    Case "0"
    Case "1"
  .
    End Select
End Sub
You don't need:
B4X:
reflect.Target = lblTest
reflect.SetOnClickListener("lblTest_Click")
 

ernschd

Active Member
Licensed User
Longtime User
I want to insert an EditText and a Label in the For / Next Loop.

Now i have a Sub EditText_EnterPressed, where i have to get a Value from the Label,
and a Sub Label_Click, where i have to use the EditText.Text (reading and writing).
 
Top