下拉刷新框架SpringView的使用

SpringView

Github

android開發(fā)游記:SpringView 下拉刷新的高效解決方案,定制你自己風格的拖拽頁面

SpringView 是一個提供了上下拖拽的功能組件,能夠進行高度自定義,實現(xiàn)各種下拉\上拉動畫效果,demo里實現(xiàn)了:仿阿里旅行、仿美團,仿QQ下拉刷紅包,仿acfun等,完全兼容源生控件如ListView、RecyclerView、ScrollView、WebView等,使用簡單,輕易定制自己風格的拖拽頁面。

SpringView 單獨將頭部/尾部獨立出來,幾乎可以實現(xiàn)任何你想要的效果,只需要繼承BaseHeader(或Footer)實現(xiàn)接口

SpringView 能在運行時動態(tài)地替換頭部/尾部,只需要設置不同的頭尾即可:springView.setHeader(MyHeader());

SpringView 支持多點觸控,可以兩只手連續(xù)拖拽,你可以定制一些非常有趣的效果(例如demo5)

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

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

SpringView 支持和 AppBarLayout 聯(lián)動

如何使用 SpringView

依賴

dependencies {

   //SpringView核心庫 (只包含DefaultHeader/Footer)
   implementation 'com.liaoinstan.springview:library:1.7.0'

   //以下是各個風格的Header/Footer,選擇自己喜歡的引入
   implementation 'com.liaoinstan.springview:AcfunHeader:1.7.0'         //AcFun風格 (header and footer)
   implementation 'com.liaoinstan.springview:AliHeader:1.7.0'           //阿里旅行風格 (header and footer)
   implementation 'com.liaoinstan.springview:MeituanHeader:1.7.0'       //美團風格 (header and footer)
   implementation 'com.liaoinstan.springview:RotationHeader:1.7.0'      //齒輪機械風格 (header and footer)
   implementation 'com.liaoinstan.springview:WeixinHeader:1.7.0'        //微信小程序header(只有header)
   implementation 'com.liaoinstan.springview:DuHeader:1.7.0'            //'毒'App header(只有header)
}

在布局文件中添加SpringView,注意SpringView和ScrollView有同樣的限制:只能有一個子元素:

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

            <ListView RecyclerView ScrollView or others
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

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

當然,你也可以不在布局中設置header\footer,使用代碼動態(tài)添加:

springView.setHeader(new DefaultHeader(this));
springView.setFooter(new DefaultFooter(this));

添加監(jiān)聽

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

基本使用:配合RecyclerView和默認頭部和底部DefaultHeader,DefaultFooter

<?xml version="1.0" encoding="utf-8"?>
<com.liaoinstan.springview.widget.SpringView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/springView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".my.MyDemo1Activity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager">

    </androidx.recyclerview.widget.RecyclerView>


</com.liaoinstan.springview.widget.SpringView>
public class MyDemo1Activity extends AppCompatActivity {

    private SpringView mSpringView;

    private RecyclerView mRecyclerView;

    private List<String> mDatas = new ArrayList<>();

    private RvAdapter mRvAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_demo1);

        mSpringView = (SpringView) findViewById(R.id.springView);
        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);

        //拖拽類型
        //OVERLAP 重疊
        //FOLLOW  跟隨
        //DRAG    拖拽
        //SCROLL  滾動
        mSpringView.setType(SpringView.Type.FOLLOW);

        //設置header/footer
        mSpringView.setHeader(new DefaultHeader(this));
        mSpringView.setFooter(new DefaultFooter(this));


        mRvAdapter = new RvAdapter(this, mDatas);
        mRecyclerView.setAdapter(mRvAdapter);

        loadData();

        mSpringView.setListener(new SpringView.OnFreshListener() {
            @Override
            public void onRefresh() {
                new Handler().postDelayed(() -> {
                    loadData();
                    Toast.makeText(MyDemo1Activity.this, "下拉刷新", Toast.LENGTH_SHORT).show();
                    mSpringView.onFinishFreshAndLoad();
                }, 1000);
            }

            @Override
            public void onLoadmore() {

                new Handler().postDelayed(() -> {
                    loadMore();
                    Toast.makeText(MyDemo1Activity.this, "上拉加載", Toast.LENGTH_SHORT).show();
                    mSpringView.onFinishFreshAndLoad();
                }, 1000);
            }
        });

    }

    private void loadData() {
        mDatas.clear();
        for (int i = 1; i <= 30; i++) {
            mDatas.add("趙麗穎" + i);
        }
        mRvAdapter.notifyDataSetChanged();
    }

    private void loadMore() {
        for (int i = 1; i <= 10; i++) {
            mDatas.add("趙麗穎更多" + i);
        }
        mRvAdapter.notifyDataSetChanged();
    }
}

