B4A Library [class] Modified CustomListView with "Pull to refresh" feature

Erel

Administrator
Staff member
Licensed User
Update: New version based on xCustomListView: https://www.b4x.com/android/forum/threads/b4x-xcustomlistview-pull-to-refresh.94015/

This class is a modified version of CustomListView. It adds a "pull to refresh" feature.

upload_2016-8-14_18-41-41.png

When the user pull down the panel a refresh event is fired. You should catch this event and update the list as necessary. In this example a timer is used to simulate a long operation.

Notes:
- You should call clv.AddTopPanel after you add the items with the top panel layout.
- If the list is too short for the scroll view to be scrollable then a "dummy" item will be added as the last item.
- You should call StopRefresh after the update.
 

Attachments

Last edited:

Informatix

Expert
Licensed User
I wanted to do a tutorial a few months ago on the pull-to-refresh and other techniques used for lists, but the legal situation was not very clear. There was apparently a patent on the pull-to-refresh belonging to Twitter, which had abruptly stopped my intent. Now things are more clear. From a legal point of view, we will not be allowed very soon to use it without authorization but Twitter is not Apple and it doesn't seem interested in suing people. I think there's nothing serious to fear actually but I prefer to warn everyone tempted to include it in his/her application. Source.
 
Last edited:

Erel

Administrator
Staff member
Licensed User
@Informatix, I did some searches about this issue:

1. Twitter has an internal agreement with its engineers about using their patents only for defensive purposes: Twitter introduces Innovators Patent Agreement, vows to not abuse patent system
2. There are thousands of iOS and Android applications that use this feature. Including Facebook and other popular apps.
3. There are many frameworks for both iOS and Android that implement this feature.

I'm not a lawyer but I don't see any reason not to use this feature.

If anyone wishes to further discuss this issue then please start a new thread.
 

Informatix

Expert
Licensed User
I don't want to start a new thread for that because I have only one thing to say on the subject: "read my source", which is recent and written by a specialist.
 

nwhitfield

Active Member
Licensed User
_Refresh event triggered

This seems to work pretty well on the whole, but for some reason I'm occasionally seeing the Refresh event triggered, even if the screen is not touched.
 

Erel

Administrator
Staff member
Licensed User
If you can please try to reproduce it and post the steps.
 

nwhitfield

Active Member
Licensed User
I've not yet managed to find a consistent pattern, despite throwing in some extra logging; it was obvious something was triggering the refresh - my app shows a list of calendar events for the next 30 days, retrieved from a server, and I used the refresh to fetch the complete list, for the whole year.

Sometimes, shortly after fetching the 30 day list, it would update with the whole thing.

I'm using the same CustomListView and simply calling the Clear method when I retrieve a new set of data from the server.

I've now added

B4X:
TopPanelVisible = False
TopPanelRefreshing = False
to the end of Public Sub Clear in the CustomListView and I think that's done the trick.
 

Erel

Administrator
Staff member
Licensed User
I see how it can happen. I will update the code. The change is:
B4X:
Public Sub Clear
   StopRefresh
   items.Clear
   panels.Clear
   sv.Panel.RemoveAllViews
   sv.Panel.Height = 0
End Sub
 
  • Like
Reactions: eps

nwhitfield

Active Member
Licensed User
Thanks.

Another quirk; most of the time, I can deal with the object that is returned by ItemClick, but if I want to delete it (and for some other operations), I need the index. That, it appears, is not always consistent.

I have my clv, dataList, and I've popped in this bit of code:

B4X:
Sub dataList_ItemClick( index As Int, Value As Object )

   Log("Clicked on item " & index)
plus some extra log items to tell me when a refresh is triggered. The particular list I noticed this on had only one element, but the logging shows it's happening with more.

I start the app, tap on the item in the list, and it has an index of 0, as I'd expect.

But if I then trigger the refresh event, after which my code calls dataList_Clear, and the refills the clv, clicking on that first item returns an index of 1 (which, consequently, calls other things to fail).

Should I instead be re-initialising the clv, rather than simply calling Clear when I need to reload it?
 

Erel

Administrator
Staff member
Licensed User
While the index doesn't appear to be consistent it is probably the correct index. When the TopPanel is added (even if it is not visible) it is added in index 0.
 

nwhitfield

Active Member
Licensed User
It's the correct index for the clv, but there can still be quirks.

For example, if I retrieve a list of messages in my app, I store them in a normal list, and display them in the clv. I can come back to the same list from elsewhere, without having to reload from the server, eg on an orientation change.

But, when a user wants to locally delete a message, via the clv, where I would previously use the clv remove item method and then delete the matching index from my original list of messages, I can't do that, as sometimes I'll be deleting the wrong item, if the indices no longer match.

I can work round it, by iterating over my original list and checking for the message id element to find the matching one, but it's a quirk that might catch other people out, if they're doing something similar, especially copying a list into a clv, so I thought it worth mentioning.
 

Erel

Administrator
Staff member
Licensed User
You will need to understand the module code and modify it to change the item location.
 

Gentry

Member
Licensed User
Is it expected that the refresh is only executed if the list is scrolled 1st? For short list that do not always expand beyond the clv panel/view length, I've been unable to get the pull to refresh to fire, as I am unable to scroll the list contents, which seems to be a prerequisite.

Also, is there a way to disable the refresh function, to minimize excessive refreshing? I know I could bypass in the _refresh code, but is there a way to disable (and re-enable) the function, to avoid showing the Refresh Panel at all?

Excellent Addition to functionality!

Thanks,
Gentry
 

Erel

Administrator
Staff member
Licensed User
See the notes in the first post.

Also, is there a way to disable the refresh function, to minimize excessive refreshing? I know I could bypass in the _refresh code, but is there a way to disable (and re-enable) the function, to avoid showing the Refresh Panel at all?
Not without modifying the code.
 

Gentry

Member
Licensed User
Thanks. I also had to graft the Sub DesignerCreateView() function into this version to get it to allow the CustomListView to be used in the Designer. For anyone else running into that.

Gentry
 

Devv

Active Member
Licensed User
hi
i have a project that i used the normall customlistview

i replaced the class withe the pull to refresh code
then i added the pulltorefresh.pal
and added

B4X:
    Dim p As Panel
    p.Initialize("")
    p.LoadLayout("PullToRefresh")
   
    clv.AddTopPanel(p, 50dip)

but im getting this error

** Activity (main) Pause, UserClosed = false **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **

main_rss_finished (java line: 640)
java.lang.Exception: Sub designercreateview was not found.
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:175)
at anywheresoftware.b4a.objects.CustomViewWrapper.AfterDesignerScript(CustomViewWrapper.java:67)
at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:158)
at anywheresoftware.b4a.objects.ActivityWrapper.LoadLayout(ActivityWrapper.java:209)
at anywheresoftware.b4a.samples.customlistview.main._rss_finished(main.java:640)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
at anywheresoftware.b4a.BA$2.run(BA.java:328)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
java.lang.Exception: Sub designercreateview was not found.
Panel size is unknown. Layout may not be loaded correctly.
any ideas ?
 
Top