1. 程式人生 > >android開發遊記:SpringView 下拉重新整理的高效解決方案,定製你自己風格的拖拽頁面

android開發遊記:SpringView 下拉重新整理的高效解決方案,定製你自己風格的拖拽頁面

關於下拉重新整理/上拉載入更多的解決方案網上已經有很多了,瀏覽了目前主流的下拉控制元件比如PullToRefresh庫等,第一:大多數實現庫都難以進行動畫和樣式的自定義。第二:不能很好的相容多種滾動控制元件,它們都對listView、RecyclerView等進行了不同程度的重新實現,你在專案中就得使用庫提供的PullToRefreshListView、PullToRefreshRecyclerView等來代替源生的listView、RecyclerView等,這樣的方式其實並不好,隨著android版本的不斷升級源生的listView、RecyclerView也不斷加入新特性和對之前bug的修改,這使得三方實現的控制元件很難跟上google的節奏,當源生listView已經更新多個版本之後,三方的ListView可能還在使用低版本的實現方式。

基於如上兩個原因,我開始著手開發SpringView(彈性View)

SpringView有哪些優點?

  1. 能對header/footer(頭部/尾部)的樣式和動畫進行高度自定義,單獨將header/footer獨立出來,幾乎可以實現任何你想要的效果,只需要繼承BaseHeader/BaseFooter實現對應介面就可以。

  2. 能動態地替換header/footer,只需要設定不同的頭尾即可:springView.setHeader(MyHeader());

  3. 在不重寫源生控制元件的情況下,完美支援系統源生的listView、RecyclerView、ScrollView、WebView等,你依然使用google提供的官方控制元件,SpringView完全不做乾澀。

  4. 使用簡單,對於簡單的需求甚至不用寫任何程式碼,只需要在佈局中為SpringView設定header=”@layout/…”屬性即可。

  5. SpringView是非常輕量級的實現,提供了非常容易拓展的對外介面

  6. SpringView支援多點觸控,可以兩隻手連續拖拽,你可以定製一些趣味的動畫(例如demo5的仿acfun效果)

  7. SpringView提供了2種拖拽方式(重疊和跟隨),可以動態地切換

  8. SpringView為不想去自定義頭/尾的懶人提供了7種預設的實現(模仿了阿里,騰訊,美團等多種風格)如下,還會繼續增加

DefaultHeader GearHeader

WebHeader AcfunHeader

QQHeader MeituanHeader

AliHeader

如何使用 SpringView?

原始碼及demo下載 gitbub:

下載地址

在佈局檔案中新增SpringView,並把你想要拖拽的控制元件放在SpringView中,給SpringView新增app:header=”@layout/…”屬性,設定一個自己編寫的頭部的佈局即可(footer同理):

    <com.liaoinstan.springview.widget.SpringView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:header="@layout/myheader"
            app:footer="@layout/myfooter">

            <listView
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

     </com.liaoinstan.springview.widget.SpringView>

這樣,最基本的實現就完成了,執行看看吧。

當然,你也可以不再佈局中設定,使用程式碼動態新增:

    //DefaultHeader/Footer是SpringView已經實現的預設頭/尾之一
    //更多還有MeituanHeader、AliHeader、RotationHeader等如上圖7種
    springView.setHeader(new DefaultHeader(this));
    springView.setFooter(new DefaultFooter(this));

重新整理和載入更多的事件處理

如果需要處理的話,只需在程式碼中新增監聽:

springView.setListener(new SpringView.OnFreshListener() {
      @Override
      public void onRefresh() {
      }
      @Override
      public void onLoadmore() {
      }
});

如何自定義一個Header或Footer

詳細的你可以看下幾種預設實現的Header原始碼,這裡只簡單介紹下:

我們要做一個簡單的能夠記錄拖拽了多少次的Header。

首先新建一個自定義頭部佈局,就是在RelativeLayout中放一個TextView啦:

這裡寫圖片描述

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="80dp"
    android:background="@drawable/view_post_comment_bg"
    android:layout_gravity="top">

    <TextView
        android:layout_width="120dp"
        android:gravity="center"
        android:layout_height="wrap_content"
        android:text="this is TextView  "
        android:background="#ff0000"
        android:textColor="#ffffff"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:id="@+id/textView" />