在ScrollView中使用:可以自定義頭部和底部布局文件

<?xml version="1.0" encoding="utf-8"?>
<com.liaoinstan.springview.widget.SpringView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/springView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:footer="@layout/default_footer"
    app:header="@layout/default_header">

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:background="#68b3f3"
                android:gravity="center"
                android:text="TextView1"
                android:textColor="#ffffff" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:background="#ff0"
                android:gravity="center"
                android:text="TextView2"
                android:textColor="#ffffff" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:background="#0f0"
                android:gravity="center"
                android:text="TextView3"
                android:textColor="#ffffff" />


        </LinearLayout>

    </androidx.core.widget.NestedScrollView>


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

public class MyDemo2Activity extends AppCompatActivity {

    private SpringView mSpringView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_demo2);

        mSpringView = (SpringView) findViewById(R.id.springView);

        mSpringView.setListener(new SpringView.OnFreshListener() {
            @Override
            public void onRefresh() {
                new Handler().postDelayed(() -> {
                    Toast.makeText(MyDemo2Activity.this, "下拉刷新", Toast.LENGTH_SHORT).show();
                    mSpringView.onFinishFreshAndLoad();
                }, 2000);
            }

            @Override
            public void onLoadmore() {

                new Handler().postDelayed(() -> {
                    Toast.makeText(MyDemo2Activity.this, "上拉加載", Toast.LENGTH_SHORT).show();
                    mSpringView.onFinishFreshAndLoad();
                }, 2000);
            }
        });
    }
}

在ListView中使用:配合齒輪機械風格頭部和底部

       <com.liaoinstan.springview.widget.SpringView
            android:id="@+id/springview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ffffff">

            <ListView
                android:id="@+id/list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="#f9f9f9"
                android:divider="@null" />

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

RotationHeader:齒輪機械風格

springView.setHeader(new RotationHeader());
springView.setFooter(new RotationFooter());

在RecyclerView中使用:配合阿里旅行風格頭部和底部

        <com.liaoinstan.springview.widget.SpringView
            android:id="@+id/springview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ffffff">

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recycle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="#ffffff"
                android:scrollbars="vertical" />

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

AliHeader:阿里旅行風格

  springView.setHeader(new AliHeader(this, R.drawable.ali, true));   //參數(shù)為:logo圖片資源,是否顯示文字
  springView.setFooter(new AliFooter(this, false));

在WebView中使用:自定義頭部布局文件

       <com.liaoinstan.springview.widget.SpringView
            android:id="@+id/springview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#797a7d"
            app:header="@layout/header_web"
            app:type="overlap">

            <WebView
                android:id="@+id/webView"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

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

header_web.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="top|center_horizontal">

    <LinearLayout
        android:orientation="vertical"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="網(wǎng)頁由 github.com 提供"
            android:id="@+id/textView2"
            android:textColor="#b2b2b2"
            android:textSize="12sp"
            android:layout_gravity="center_horizontal" />

        <TextView
            android:layout_marginTop="5dp"
            android:layout_width="match_parent"
            android:gravity="center"
            android:layout_height="wrap_content"
            android:textColor="#b2b2b2"
            android:text="已啟用QQ瀏覽器X5內(nèi)核"
            android:textSize="12sp"
            android:id="@+id/textView3"
            android:layout_gravity="center_horizontal" />
    </LinearLayout>
</LinearLayout>

