This is a story about how to get a working implementation of Pull to refresh under Android. No code examples at all. A few pictures and at the end of the article link to the project archive.
Recently there was a need to embed Pull to refresh into the current application. This is now fashionable, users are used to, and for twitter clients has already become the standard. Search for ready-made solutions on the network brought to the only option - the open-source project
Johan Nilsson android-pulltorefresh on Github.

')
Header is inserted into the ListView, which is hidden if necessary. The solution is working, but very crooked. Often hangs in any condition. If there are few elements in the list and they do not occupy the entire space allocated for the ListView, then the Header is not hidden, and the inscription is changed to Tap to refresh. The logical limitation of this implementation. Another feature was discovered when this project was added to the production application. Since Pull to refresh is a Header, the setSelection (1) method is often executed to hide the Header. And since we use saving and restoring positions, then of course the constant call to setSelection spoils us all.
At first they decided to modify this implementation, correct the most unpleasant moments. Even built into one project. But it didn’t work out the way I wanted, the limitations of using Header affected.
There was an idea how to do it differently and free time appeared. Once the problem is in Header, it means that you need to remove it and put Pull to refresh View and ListView itself into one LinearLayout and move it. Ideally, I wanted to get the same Pull to refresh as in the official Twitter client. But they use another bunch. Pull to refresh is smooth and works well everywhere. In general, a lot of time spent watching the work of the official Twitter-client.
Options that and how to move a lot. You can move and Pull to refresh View, and ListView, and LinearLayout. You can move by changing the Padding, Margin or ScrollTo. After a large number of experiments on the emulator and on real devices, the most optimal combination was found. The initial shift is done by changing the Padding to the height of Pull to refresh View, so we hide it from the screen. And then we move the whole Layout by changing the ScrollTo.
It turned out beautifully and as smoothly as possible. But there was a problem, at that time seemingly insurmountable. For some reason, when the Layout was shifted, everything started to jump. Coordinates came lower and higher, and there was no way to fix it. Almost did not even return to the original plan - to finalize Pull to refresh by Johan Nilsson.
But then, as if by magic, another project hit my eyes.
Alternative Pull To Refresh from guillep on the same Github. It works even worse than with Johan Nilsson, but uses a completely different mechanism, similar to our idea. And most importantly, there is a problem with jumping Layout. Take the last three coordinates and calculate the average. This ensures smoothness.

We took a bit of each project, everything was combined, and it turned out well-working Pull to refresh, but the loading state remained unfinished. After releasing Release to refresh turns into Loading and in this state it should scroll with the list, so it should be part of the ListView. A separate Pull to refresh View should disappear, and Pull to refresh View in the Loading state should be added to the ListView.
Since our View must constantly appear and disappear in the ListView, you cannot use it as a Header. But I also do not want to change the current adapters. It is necessary that when adding Pull to refresh to the working draft, there should be as few changes as possible. We decided to use a special Adapter inside Pull to refresh as a Decorator. And this adapter controls the presence of a special View in the Loading state.

There were many problems, especially when added to the working draft, but they all successfully resolved. In the end, it turned out to be a class that can replace the usual ListView and which implements a well-functioning Pull to refresh. It works great on all APIs starting from version 1.5.
Only on some Samsung devices with a converted ListView, there are sometimes problems. But there are already ideas how and what can be redone.
Project on github .