</RelativeLayout>

接著,新建一個MyHeader基礎自BaseHeader:

public class MyHeader extends BaseHeader{
    //獲取Header
    @Override
    public View getView(LayoutInflater inflater, ViewGroup viewGroup) {}

    //拖拽開始前回調
    @Override
    public void onPreDrag(View rootView) {}

    //手指拖拽過程中不斷回撥,dy為拖拽的距離,可以根據拖動的距離新增拖動過程動畫
    @Override
    public void onDropAnim(View rootView, int dy) {}

    //手指拖拽過程中每次經過臨界點時回撥,upORdown是向上經過還是向下經過
    @Override
    public void onLimitDes(View rootView, boolean upORdown) {}

    //拉動超過臨界點後鬆開時回撥
    @Override
    public void onStartAnim() {}

    //頭部已經全部彈回時回撥
    @Override
    public void onFinishAnim() {}
}

註釋已經很清楚了,其中必須實現的方法是getView(),將頭部的View例項返回給SpringView,其餘方法有需求就實現。

實現getView()方法,新增一個成員變數儲存頭部中的TextView:

    private TextView textView;
    @Override
    public View getView(LayoutInflater inflater, ViewGroup viewGroup) {
        View view = inflater.inflate(R.layout.header_my, viewGroup, true);
        textView = (TextView)view.findViewById(R.id.textView);
        return view;
    }

實現onLimitDes方法,在每次經過臨界點時改變TextView的內容:

    private int i = 0;
    @Override
    public void onLimitDes(View rootView, boolean upORdown) {
        i++;
        textView.setText("this is TextView "+i);
    }

OK,在Activity中為SpringView設定我們自定義的MyHeader就可以了,再設定一個監聽器,在重新整理和載入更多的時候等待1秒呼叫onFinishFreshAndLoad()結束重新整理動作。

        springView = (SpringView) findViewById(R.id.springview);
        springView.setHeader(new MyHeader());

        springView.setListener(new SpringView.OnFreshListener() {
            @Override
            public void onRefresh() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        springView.onFinishFreshAndLoad();
                    }
                }, 1000);
            }
            @Override
            public void onLoadmore() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        springView.onFinishFreshAndLoad();
                    }
                }, 1000);
            }
        });

這裡寫圖片描述

這樣就完成了一個簡單的自定義Header,Footer同理。

如何自定義最大下拉高度,臨界高度,和回彈高度

在BaseHeader(BaseFooter同理)中預設已經實現3個方法,分別返回的是臨界高度(limit hight),下拉最大高度(max height),下拉彈動高度(spring height):
如果有更加複雜的需求,需要更改這些高度的話,就在自己的Header中重寫這些方法,註釋已經很清楚了:

public abstract class BaseHeader implements SpringView.DragHander{
    /**
     * 這個方法用於設定當前View的臨界高度(limit hight),即拉動到多少會被認定為重新整理超作,而沒到達該高度則不會執行重新整理
     * 返回值大於0才有效,如果<=0 則設定為預設header的高度
     * 預設返回0
     */
    @Override
    public int getDragLimitHeight(View rootView) {
        return 0;
    }

    /**
     * 這個方法用於設定下拉最大高度(max height),無論怎麼拉動都不會超過這個高度
     * 返回值大於0才有效,如果<=0 則預設600px
     * 預設返回0
     */
    @Override
    public int getDragMaxHeight(View rootView) {
        return 0;
    }

    /**
     * 這個方法用於設定下拉彈動高度(spring height),即彈動後停止狀態的高度
     * 返回值大於0才有效,如果<=0 則設定為預設header的高度
     * 預設返回0
     */
    @Override
    public int getDragSpringHeight(View rootView) {
        return 0;
    }
}

到這裡,SpringView的使用方法基本介紹完了,後面的文章會陸續從原始碼介紹SpringView的實現,和自帶的各種預設Header的實現

下載請移步gitbub:

覺得不錯的話,下面有個贊可以點一下:)