There’s always some crap to start with

Pull-up, load, and pull-down refresh interactions exploded a long time ago. If you’ve been around android development for a couple of years now, you’ve probably heard of the PullToRefreshListView framework. It’s easy to use, thanks to the great authors, but it’s a bit too big for beginners, with too many classes and methods. The customization is too complex and, I have to say, the framework has a lot of limitations when it comes to reuse. At the end of the day, it’s just a ListView, and there are all sorts of problems when you use it with other sliders, and the authors of the framework haven’t maintained it in years. I tried to find a replacement on Git, and luckily I found this one. Although he is very old, I still use and maintain his code. Android-ultra-pull-to-refresh, also thanks To Liaohuqiu for contributing such an excellent work. I’m used to calling this framework Ptr, and as to why I still recommend it, let me explain:

  • First of all, it’s not a ListView and it’s not a GridView, it’s a ViewGroup. What does that mean? It means that your entire ViewGroup can be pulled down, you can put anything in your ViewGroup, TextView, Button, ListView, RecycleView, it’s not limited, I’m just a ListView, in short, pull down this action, No controls are bound, it is independent. I give full marks for this merit.
  • Fully abstracted decouple, we can define our own refresh styles, as long as the unified interface is implemented, customizing your style is not that difficult, typical object-oriented thinking.
  • There are relatively few classes. You say that’s also a strength? I say this is a big advantage, the class is few code is easy to read, the core class is concentrated, modification and customization will be very easy.

So he has no faults? B: of course!

  • Maybe this is not a disadvantage, in the open source project published by the author, there is no support for pull-up to load more functions, as to why, the author has commented in his issues, generally meaning: pull-down refresh and load more functions, not the same level of functionality. Loading more should not be implemented by UltraPTR, but by Content itself. It doesn’t matter that the author has another open source library that does just that, and in this article, we put it all together!
  • Author source code implementation is the use of ListView, here we will change to RecycleView, after all, to keep pace with The Times!
  • Also in sliding nesting, there is the problem of collisions. It doesn’t matter. I’ve already solved some of that in the code.

What do you get by reading this article?

I will not parse the source code of the author, after all, there are already many wheels on the Internet, it is shameful to duplicate the wheel. The process of modifying the source code will not be explained, why? Because it was fixed a long time ago, and now I have forgotten the specific process… Ha! Ha! Sorry, in this article I will try my best to show the structure and use of the framework to help you better understand the advantages of Ptr. The idea is the most important, not the code!

Let’s get to work

GIF I show the pull-up load, pull-down refresh, standard, full function, empty View five cases. This is just to show you, in fact, when we use it, we don’t really need to switch between different situations. There are only two styles of headers defined in the project, the first is similar to the MaterialDesign style in GIF, and the second is a traditional style similar to the PullToRefreshListView style, which is not shown here.

I. Usage guide

1. Layout use

 <com.leinyo.superptrwithrv.widget.ptr.PullToRefreshView
        android:id="@+id/pull_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:ptr_refresh_mode="none"
        app:ptr_scrollable="true"
        />Copy the code

Here is no nonsense, explain the meaning of attributes:

<declare-styleable name="PullToRefreshView">
        <attr name="ptr_refresh_mode" format="enum">
            <enum name="none" value="0"/>
            <enum name="pull_from_start" value="1"/>
            <enum name="pull_from_end" value="2"/>
            <enum name="both" value="3"/>
        </attr>
        <attr name="ptr_check_login" format="boolean"/>
        <attr name="ptr_header_mode" format="enum">
            <enum name="material" value="0"/>
            <enum name="normal" value="1"/>
        </attr>
        <attr name="ptr_padding_left" format="integer"/>
        <attr name="ptr_padding_right" format="integer"/>
        <attr name="ptr_scrollable" format="boolean"/>
    </declare-styleable>Copy the code
  • Ptr_refresh_mode Refresh mode None Standard RecycleView pull_FROm_START Pull-down refresh pull_FROM_END Pull-up load both pull-up load pull-down refresh
  • Ptr_check_login Whether to check login status Only login (this code implements itself) triggers the drop-down refresh function
  • Ptr_header_mode drop down refresh header styles shown in material GIF normal standard mode
  • Ptr_padding_left ptr_padding_right Sets the padding of RecycleView
  • Ptr_scrollable Specifies whether to display scroll bars