自己編寫的頭部和底部的布局

  <com.liaoinstan.springview.widget.SpringView
        android:id="@+id/springView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:footer="@layout/my_footer"
        app:header="@layout/my_header">
  </androidx.core.widget.NestedScrollView>

my_header

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:gravity="center"
    android:layout_height="70dp">

    <ProgressBar
        android:id="@+id/default_header_progressbar"
        android:layout_width="30dp"
        android:layout_height="30dp" />

    <TextView
        android:id="@+id/default_header_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="下拉刷新"
        android:textColor="#777777" />

</LinearLayout>

my_footer

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:orientation="horizontal"
    android:gravity="center"
    android:layout_height="50dp">

        <ProgressBar
            android:id="@+id/default_footer_progressbar"
            android:layout_width="30dp"
            android:layout_height="30dp" />

        <TextView
            android:id="@+id/default_footer_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#777777"
            android:text="加載更多" />

</LinearLayout>

AcfunHeader:AcFun風格

springView.setHeader(new AcFunHeader(this, R.drawable.acfun_header));
springView.setFooter(new AcFunFooter(this, R.drawable.acfun_footer));

Drag Header

簡單定制的QQ新年刷紅包效果,可以在此基礎上自己增加動畫特效,這里只是模擬出該效果框架進行演示,故該Header不放在library里面。

具體使用看官方案例。

public class Demo6Activity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {

    private SpringView springView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo6);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        ((RadioGroup) findViewById(R.id.group_header)).setOnCheckedChangeListener(this);

        springView = findViewById(R.id.springview);
        springView.setListener(new SpringView.OnFreshListener() {
            @Override
            public void onRefresh() {
                //如果當前設置的頭部是QQHeader,則不finish
                if (springView.getHeader() instanceof QQHeader) return;
                new Handler().postDelayed(() -> springView.onFinishFreshAndLoad(), 1000);
            }

            @Override
            public void onLoadmore() {
                new Handler().postDelayed(() -> springView.onFinishFreshAndLoad(), 1000);
            }
        });
        springView.setHeader(new QQHeader().setMovePara(1.5f));     //設置拖拽系數(shù)(值越大,移動越慢)
        springView.setFooter(new DefaultFooter(this, R.drawable.progress_small));
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        switch (checkedId) {
            case R.id.drag_header:
                springView.setHeader(new QQHeader());
                break;
            case R.id.nomal_header:
                springView.setHeader(new DefaultHeader(this));
                break;
        }
    }
}

MeituanHeader,MeituanFooter:美團風格

public class Demo7Activity extends AppCompatActivity {

    private SpringView springView;

    //下拉過程動畫
    private int[] pullAnimSrcs = new int[]{R.drawable.mt_pull, R.drawable.mt_pull01, R.drawable.mt_pull02, R.drawable.mt_pull03, R.drawable.mt_pull04, R.drawable.mt_pull05};
    //刷新中動畫
    private int[] refreshAnimSrcs = new int[]{R.drawable.mt_refreshing01, R.drawable.mt_refreshing02, R.drawable.mt_refreshing03, R.drawable.mt_refreshing04, R.drawable.mt_refreshing05, R.drawable.mt_refreshing06};
    //加載更多底部動畫
    private int[] loadingAnimSrcs = new int[]{R.drawable.mt_loading01, R.drawable.mt_loading02};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo7);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        springView = findViewById(R.id.springview);
        springView.setListener(new SpringView.OnFreshListener() {
            @Override
            public void onRefresh() {
                new Handler().postDelayed(() -> springView.onFinishFreshAndLoad(), 2000);
            }

            @Override
            public void onLoadmore() {
                new Handler().postDelayed(() -> springView.onFinishFreshAndLoad(), 2000);
            }
        });
        springView.setHeader(new MeituanHeader(this, pullAnimSrcs, refreshAnimSrcs));
        springView.setFooter(new MeituanFooter(this, loadingAnimSrcs));
    }
}

