Over the last couple of days I have been investigating the pull to refresh paradigm, and its possible implementation in an Android app.
A quick Google search produces this library from Chris Banes, and this fork from Naver Communications.
They are however for my use cases too complex and not customizable enough for what I want. (I appreciate that they are both extremely customizable.. just not in the ways that I need ;))
The latest versions of the Google support library include the
SwipeRefreshLayout (documentation link) which although 'official' does not do the entirity of what I require. Whilst I could extend and adapt this in-built widget, from playing with the various implementations I had found across the web, I felt that implementing it myself would be the best course of action.
I like knowing exactly what my code does and how it works. Writing it myself allows this.. whilst also removing the bloat of larger overly complex libraries.
What I wanted
I wanted to extend my
ListView so that I could 'pull' down at the top to refresh, and scroll down at the bottom to load more data.
I wanted my actions to be explicit, so unless you pull down enough or scroll down enough the actions wont be executed and the list will animate back.
On a conceptual level what i want to do is:
Have a list header which will contain the refresh control
Have a list footer which will contain the footer control
When the user scrolls the list view, work out if they are scrolling either of these views into view
If they are, on stopping scrolling execute one of the following actions:
- animate the control back off the screen if the user has not scrolled far enough
- animate to the top/bottom of the control respectively, update its display, and begin the background task associated with refreshing/loading more if they have scrolled far enough
If the former, no further action is taken
If the latter, once the background task has completed the control should animate back off the screen
Intriguingly, and somewhat suprisingly there seems to be an extreme lack of commenting across open source code. If you were looking at some of these projects you may be a bit flummoxed as to what a code block is doing and why..
This in my opinion is a real issue within the Android ecosystem whereby API differences mean that many code bases are built in certain ways for the APIs they were targetting at the time.
For example I had a look at this library by erikwt which does some intriguing things with animations for reasons that are not immediately clear..
That said, I am not complaining. Open source is great and I'd rather people share their code than keep it to themselves :)
The main conceptual premises behind the working of this code are as follows:
Is it visible
We determine if the header or footer is visible by utilizing the
getLastVisiblePosition() methods of
ListView and maintaining control state using enumerations.
The ability to scroll past the top/bottom of the list view is achieved by adding top/bottom padding to the respective control views in amounts that are relative to the amount the user has scrolled.
The animation of padding properties is achieved by proxying the padding property of these control views into a form that can be used by an
ObjectAnimator (docs). The docs (here) state that 'The object property that you are animating must have a setter function'. Someone has kindly written a gist which illustrates how you can do this.
Here you go..
I will clean this up and release it as a project at some point. For now I have provided the full source of my
PRListView as a gist.
I apologize for the colloquial language in my comments.. I was basically just outputting my internal dialog. None the less I hope commented code helps you get to grips with the code.
Thanks a lot to the library authors mentioned above whose code influenced the development of this extension.