2. The refresh action corresponds to a callback

Drop down to refresh the corresponding callback interface:

public interface OnPullRefreshListener {
        void onPullRefresh();
    }Copy the code

The onPullRefresh() method will call back after the refresh animation reaches a threshold. Cancel pull-down drawing method:

 public void onPullRefreshComplete() {
        mPtrFrameLayout.refreshComplete();
    }Copy the code

Pull-up load corresponding callback interface:

public interface OnLoadMoreListener {
        void onLoadMoreRefresh();
    }Copy the code

Cancel pull up drawing method:

    public void onLoadMoreComplete(boolean hasMore) {
        mLoadMoreRecyclerViewContainer.loadMoreFinish(hasMore);
    }Copy the code

Boolean indicates whether the pull-up can continue false does not call onLoadMoreRefresh() again!!

Both corresponding callback interface:

 public interface OnRefreshListener {
        void onPullRefresh();

        void onLoadMoreRefresh();
    }Copy the code

Cancel all animation methods:

  public void onLoadComplete(boolean hasMore) {
        mLoadMoreRecyclerViewContainer.loadMoreFinish(hasMore);
        if (mCurrentRefreshMode == REFRESH_FROM_START) {
            if(isRefreshing()) { mPtrFrameLayout.refreshComplete(); }}}Copy the code

3. Add EmptyView

If the data we return is empty, we need to display an empty page. We don’t need to control the show and gone of two views, ListView can do the same thing. mPullView.addEmptyView(mEmpty); Note: The addEmptyView method cannot be set before the display, otherwise the empty View will be displayed first. Why? We’ll talk about that later.

4. Add a header HeadView

We can do the same thing with ListView. mPullView.addHeaderView(mHeadView);

Second, the architecture level

This part must be the picture above, it’s all unintentional.

You’d better know something about Ptr in this part

  • PtrFrameLayout is the outermost ViewGroup, which is only responsible for the drop-down refresh. If the first touch event meets the drop-down logic, the header layout will be displayed, otherwise the event will be distributed down
  • LoadMoreRecyclerViewContainer second ViewGroup, only responsible for loading, listening in on events, logical, informed RecyclerView Foot layout drawing.
  • The last layer of RecyclerView, I am only responsible for display layout, including Head, EmptyView, Foot and normal data layout.

How’s that? Is one picture clear enough? See now do you already admire the author’s design ability? Click to refresh and load more, not at the same level. Loading more should not be implemented by UltraPTR, but by Content itself. Each level corresponds to its own business logic and does not care what others are doing. This is called single responsibility, decoupling.

Speaks the most thought is supposed to be here, but I write this, found that was nothing to say, if you really saw source of Ptr, believe you also have no doubt, here and have a kind of refreshing feeling, in fact is so simple, code design is very important, and this is why some code to let a person look very cool, some code to let a person see the vomiting

Three, display layout

RecyclerView is responsible for display layout. Of course, it can be given to Adapter, use RecyclerView.Adapter getItemViewType(int Position). Things to keep in mind: We extract the base class BaseRefreshAdapter, which has some basic operations on multiple layout displays that need to be subclassed, OnCreateHolder (ViewGroup parent, int viewType) onCreateViewHolder(ViewGroup parent, int viewType) Int viewType) and onBindHolder(VH holder, int position), In subclasses you only need to worry about your own Item layout, leaving the rest to the logic in the BaseRefreshAdapter. There is a generic definition, look at the source code is easy to understand. It’s easy to understand why the addEmptyView method can’t be set before displaying the layout, because if you initialize the addEmptyView method, then when the Adapter is initialized, the onCreateViewHolder() method will be executed, This will display the EmptyView immediately, and the data layout will not be refreshed until the data you really need is returned.

At the end, there will be some nonsense

I did not focus on how to explain how to package, how to modify source RecyclerView, also did not open source to explain the principle of Ptr, also hope we can understand, time is a little tight, and a lot of wheels, do not want to recreate. I hope if you see the end, this article will be helpful to you, you also get a support for a variety of functions, RecyclerView based packaging Ptr framework (feel good around the word), as for why called SuperPtr, pure shatter is for fun… If you are in the process of using, have questions and improvement comments welcome to contact me. SupterPtr thank you very much for your support, like to invite you star oh ~~