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,093
  • screenshot-1336034966953.png
    screenshot-1336034966953.png
    9.9 KB · Views: 7,347
  • AHViewPager2_21.zip
    39.8 KB · Views: 2,350
  • AHViewPager3_00.zip
    74.9 KB · Views: 2,268
Last edited:

corwin42

Expert
Licensed User
Longtime User
B4X:
Pager.GotoPage(0, True)

Hi, any way to change page transition speed? change too fast on real devices :)

Sorry, no. It is not possible.
There are some (complicated) solutions on StackOverflow how to set the transition speed but I don't think I will add one of them to the library.
 

fishwolf

Well-Known Member
Licensed User
Longtime User
How to replace the list view with table?

i have tried with:

B4X:
Case TYPE_LISTVIEW
       Dim TableIndex As Table
       
       TableIndex.Initialize(Me, "TableIndex", 4)
       TableIndex.SetHeader(Array As String("Col1", "Col2", "Col3", "Col4"))
       TableIndex.SetColumnsWidths(Array As Int(25%x, 25%x, 25%x, 25%x))
   
       For i=0 To 20
         TableIndex.AddRow(1, Array As String(i+1, "aaaaaaaa", " bbbbbbbbb", "cccc"))
       Next
       
       pan.AddView(TableIndex, 0, 0, FILL_PARENT, FILL_PARENT)

but i receive this compile error:

