PullToRefresh实现下拉刷新和上拉加载更多的ListView

来源:互联网 发布:自考,成考,远程网络 编辑:程序博客网 时间:2024/06/03 14:30

使用PullToRefresh实现下拉刷新和上拉加载更多的ListView效果如下:


PullToRefresh是非常好用的第三方下拉刷新库,它支持:

1.ListView

2.ExpandableListView

3.GridView

4.WebView

等多种常用的需要刷新的View控件,基本上能够满足我们的开发需要。

下面结合一个小Demo介绍一下使用PullToRefresh实现下拉刷新和上拉加载更多的ListView的方法:

(一) 先到GitHub上下载PullToRefresh的类库,下载地址是:

https://github.com/chrisbanes/Android-PullToRefresh

(二) 解压缩后,导入library到自己的工程目录下,然后让使用此功能的Module与library建立依赖。

library给我们提供了常用控件的实现代码,我们可以参照这些代码来自己开发:



(三) 如何理解下拉刷新和上拉加载更多?

我感觉这段说的很到位:

     下拉刷新是重新加载列表,重新请求数据;而上拉加载更多,是在已有列表的基础上,根据当前客户端显示的最后一个item的ID值,找到后续的若干个Item数据,返回给客户端,添加到当前列表的末尾显示的;就发送请求和返回数据的技术而言,没有区别,区别在SQL语句;还有对于Listview是重置列表数据,还是添加数据到列表末尾的问题。


(四)setMode 设置模式:

  • Mode.BOTH:同时支持上拉下拉
  • Mode.PULL_FROM_START:只支持下拉Pulling Down
  • Mode.PULL_FROM_END:只支持上拉Pulling Up
  • DISABLED 不支持刷新功能

也可以用 ptr:ptrMode="both"

可选值为:disabled(禁用下拉刷新),pullFromStart(仅支持下拉刷新),pullFromEnd(仅支持上拉刷新),both(二者都支持),manualOnly(只允许手动触发)

如果Mode设置成Mode.BOTH,需要设置刷新Listener为OnRefreshListener2,并实现onPullDownToRefresh()、onPullUpToRefresh()两个方法。 

如果Mode设置成Mode.PULL_FROM_START或Mode.PULL_FROM_END,需要设置刷新Listener为OnRefreshListener,同时实现onRefresh()方法。

当然也可以设置为OnRefreshListener2,但是Mode.PULL_FROM_START的时候只调用onPullDownToRefresh()方法,Mode.PULL_FROM的时候只调用onPullUpToRefresh()方法.

如果想上拉、下拉刷新的时候 做一样的操作,那就用OnRefreshListener,上拉下拉的时候都调用

如果想上拉、下拉做不一样的的操作,那就在setOnRefreshListener时 用new OnRefreshListener2<ListView>


(五) 实现上面效果的代码:

①MainActivity代码:

<span style="font-size:18px;"><span style="font-size:18px;">/** * 下拉刷新,上拉加载更多 * 上拉加载更多,数据量大需要分页,减少内消耗。避免用户快速向下滑动,减少流量 * 下拉刷新,用户习惯 * 使用第三方  Xlistview  pulltorefreshlistview * 官方(下拉刷新,但是没有上拉加载更多) * pulltorefreshview其实都是一个自定义的布局,里面包裹着Listview或者其他的控件 */public class MainActivity extends AppCompatActivity {    protected PullToRefreshListView mPullToRefreshList;    private MyAdapter mAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        super.setContentView(R.layout.activity_main);        initView();        //第一次加载数据,默认我下拉刷新        initData(false);        /**         * 设置模式         * DISABLED 不启用刷新功能         * PULL_FROM_START 仅支持下拉         * PULL_FROM_END 仅支持上拉         * BOTH  支持上拉和下拉         * MANUAL_REFRESH_ONLY  不支持手势刷新,但是支持使用点击或者其他动作通过代码手动调用刷新         *         */        mPullToRefreshList.setMode(PullToRefreshBase.Mode.BOTH);        //如果mode为both时(即有两种状态),使用这个监听        mPullToRefreshList.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<ListView>() {            //开始下拉  我们需要在用户下拉的时候重新做http请求            @Override            public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {                initData(false);            }            @Override            public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {                initData(true);            }        });        mAdapter = new MyAdapter();        mPullToRefreshList.setAdapter(mAdapter);        //如果需要自定义头标题,先拿到原生控件,在原生控件的基础上添加头标题        //ListView refreshableView = mPullToRefreshList.getRefreshableView();        //refreshableView.addHeaderView(null);        //获取一个头部和尾部的布局        ILoadingLayout loadingLayoutProxy = mPullToRefreshList.getLoadingLayoutProxy();        loadingLayoutProxy.setRefreshingLabel("正在刷新..."); // 刷新时        loadingLayoutProxy.setPullLabel("下拉刷新"); // 刚下拉时,显示的提示        loadingLayoutProxy.setLoadingDrawable(getResources().getDrawable(R.mipmap.ic_launcher));        loadingLayoutProxy.setLastUpdatedLabel("刚刚"); //一般是上次刷新的时间        loadingLayoutProxy.setReleaseLabel("松手开始刷新");    }    private void initView() {        mPullToRefreshList = (PullToRefreshListView) findViewById(R.id.pullToRefresh);    }    //要获取实体类中的数据    private List<ListData.ResultEntity> mResult = new ArrayList<>();    /**     * 获取数据,参数为判断是上拉加载更多,还是下拉刷新     */    private void initData(final boolean isUP) {        //使用xutils获取网络数据        HttpUtils httpUtils = new HttpUtils();        String url = "http://api.shigeten.net/api/Critic/GetCriticList";        httpUtils.send(HttpRequest.HttpMethod.GET, url, new RequestCallBack<String>() {            @Override            public void onSuccess(ResponseInfo<String> responseInfo) {                //使用Gson解析之前需导包                Gson gson = new Gson();                ListData listData = gson.fromJson(responseInfo.result, ListData.class);                List<ListData.ResultEntity> result = listData.getResult();                if (isUP) { //上拉加载更多                    mResult.addAll(result);                    mAdapter.setResults(mResult);                    mAdapter.notifyDataSetChanged();                } else { //下拉刷新                    mAdapter.setResults(result);                    mAdapter.notifyDataSetChanged();                }                //刷新完成提供给我们手动调用                mPullToRefreshList.onRefreshComplete();                Toast.makeText(MainActivity.this, "数据请求成功", Toast.LENGTH_SHORT).show();            }            @Override            public void onFailure(HttpException error, String msg) {                Log.e("onFailure", error.getMessage());            }        });    }}</span></span>

注:上面的代码用到了第三方框架xUtils和和Gson,需要提前把这两个包导入。


②对应的自定义适配器代码:

<span style="font-size:18px;"><span style="font-size:18px;">public class MyAdapter extends BaseAdapter {    List<ListData.ResultEntity> results;    public void setResults(List<ListData.ResultEntity> results) {        this.results = results;    }    @Override    public int getCount() {        return results == null ? 0 : results.size();    }    @Override    public Object getItem(int position) {        return results.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        ViewHolder holder;        if (convertView == null){            convertView = View.inflate(parent.getContext(),R.layout.item,null);            holder = new ViewHolder();            holder.iv = (ImageView) convertView.findViewById(R.id.img);            holder.tv = (TextView) convertView.findViewById(R.id.text);            convertView.setTag(holder);        }else{            holder = (ViewHolder) convertView.getTag();        }        ListData.ResultEntity resultEntity = results.get(position);        holder.tv.setText(resultEntity.getTitle());        BitmapUtils bitmapUtils = new BitmapUtils(parent.getContext());        bitmapUtils.display(holder.iv, "http://api.shigeten.net/" + resultEntity.getImage());        return convertView;    }    class ViewHolder{        private TextView tv;        private ImageView iv;    }}</span></span>


③对应的要解析的数据的实体类代码:

<span style="font-size:18px;"><span style="font-size:18px;">public class ListData {    /*     * status : 0     * errMsg : null     */    private int status;    private Object errMsg;    /**     * id : 100045     * type : 1     * publishtime : 636107040000000000     * title : 《瑞士军刀男》人生已经如此艰难,就不要拆穿     * summary : 看似荒诞,实则厚重。生与死的距离其实真的不远,自我认知与自我救赎也只是一线之隔。不知道有没有人和我一样,看到最后尸体踏浪而去的时候内心澎湃不已。     * image : images/B0181F9BC6EFC33D0396A16556952710.jpg     */    private List<ResultEntity> result;    public int getStatus() {        return status;    }    public void setStatus(int status) {        this.status = status;    }    public Object getErrMsg() {        return errMsg;    }    public void setErrMsg(Object errMsg) {        this.errMsg = errMsg;    }    public List<ResultEntity> getResult() {        return result;    }    public void setResult(List<ResultEntity> result) {        this.result = result;    }    public static class ResultEntity {        private int id;        private int type;        private long publishtime;        private String title;        private String summary;        private String image;        public int getId() {            return id;        }        public void setId(int id) {            this.id = id;        }        public int getType() {            return type;        }        public void setType(int type) {            this.type = type;        }        public long getPublishtime() {            return publishtime;        }        public void setPublishtime(long publishtime) {            this.publishtime = publishtime;        }        public String getTitle() {            return title;        }        public void setTitle(String title) {            this.title = title;        }        public String getSummary() {            return summary;        }        public void setSummary(String summary) {            this.summary = summary;        }        public String getImage() {            return image;        }        public void setImage(String image) {            this.image = image;        }    }}</span></span>

④主布局代码activity_main.xml:

<span style="font-size:18px;"><span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?><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"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.example.pulltorefreshlistview.MainActivity">    <com.handmark.pulltorefresh.library.PullToRefreshListView        android:id="@+id/pullToRefresh"        android:layout_width="match_parent"        android:layout_height="match_parent"/></RelativeLayout></span></span>


⑤条目布局,item.xml:

<span style="font-size:18px;"><span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"              android:layout_width="match_parent"              android:layout_height="match_parent"              android:orientation="vertical">    <ImageView android:id="@+id/img"               android:layout_width="wrap_content"               android:layout_height="wrap_content"/>    <TextView        android:id="@+id/text"        android:layout_width="wrap_content"        android:layout_height="wrap_content"/></LinearLayout></span></span>


1 0
原创粉丝点击