SpringView不會和水平滑動有沖突,側(cè)滑刪除試試


        RecyclerView recyclerView = findViewById(R.id.recycle);
        recyclerView.setHasFixedSize(true);
        RecyclerAdapter recyclerAdapter = new RecyclerAdapter(mDatas);
        recyclerView.setAdapter(recyclerAdapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new MyItemTouchCallback(recyclerAdapter));
        itemTouchHelper.attachToRecyclerView(recyclerView);

具體使用看官方案例。

TabLayout+ViewPager+Fragment+CoordinatorLayout+CollapsingToolbarLayout

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".demo9.Demo9Activity">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="250dp"
                android:scaleType="centerCrop"
                android:src="@drawable/bk_test"
                app:layout_collapseMode="parallax" />

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay"
                app:title="Demo9Activity" />

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffffff"
        android:orientation="vertical"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabIndicatorColor="#5793e6"
            app:tabIndicatorHeight="1dp"
            app:tabSelectedTextColor="#5793e6"
            app:tabTextColor="#665793e6"
            tools:background="#33ff0000" />

        <!--app:tabTextAppearance="@style/TabLayoutTextStyle"-->

        <androidx.viewpager.widget.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />

    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

具體使用看官方案例。

給header和footer設置為DRAG模式

//給header和footer設置為DRAG模式
springView.setHeader(new MeituanHeader(this, pullAnimSrcs, refreshAnimSrcs).setType(SpringView.Type.DRAG));
springView.setFooter(new MeituanFooter(this, loadingAnimSrcs).setType(SpringView.Type.DRAG));
image.png

SpringView 現(xiàn)在支持在內(nèi)部嵌套布局了(在下拉的頭部中嵌套一些布局)

具體使用看官方案例。

實現(xiàn)類似于微信下拉 拉出小程序列表

具體使用看官方案例。

SpringView新增了SCROLL模式,基于這種模式可以實現(xiàn)自動加載等效果,下拉到底部實現(xiàn)自動加載

具體使用看官方案例。

springView.setHeader(new AliHeader(this));
springView.setFooter(new AutoFooter());

DuHeader風格

下拉刷新后彈出:為你更新20條新內(nèi)容。

image.png
    <com.liaoinstan.springview.duheader.TopBarFrameLayout
        android:id="@+id/top_bar_frame_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <com.liaoinstan.springview.widget.SpringView
            android:id="@+id/springview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ffffff">

            <ScrollView
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/text"
                        android:layout_width="match_parent"
                        android:layout_height="200dp"
                        android:background="#ffffff"
                        android:gravity="center"
                        android:text="We are in ScrollView"
                        android:textColor="#cccccc" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="200dp"
                        android:background="#ECECF0"
                        android:gravity="center"
                        android:text="這是一個仿'毒'APP的效果"
                        android:textColor="#333333"
                        android:textSize="12sp" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="200dp"
                        android:background="#ffffff" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="200dp"
                        android:background="#ECECF0" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="200dp"
                        android:background="#ffffff" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="200dp"
                        android:background="#ECECF0" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="200dp"
                        android:background="#ffffff" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="200dp"
                        android:background="#ECECF0" />

                </LinearLayout>
            </ScrollView>

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

    </com.liaoinstan.springview.duheader.TopBarFrameLayout>
       topBarFrameLayout = findViewById(R.id.top_bar_frame_layout);
        springView = findViewById(R.id.springview);
        springView.setListener(new SpringView.OnFreshListener() {
            @Override
            public void onRefresh() {
                new Handler().postDelayed(() -> {
                    //0.5秒后再結(jié)束header刷新動畫(模仿'毒'的延遲,大概0.5秒左右)
                    springView.onFinishFreshAndLoadDelay(500);
                    //開始展開topBar頂部提示,并在2.5秒回自動收回
                    topBarFrameLayout.setTopBarText("為你更新20條新內(nèi)容");
                    topBarFrameLayout.showAndHideDelay(2500);
                }, 2000);
            }

            @Override
            public void onLoadmore() {
                new Handler().postDelayed(() -> springView.onFinishFreshAndLoad(), 2000);
            }
        });
        springView.setHeader(new DuHeader());

具體使用看官方案例。

如何自定義一個Header或Footer