B4X:
pan.AddView(TableIndex, 0, 0, FILL_PARENT, FILL
javac 1.7.0_21
src\de\amberhome\viewpagerexample\main.java:653: error: inconvertible types
_pan.AddView((android.view.View)(_tableindex),(int) (0),(int) (0),_fill_parent,_fill_parent);
  ^
  required: View
  found:  table
1 error
 

corwin42

Expert
Licensed User
Longtime User
How to replace the list view with table?

i have tried with: [...]

Do you use an additional library for the Table? A Table object is not known to B4A by default.
 

corwin42

Expert
Licensed User
Longtime User

You cannot add this class as a view.

Try to add a Panel to the ViewPager and then use Table.AddToActivity(Panel, Left, Top, Width, Height) to add the Table to this Panel.
If this does not work because of a type conflict (Activity<->Panel) then you have to change the table class AddToActivity Sub that it accepts a panel instead of an activity.
 

fishwolf

Well-Known Member
Licensed User
Longtime User
Ok, with
You cannot add this class as a view.

Try to add a Panel to the ViewPager and then use Table.AddToActivity(Panel, Left, Top, Width, Height) to add the Table to this Panel.
If this does not work because of a type conflict (Activity<->Panel) then you have to change the table class AddToActivity Sub that it accepts a panel instead of an activity.
OK, with panel work fine.

Other question:
i need put data into the tables from some http request, one request for each panel.
http request works in asyncron mode.

what is the correct method for write the code?

create each panel and after put the data (how to?)
or
call the http request and after into asyncron callback function, create the panel with the data

?????

Thanks
 

corwin42

Expert
Licensed User
Longtime User
what is the correct method for write the code?

There is no "correct method". It depends on how you want your app behave. Both of your solutions are possible.
 

fishwolf

Well-Known Member
Licensed User
Longtime User
There is no "correct method". It depends on how you want your app behave. Both of your solutions are possible.

I prefer the first method, i think that i see the tab and the header table during the time download

But, how to i can access to table object if the object is defined into function ?
 

ajk

Active Member
Licensed User
Longtime User
Rapid debug do not work with this library (eg. with example file). This is common issue or problem with my computer?
 

ajk

Active Member
Licensed User
Longtime User
I do not get any error. Just device "hangs". I have found "solution" - tried it on newest phone - and works OK.

My post 429 was written after unsuccessful attempts on 5 different "older" devices.

Than you Erel for your fast response!
 

AHilberink

Active Member
Licensed User
Longtime User
Hi,

I have a question. Adding a new tab works fine, but going to the new tab by using GotoPage gives an error:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

My code:
B4X:
Sub NewPage(NaamTab As String)
    container.AddPageAt(CreatePanel(TYPE_Schoen, NaamTab),NaamTab, container.Count)
    'Inform the AHViewPagerTabs object that the data has changed.
    tabs.NotifyDataChange
    'Slide to the new page
    pager.GotoPage(container.Count-1, True)
End Sub

What is going wrong?

Best regards,
André
 

AHilberink

Active Member
Licensed User
Longtime User
Hi again,

I do have another question:
On my tabs I have a ListView. Updating the ListView appears on the last Tab and not on the one currently active.

For example:
I have 4 tabs all having the ListView with different data depending on the tab. I am on Tab2 and add a line to the ListView. The new ListView appears on Tab4 (last tab) and not on the Tab2 (currently active).

Is there something I can do about this?

Best regards,
André
 

corwin42

Expert
Licensed User
Longtime User
Hi,

I have a question. Adding a new tab works fine, but going to the new tab by using GotoPage gives an error:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

My code:
B4X:
Sub NewPage(NaamTab As String)
    container.AddPageAt(CreatePanel(TYPE_Schoen, NaamTab),NaamTab, container.Count)
    'Inform the AHViewPagerTabs object that the data has changed.
    tabs.NotifyDataChange
    'Slide to the new page
    pager.GotoPage(container.Count-1, True)
End Sub
Can you please add the full stack trace and not only the exception. With that information I can't see where the exception is thrown.

On my tabs I have a ListView. Updating the ListView appears on the last Tab and not on the one currently active.
I don't know how you have implemented this. But from what you describe it seems that you have only one reference for the ListViews so updating the ListView with this reference will of course always update the last ListView. You have to store all ListView references in a global variable (Array, List etc.) and update the one you want.
 

AHilberink

Active Member
Licensed User
Longtime User
Can you please add the full stack trace and not only the exception. With that information I can't see where the exception is thrown.


I don't know how you have implemented this. But from what you describe it seems that you have only one reference for the ListViews so updating the ListView with this reference will of course always update the last ListView. You have to store all ListView references in a global variable (Array, List etc.) and update the one you want.

Hi,

Thanks for the quick response. Here the full stack trace:
** Activity (main) Pause, UserClosed = false **
** Activity (addshoe) Create, isFirst = true **
** Activity (addshoe) Resume **
InsertMaps (first query out of 1): INSERT INTO [Schoenen] ([Naam], [Afbeelding], [Actief]) VALUES (?, ?, ?)
** Activity (addshoe) Pause, UserClosed = true **
** Activity (main) Resume **
main_newpage (B4A line: 168)
End Sub
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:1970)
at android.view.ViewGroup.addView(ViewGroup.java:1865)
at android.support.v4.view.ViewPager.addView(ViewPager.java:1304)
at de.amberhome.viewpager.AHPageContainer.instantiateItem(AHPageContainer.java:86)
at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:832)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1016)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:550)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:509)
at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:501)
at de.amberhome.viewpager.AHViewPager.GotoPage(AHViewPager.java:121)
at b4a.RunningShoe.main._newpage(main.java:892)
at b4a.RunningShoe.main._activity_resume(main.java:506)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:187)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:171)
at b4a.RunningShoe.main$ResumeMessage.run(main.java:296)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)

Best regards,
André
 

corwin42

Expert
Licensed User
Longtime User
It seems that the Panel you added to the AHPageContainer is already added to another view. Does CreatePanel really create a new panel. It must not reuse another panel object.
 

Jerez

Active Member
Licensed User
Longtime User
Hi! i'm using smooth transition. Any way to go from page 1 to 10 without passing by 2,3,4,5,6,7,8,9... and then 10? looks like a carousel effect. Please advise! i won't lose the smooth animation transition.

thanks!
 

Kiese

Member
Licensed User
Longtime User
Hi ! I was wondering if there is any way to add pages with different widths or is there a workaround to give such effect or maybe more control over the position of the pages ?
Not too sure if this makes all sense, but what I would like to do is give an impression of piling up some of the pages as the user navigates . (Did that make sense ?)
 

Kiese

Member
Licensed User
Longtime User
I noticed there is a container.getpagewidth(arg0) as int. By any chance is there a way to implement a container.setpagewidth maybe through reflection/javaobject (which are new to me so I don't really know where to begin).
Thanks in advance and many thanks for the great lib! Sure saves a lot of coding time.
 
Top