Android下拉刷新组件—PullToRefresh

来源:互联网 发布:node读文件 promise 编辑:程序博客网 时间:2024/06/04 17:53

介绍

这里写图片描述
下拉刷新,几乎是每个 Android 应用都会需要的功能。 android-Ultra-Pull-To-Refresh (以下简称 UltraPTR )便是一个强大的 Andriod 下拉刷新框架。
主要特点:
(1).继承于 ViewGroup , Content 可以包含任何 View 。
(2).简洁完善的 Header 抽象,方便进行拓展,构建符合需求的头部。
PullToRefresh是一套实现非常好的下拉刷新库,它支持:

ListView
ExpandableListView
GridView
WebView
ScrollView
HorizontalScrollView
ViewPager

点击查看Github
源码分析

PullToRefreshListView使用

这里写图片描述

1.下载项目包,将library包导入即可,其他的包暂时不用
2.分析源码,看我们可以设置的有哪些

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="PullToRefresh">        <!-- 设置刷新view的背景 -->        <attr name="ptrRefreshableViewBackground" format="reference|color" />        <!-- 设置头部view的背景 -->        <attr name="ptrHeaderBackground" format="reference|color" />        <!-- 设置头部/底部文字的颜色 -->        <attr name="ptrHeaderTextColor" format="reference|color" />        <!-- 设置头部/底部副标题的文字颜色 -->        <attr name="ptrHeaderSubTextColor" format="reference|color" />        <!-- 设置下拉刷新的模式,有多重方式可选。无刷新功能,从顶部刷新,从底部刷新,二者都有,只允许手动刷新 -->        <attr name="ptrMode">            <flag name="disabled" value="0x0" />            <flag name="pullFromStart" value="0x1" />            <flag name="pullFromEnd" value="0x2" />            <flag name="both" value="0x3" />            <flag name="manualOnly" value="0x4" />            <!-- 这两个属性不推荐了,用上面的代替即可 -->            <flag name="pullDownFromTop" value="0x1" />            <flag name="pullUpFromBottom" value="0x2" />        </attr>        <!-- 是否显示指示箭头 -->        <attr name="ptrShowIndicator" format="reference|boolean" />        <!-- 指示箭头的图片 -->        <attr name="ptrDrawable" format="reference" />        <!-- 顶部指示箭头的图片,设置后会覆盖ptrDrawable中顶部的设置 -->        <attr name="ptrDrawableStart" format="reference" />        <!-- 底部指示箭头的图片,设置后会覆盖ptrDrawable中底部的设置 -->        <attr name="ptrDrawableEnd" format="reference" />        <attr name="ptrOverScroll" format="reference|boolean" />        <!-- 设置文字的基本字体 -->        <attr name="ptrHeaderTextAppearance" format="reference" />        <!-- 设置副标题的基本字体 -->        <attr name="ptrSubHeaderTextAppearance" format="reference" />        <!-- 设置下拉时标识图的动画,默认为rotate -->        <attr name="ptrAnimationStyle">            <flag name="rotate" value="0x0" />            <flag name="flip" value="0x1" />        </attr>        <!-- 设置刷新时是否允许滚动,一般为true -->        <attr name="ptrScrollingWhileRefreshingEnabled" format="reference|boolean" />        <!-- 允许在listview中添加头/尾视图 -->        <attr name="ptrListViewExtrasEnabled" format="reference|boolean" />        <!-- 当设置rotate时,可以用这个来设置刷新时旋转的图片 -->        <attr name="ptrRotateDrawableWhilePulling" format="reference|boolean" />        <!-- BELOW HERE ARE DEPRECEATED. DO NOT USE. -->        <attr name="ptrAdapterViewBackground" format="reference|color" />        <attr name="ptrDrawableTop" format="reference" />        <attr name="ptrDrawableBottom" format="reference" />    </declare-styleable></resources>

设置Mode

PullToRefreshListView mListView = (PullToRefreshListView) findViewById(R.id.list_view);  mListView.setMode(Mode.BOTH);  

Mode.BOTH:同时支持上拉下拉
Mode.PULL_FROM_START:只支持下拉Pulling Down
Mode.PULL_FROM_END:只支持上拉Pulling Up