新建一個MyHeader基礎自BaseHeader:

public class MyHeader extends BaseHeader {

    private TextView textView;

    private int i = 0;

    /**
     * 獲取Header
     *
     * @param inflater
     * @param viewGroup
     * @return
     */
    @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;
    }

    /**
     * 即將開始拖拽時的回調(diào),可進行初始化操作
     */

    @Override
    public void onPreDrag(View rootView) {
        super.onPreDrag(rootView);
    }


    /**
     * 手指拖拽過程中不斷回調(diào),dy為拖拽的距離,可以根據(jù)拖動的距離添加拖動過程動畫
     *
     * @param rootView
     * @param dy       拖動距離,下拉為+,上拉為-
     */
    @Override
    public void onDropAnim(View rootView, int dy) {

    }

    /**
     * 手指拖拽過程中每次經(jīng)過臨界點時回調(diào),upORdown是向上經(jīng)過還是向下經(jīng)過
     *
     * @param rootView
     * @param upORdown 是上拉還是下拉 true(上),false(下)
     */
    @Override
    public void onLimitDes(View rootView, boolean upORdown) {
        //實現(xiàn)onLimitDes方法,在每次經(jīng)過臨界點時改變TextView的內(nèi)容:
        i++;
        textView.setText("松開刷新" + i);
    }

    /**
     * 拉動超過臨界點后松開時回調(diào)
     */
    @Override
    public void onStartAnim() {
        textView.setText("正在刷新");
    }

    /**
     * 頭部已經(jīng)全部彈回時回調(diào)
     */
    @Override
    public void onFinishAnim() {
        textView.setText("下拉刷新");
    }

}

mSpringView.setHeader(new MyHeader());

這樣就完成了一個簡單的自定義Header,F(xiàn)ooter同理。

自定義頭部Gif圖片

public class GifHeader extends BaseHeader {

    private GifDrawable mGifDrawable;

    private ViewGroup.LayoutParams mLp;

    private int mLoadingW = 0, mLoadingH = 0;

    private GifImageView mGifImageView;

    private Context mContext;

    public GifHeader(Context context) {
        mContext = context;
    }

    /**
     * 獲取Header
     *
     * @param inflater
     * @param viewGroup
     * @return
     */
    @Override
    public View getView(LayoutInflater inflater, ViewGroup viewGroup) {
        View view = inflater.inflate(R.layout.gif_header, viewGroup, true);
        mGifImageView = view.findViewById(R.id.gif_second);

        mGifDrawable = (GifDrawable) mGifImageView.getDrawable();

        mLoadingW = dip2px(mContext, 238f);
        mLoadingH = dip2px(mContext, 120f);
        mLp = mGifImageView.getLayoutParams();

        return view;
    }

    /**
     * 即將開始拖拽時的回調(diào),可進行初始化操作
     */

    @Override
    public void onPreDrag(View rootView) {
        super.onPreDrag(rootView);
        mGifDrawable.stop();
    }


    /**
     * 手指拖拽過程中不斷回調(diào),dy為拖拽的距離,可以根據(jù)拖動的距離添加拖動過程動畫
     *
     * @param rootView
     * @param dy       拖動距離,下拉為+,上拉為-
     */
    @Override
    public void onDropAnim(View rootView, int dy) {
        if (dy > 238f) {
            changeLoadingWH(1);
        } else if (dy <= 238f) {
            changeLoadingWH(dy / 238f);
        }
    }

    /**
     * 手指拖拽過程中每次經(jīng)過臨界點時回調(diào),upORdown是向上經(jīng)過還是向下經(jīng)過
     * 實現(xiàn)onLimitDes方法,在每次經(jīng)過臨界點時改變TextView的內(nèi)容:
     *
     * @param rootView
     * @param upORdown 是上拉還是下拉 true(上),false(下)
     */
    @Override
    public void onLimitDes(View rootView, boolean upORdown) {

    }

    /**
     * 拉動超過臨界點后松開時回調(diào)
     */
    @Override
    public void onStartAnim() {
        mGifDrawable.start();
    }

    /**
     * 頭部已經(jīng)全部彈回時回調(diào)
     */
    @Override
    public void onFinishAnim() {
        mGifDrawable.reset();
        mGifDrawable.stop();
    }

    /**
     * 這個方法用于設置當前View的臨界高度(limit hight),即拉動到多少會被認定為刷新超作,而沒到達該高度則不會執(zhí)行刷新
     * 返回值大于0才有效,如果<=0 則設置為默認header的高度
     * 默認返回0
     */
    @Override
    public int getDragLimitHeight(View rootView) {
        return 200;
    }

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

    /**
     * 這個方法用于設置下拉彈動高度(spring height),即彈動后停止狀態(tài)的高度
     * 返回值大于0才有效,如果<=0 則設置為默認header的高度
     * 默認返回0
     */
    @Override
    public int getDragSpringHeight(View rootView) {
        return 450;
    }

    private void changeLoadingWH(float fraction) {
        mLp.width = (int) (mLoadingW * fraction);
        mLp.height = (int) (mLoadingH * fraction);
        mGifImageView.setLayoutParams(mLp);
    }


    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="horizontal"
    tools:ignore="MissingDefaultResource">


    <pl.droidsonroids.gif.GifImageView
        android:id="@+id/gif_second"
        android:layout_width="238dp"
        android:layout_height="120dp"
        android:src="@drawable/refresh_header3"
        android:layout_gravity="center" />

</LinearLayout>

自定義Footer

public class MyFooter extends BaseFooter {

    private Context context;
    private int rotationSrc;
    private TextView footerTitle;
    private ProgressBar footerProgressbar;

    public MyFooter(Context context) {
        this(context, R.drawable.progress_small);
    }

    public MyFooter(Context context, int rotationSrc) {
        this.context = context;
        this.rotationSrc = rotationSrc;
    }

    @Override
    public View getView(LayoutInflater inflater, ViewGroup viewGroup) {
        View view = inflater.inflate(R.layout.default_footer, viewGroup, true);
        footerTitle = (TextView) view.findViewById(R.id.default_footer_title);
        footerProgressbar = (ProgressBar) view.findViewById(R.id.default_footer_progressbar);
        footerProgressbar.setIndeterminateDrawable(ContextCompat.getDrawable(context, rotationSrc));
        return view;
    }

    @Override
    public void onPreDrag(View rootView) {
    }

    @Override
    public void onDropAnim(View rootView, int dy) {
    }

    /**
     * 手指拖拽過程中每次經(jīng)過臨界點時回調(diào),upORdown是向上經(jīng)過還是向下經(jīng)過
     *
     * @param rootView
     * @param upORdown 是上拉還是下拉 true(上),false(下)
     */
    @Override
    public void onLimitDes(View rootView, boolean upORdown) {
        if (upORdown) {
            footerTitle.setText("松開載入更多");
        } else {
            footerTitle.setText("查看更多");
        }
    }

    @Override
    public void onStartAnim() {
        footerTitle.setVisibility(View.INVISIBLE);
        footerProgressbar.setVisibility(View.VISIBLE);
    }

    @Override
    public void onFinishAnim() {
        footerTitle.setText("查看更多");
        footerTitle.setVisibility(View.VISIBLE);
        footerProgressbar.setVisibility(View.INVISIBLE);
    }
}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="10dp" >

        <ProgressBar
            android:id="@+id/default_footer_progressbar"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_centerInParent="true"
            android:visibility="invisible" />

        <TextView
            android:id="@+id/default_footer_title"
            android:gravity="center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:textColor="#777777"
            android:text="加載更多" />
    </RelativeLayout>

</LinearLayout>

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

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

public abstract class BaseHeader implements SpringView.DragHander{
    /**
     * 這個方法用于設置當前View的臨界高度(limit hight),即拉動到多少會被認定為刷新超作,而沒到達該高度則不會執(zhí)行刷新
     * 返回值大于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),即彈動后停止狀態(tài)的高度
     * 返回值大于0才有效,如果<=0 則設置為默認header的高度
     * 默認返回0
     */
    @Override
    public int getDragSpringHeight(View rootView) {
        return 0;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容