3.开始用它建立自己的工程

设置布局文件

就是插入PullToRefreshListView

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="${relativePackage}.${activityClass}"     android:background="#000000"><!--     The PullToRefreshListView replaces a standard ListView widget. -->    <com.handmark.pulltorefresh.library.PullToRefreshListView        xmlns:ptr="http://schemas.android.com/apk/res-auto"        android:id="@+id/pull_refresh_list"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:cacheColorHint="#000000"        android:divider="#19000000"        android:dividerHeight="4dp"        android:fadingEdge="none"        android:fastScrollEnabled="false"        android:footerDividersEnabled="false"        android:headerDividersEnabled="false"        android:smoothScrollbar="true"         ptr:ptrAnimationStyle="rotate"        ptr:ptrHeaderTextColor="#ffffff"        ptr:ptrHeaderSubTextColor="#00ffff"        ptr:ptrHeaderBackground="@null"        ptr:ptrDrawable="@drawable/ic_launcher"/></RelativeLayout>

开始编写代码

1.找到这个控件,并且设置监听器

这里面用到了一个日期的工具类,其实就是设置上次下拉的时间的。此外在下拉后会触发一个异步任务

package com.kale.ptrlistviewtest;import java.util.Arrays;import java.util.LinkedList;import android.app.Activity;import android.os.Bundle;import android.text.format.DateUtils;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.Toast;import com.handmark.pulltorefresh.library.PullToRefreshBase;import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;import com.handmark.pulltorefresh.library.PullToRefreshBase.OnLastItemVisibleListener;import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;import com.handmark.pulltorefresh.library.PullToRefreshBase.State;import com.handmark.pulltorefresh.library.PullToRefreshListView;import com.handmark.pulltorefresh.library.extras.SoundPullEventListener;public class MainActivity extends Activity {    //一个可以下拉刷新的listView对象    private PullToRefreshListView mPullRefreshListView;    //普通的listview对象    private ListView actualListView;    //添加一个链表数组,来存放string数组,这样就可以动态增加string数组中的内容了    private LinkedList<String> mListItems;    //给listview添加一个普通的适配器    private ArrayAdapter<String> mAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        //一打开应用就自动刷新,下面语句可以写到刷新按钮里面        mPullRefreshListView.setRefreshing(true);        //new GetDataTask(mPullRefreshListView, mAdapter, mListItems).execute();        //mPullRefreshListView.setRefreshing(false);    }    private void initView() {        initPTRListView();        initListView();    }    /**     * 设置下拉刷新的listview的动作     */    private void initPTRListView() {        mPullRefreshListView = (PullToRefreshListView) findViewById(R.id.pull_refresh_list);        //设置拉动监听器        mPullRefreshListView.setOnRefreshListener(new OnRefreshListener<ListView>() {            @Override            public void onRefresh(PullToRefreshBase<ListView> refreshView) {                //设置下拉时显示的日期和时间                String label = DateUtils.formatDateTime(getApplicationContext(), System.currentTimeMillis(),                        DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL);                // 更新显示的label                refreshView.getLoadingLayoutProxy().setLastUpdatedLabel(label);                // 开始执行异步任务,传入适配器来进行数据改变                new GetDataTask(mPullRefreshListView, mAdapter,mListItems).execute();            }        });        // 添加滑动到底部的监听器        mPullRefreshListView.setOnLastItemVisibleListener(new OnLastItemVisibleListener() {            @Override            public void onLastItemVisible() {                Toast.makeText(getApplication(), "已经到底了", Toast.LENGTH_SHORT).show();            }        });        //mPullRefreshListView.isScrollingWhileRefreshingEnabled();//看刷新时是否允许滑动        //在刷新时允许继续滑动        mPullRefreshListView.setScrollingWhileRefreshingEnabled(true);        //mPullRefreshListView.getMode();//得到模式        //上下都可以刷新的模式。这里有两个选择:Mode.PULL_FROM_START,Mode.BOTH,PULL_FROM_END        mPullRefreshListView.setMode(Mode.BOTH);        /**         * 设置反馈音效         */        SoundPullEventListener<ListView> soundListener = new SoundPullEventListener<ListView>(this);        soundListener.addSoundEvent(State.PULL_TO_REFRESH, R.raw.pull_event);        soundListener.addSoundEvent(State.RESET, R.raw.reset_sound);        soundListener.addSoundEvent(State.REFRESHING, R.raw.refreshing_sound);        mPullRefreshListView.setOnPullEventListener(soundListener);    }    /**     * 设置listview的适配器     */    private void initListView() {        //通过getRefreshableView()来得到一个listview对象        actualListView = mPullRefreshListView.getRefreshableView();        String []data = new String[] {"android","ios","wp","java","c++","c#"};        mListItems = new LinkedList<String>();        //把string数组中的string添加到链表中        mListItems.addAll(Arrays.asList(data));        mAdapter = new ArrayAdapter<>(getApplicationContext(),                 android.R.layout.simple_list_item_1, mListItems);        actualListView.setAdapter(mAdapter);    }}

3.写一个异步任务,来模仿从网络加载数据

这里要注意的是,加载完后要出发刷新完成和通知适配器改变的方法

public class GetDataTask extends AsyncTask<Void, Void, Void>{    private PullToRefreshListView mPullRefreshListView;    private ArrayAdapter<String> mAdapter;    private LinkedList<String> mListItems;    public GetDataTask(PullToRefreshListView listView,            ArrayAdapter<String> adapter,LinkedList<String> listItems) {        // TODO 自动生成的构造函数存根        mPullRefreshListView = listView;        mAdapter = adapter;        mListItems = listItems;    }    @Override    protected Void doInBackground(Void... params) {        //模拟请求        try {            Thread.sleep(2000);        } catch (InterruptedException e) {        }        return null;    }    @Override    protected void onPostExecute(Void result) {        // TODO 自动生成的方法存根        super.onPostExecute(result);        //得到当前的模式        Mode mode = mPullRefreshListView.getCurrentMode();        if(mode == Mode.PULL_FROM_START) {            mListItems.addFirst("这是刷新出来的数据");        }        else {            mListItems.addLast("这是刷新出来的数据");        }        // 通知数据改变了        mAdapter.notifyDataSetChanged();        // 加载完成后停止刷新        mPullRefreshListView.onRefreshComplete();    }}

PullToRefreshGridView使用方法

思路:

1.写布局文件,放入可以下拉刷新的控件

2.找到下拉刷新的控件,设置监听器,并且在刷新方法中开启一个异步任务来操作

3.通过这个下拉刷新控件的getRefreshableView()方法来得到GridView对象,按照正常的操作来设置适配器

4.在异步任务中通过LinkedList来给头部或者是尾部添加新的数据

实现:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent" ><!-- The PullToRefreshGridView replaces a standard GridView widget. -->    <com.handmark.pulltorefresh.library.PullToRefreshGridView        xmlns:ptr="http://schemas.android.com/apk/res-auto"        android:id="@+id/pull_refresh_grid"        android:layout_height="fill_parent"        android:layout_width="fill_parent"        android:numColumns="auto_fit"        android:verticalSpacing="1dp"        android:horizontalSpacing="1dp"        android:columnWidth="100dp"        android:stretchMode="columnWidth"        android:gravity="fill"        ptr:ptrMode="both"        ptr:ptrDrawable="@drawable/ic_launcher" /></LinearLayout>

2.找到这个可以下拉刷新的控件,并且设置监听器

这里的监听器和上篇文章讲的不同,是双向的。所以很方便监听滑动操作!
这里也可以设置适配器中无数据时显示的内容,调用的方法是:setEmptyView()

public class MainActivity extends Activity {    //链表数组对象,用来方便添加string对象    private LinkedList<String> mListItems;    //用来下拉刷新的控件    private PullToRefreshGridView mPullRefreshGridView;    //真正用到的控件,它被隐含到PullToRefreshGridView中,所以需要找出来才能使用    private GridView mGridView;    //定义GridView的适配器    private ArrayAdapter<String> mAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();    }    private void initView() {        // TODO 自动生成的方法存根        initPTRGrideView();        initGrideView();    }    /**     *设置下拉刷新的view,设置双向监听器      */    private void initPTRGrideView() {        // 得到下拉刷新的GridView        mPullRefreshGridView = (PullToRefreshGridView) findViewById(R.id.pull_refresh_grid);        // 设置监听器,这个监听器是可以监听双向滑动的,这样可以触发不同的事件        mPullRefreshGridView.setOnRefreshListener(new OnRefreshListener2<GridView>() {            @Override            public void onPullDownToRefresh(PullToRefreshBase<GridView> refreshView) {                Toast.makeText(getApplicationContext(), "下拉", Toast.LENGTH_SHORT).show();                new GetDataTask(mPullRefreshGridView, mAdapter, mListItems).execute();            }            @Override            public void onPullUpToRefresh(PullToRefreshBase<GridView> refreshView) {                Toast.makeText(getApplicationContext(), "上拉", Toast.LENGTH_SHORT).show();                new GetDataTask(mPullRefreshGridView, mAdapter, mListItems).execute();            }        });    }    /**     * 设置GridView,首先找到它,然后设置适配器     */    private void initGrideView() {        mGridView = mPullRefreshGridView.getRefreshableView();        //定义String数组,然后把它放到LinkedList中,之后只要在异步任务中用LinkedList就可以添加开头和结尾的数据了        String []data = new String[] {"android","ios","wp","java","c++","c#"};        mListItems = new LinkedList<String>();        mListItems.addAll(Arrays.asList(data));        //当适配器中没有数据的时候显示的东西,这里因为我给适配器中填充了string数组,所以不会显示“这里很空,下拉刷新试试”        TextView tv = new TextView(this);        tv.setGravity(Gravity.CENTER);        tv.setText("这里很空,下拉刷新试试");        //当界面为空的时候显示的视图        mPullRefreshGridView.setEmptyView(tv);        //设置适配器        mAdapter = new ArrayAdapter<String>(this,                 android.R.layout.simple_list_item_1, mListItems);        mGridView.setAdapter(mAdapter);    }}
public class GetDataTask extends AsyncTask<Void, Void, Void>{    private PullToRefreshGridView mPullRefreshGridView;    private ArrayAdapter<String> mAdapter;    private LinkedList<String> mListItems;    public GetDataTask(PullToRefreshGridView gridView,            ArrayAdapter<String> adapter,LinkedList<String> listItems) {        // TODO 自动生成的构造函数存根        mPullRefreshGridView = gridView;        mAdapter = adapter;        mListItems = listItems;    }    @Override    protected Void doInBackground(Void... params) {        //模拟请求,舒眠2秒钟        try {            Thread.sleep(2000);        } catch (InterruptedException e) {        }        return null;    }    @Override    protected void onPostExecute(Void result) {        // TODO 自动生成的方法存根        super.onPostExecute(result);        //得到当前的模式,来判断数据应该加载到哪个位置        Mode mode = mPullRefreshGridView.getCurrentMode();        if(mode == Mode.PULL_FROM_START) {            mListItems.addFirst("这是刷新出来的数据");        }        else {            mListItems.addLast("这是刷新出来的数据");        }        // 通知数据改变了        mAdapter.notifyDataSetChanged();        // 加载完成后停止刷新        mPullRefreshGridView.onRefreshComplete();    }}

PullToRefreshScrollView 使用

和ScrollView不同的是,这里不用放一个linearLayout来做内容的容器,直接放入要显示的东西就行。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" > pulltorefresh.library.PullToRefreshScrollView        xmlns:ptr="http://schemas.android.com/apk/res-auto"        android:id="@+id/pull_refresh_scrollview"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        ptr:ptrAnimationStyle="flip"        ptr:ptrMode="both" >        <TextView            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:padding="8dp"            android:text="@string/filler_text"            android:textSize="16sp" />    </com.handmark.pulltorefresh.library.PullToRefreshScrollView></LinearLayout>

2.找到控件并进行设置

public final class PullToRefreshScrollViewActivity extends Activity {    PullToRefreshScrollView mPullRefreshScrollView;    ScrollView mScrollView;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_ptr_scrollview);        //找到控件        mPullRefreshScrollView = (PullToRefreshScrollView) findViewById(R.id.pull_refresh_scrollview);        //设置监听器,监听器中执行异步任务        mPullRefreshScrollView.setOnRefreshListener(new OnRefreshListener<ScrollView>() {            @Override            public void onRefresh(PullToRefreshBase<ScrollView> refreshView) {                new GetDataTask().execute();            }        });        mScrollView = mPullRefreshScrollView.getRefreshableView();    }    private class GetDataTask extends AsyncTask<Void, Void, String[]> {        @Override        protected String[] doInBackground(Void... params) {            try {                Thread.sleep(4000);            } catch (InterruptedException e) {            }            return null;        }        @Override        protected void onPostExecute(String[] result) {            //注意:执行完后通知控件刷新完成            mPullRefreshScrollView.onRefreshComplete();            super.onPostExecute(result);        }    }}

下面是横向的ScrollView

1.布局文件,就是几个textview

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <!-- The PullToRefreshScrollView replaces a standard PullToRefreshScrollView widget. -->    <com.handmark.pulltorefresh.library.PullToRefreshHorizontalScrollView        xmlns:ptr="http://schemas.android.com/apk/res-auto"        android:id="@+id/pull_refresh_horizontalscrollview"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        ptr:ptrAnimationStyle="flip"        ptr:ptrMode="both" >        <LinearLayout            android:layout_width="wrap_content"            android:layout_height="fill_parent"            android:orientation="horizontal" >            <TextView                style="@style/HorizScrollViewItem"                android:layout_width="wrap_content"                android:layout_height="fill_parent"                android:background="#ff99cc00" />            <TextView                style="@style/HorizScrollViewItem"                android:layout_width="wrap_content"                android:layout_height="fill_parent"                android:background="#ffff4444" />            <TextView                style="@style/HorizScrollViewItem"                android:layout_width="wrap_content"                android:layout_height="fill_parent"                android:background="#ff33b5e5" />            <TextView                style="@style/HorizScrollViewItem"                android:layout_width="wrap_content"                android:layout_height="fill_parent"                android:background="#ffcc0000" />        </LinearLayout>    </com.handmark.pulltorefresh.library.PullToRefreshHorizontalScrollView></LinearLayout>

2.activity中的代码,和上面基本一样

public final class PullToRefreshHorizontalScrollViewActivity extends Activity {    PullToRefreshHorizontalScrollView mPullRefreshScrollView;    HorizontalScrollView mScrollView;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_ptr_horizontalscrollview);mPullRefreshScrollView = (PullToRefreshHorizontalScrollView)findViewById(R.id.pull_refresh_horizontalscrollview);        mPullRefreshScrollView.setOnRefreshListener(new OnRefreshListener<HorizontalScrollView>() {            @Override            public void onRefresh(PullToRefreshBase<HorizontalScrollView> refreshView) {                new GetDataTask().execute();            }        });        mScrollView = mPullRefreshScrollView.getRefreshableView();    }    private class GetDataTask extends AsyncTask<Void, Void, String[]> {        @Override        protected String[] doInBackground(Void... params) {            try {                Thread.sleep(4000);            } catch (InterruptedException e) {            }            return null;        }        @Override        protected void onPostExecute(String[] result) {            mPullRefreshScrollView.onRefreshComplete();            super.onPostExecute(result);        }    }}

这里我们来注意下这部分

 mPullRefreshScrollView = (PullToRefreshHorizontalScrollView) findViewById(R.id.pull_refresh_horizontalscrollview);        mPullRefreshScrollView.setOnRefreshListener(new OnRefreshListener<HorizontalScrollView>() {            @Override            public void onRefresh(PullToRefreshBase<HorizontalScrollView> refreshView) {                new GetDataTask().execute();            }        });

    mPullRefreshScrollView.setOnRefreshListener(new OnRefreshListener<ScrollView>() {        @Override        public void onRefresh(PullToRefreshBase<ScrollView> refreshView) {            new GetDataTask().execute();        }    });

ViewPager使用方法

点击查看参考博客

这里写图片描述

0 0
原创粉丝点击