文档章节

android使用PullToRefresh实现下拉刷新

fxdong6_6
 fxdong6_6
发布于 2017/09/11 01:21
字数 2019
阅读 41
收藏 0

精选30+云产品,助力企业轻松上云!>>>

android中下拉刷新是一个很常见的功能,今天我们就来介绍一个能很方便的实现下拉刷新的方式。

PullToRefresh是github上的一个非常好用的下拉刷新的开源库,下面是PullToRefresh的官方下载地址:

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

下面正式开始介绍PullToRefresh在项目中的应用,开发工具使用的是android studio。

1、下载PullToRefresh

打开上面的PullToRefresh官网链接,点击绿色按钮“Clone or download",然后点击Download ZIP,下载PullToRefresh压缩包。

2、将PullToRefresh配置到项目中

首先新建一个android项目,然后找到刚才下载的PullToRefresh压缩包,解压后得到目录如下:

然后将目录中的library作为一个module导入项目,具体步骤哦:点击android studio菜单栏的File->New->Import Module,弹出New Module窗口,在Source directory出填写library的完整路径,也可以点击右边的浏览按钮,找到library,选中点击OK,如下图:

导入的module名字默认为文件夹的名字library,我们可以自己给这个module起一个名字,点击next->finish完成。

导入完成后项目目录如下:

到这里还没完成,如果想正常使用PullToRefresh,我们还需要将app和PullToRefresh这两个module进行关联。点击菜单栏的File->Project Structure,弹出窗口如下,点击左侧的app,然后点击上方的Dependencies,点击右边的绿色加号,选择第三个选项

点击上图中的第三个选项之后弹出module选择窗口,这里我们除了app之外只有一个module,就是我们刚才添加的library(我自己起的名字是pulltorefresh-library),选中这个module,点击OK

这时我们能看到app下多了一个依赖,就是我们刚才添加的pulltorefresh-library。到这里,我们就可以在项目中正常使用PullToRefresh了。

另外,值得注意的一点是,在PullToRefresh的res目录下有很多的"values-xx"目录,如下图所示。

打开看一下会发现里卖弄是定义的一些字符串,其实这些文件是为了翻译values目录下定义的字符串的,是PullToRefresh为了提供更好的国际兼容性而做的。个人建议使用时将这些"values-xx"全部删除,然后打开values目录下的字符创定义文件,将其中定义的字符串的值修改为固定值,如下图所示。如果不这样做的话,在打包apk时会提示在其他地方定义的字符串在某个字符串定义文件中缺少翻译而打包失败。

3、在项目中使用PullToRefresh实现下拉刷新

通过查看PullToRefresh的类库可知,PullToRefresh支持ExpandableListView、GridView、HorizontalScrollView、ListView、ScrollView、WebView等控件的下拉刷新和上拉加载,这篇文章将以其中的ListView(扩展类为PullToRefreshListView)为例进行说明。

1)首先,打开我们刚才新建的android项目,找到layout目录下的activity_main.xml布局文件,在里面添加一个PullToRefreshListView控件,代码如下。

activity_main.xml  

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.conan.pulltorefreshdemo.MainActivity">
    
    <com.handmark.pulltorefresh.library.PullToRefreshListView
        android:id="@+id/lv_mylistview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:ptrAnimationStyle="flip"
        app:ptrHeaderBackground="#f0f0f0"
        app:ptrHeaderTextColor="#000000">

    </com.handmark.pulltorefresh.library.PullToRefreshListView>

</RelativeLayout>

需要注意有两点,第一,因为使用了自定义的控件,所以需要在PullToRefreshListView控件或其父控件中添加命名空间xmlns:app="http://schemas.android.com/apk/res-auto";第二,PullToRefreshListView中的属性ptrAnimationStyle、ptrHeaderBackground和ptrHeaderTextColor为PullToRefresh中自定义的属性,其中ptrAnimationStyle用来设置刷新和加载时的动画效果,ptrHeaderBackground用来设置刷新和加载区域的背景,ptrHeaderTextColor用来设置刷新和加载区域的字体颜色,PullToRefresh还有一些其他的属性,具体可以查看PullToRefresh类库的values目录下的attrs.xml文件。

2)有了一个ListView,我们还需要一个item布局文件,用来填充这个ListView。

在layout目录下再新建一个my_list_item.xml布局文件,代码如下。

my_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp">
        <ImageView
            android:id="@+id/iv_item_pic"
            android:layout_width="200dp"
            android:layout_height="160dp" />
        <TextView
            android:id="@+id/tv_item_name"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_toRightOf="@id/iv_item_pic"
            android:layout_marginLeft="10dp"
            android:layout_alignParentTop="true"
            android:gravity="center_vertical"
            android:textSize="24sp"/>
        <TextView
            android:id="@+id/tv_item_introduce"
            android:layout_width="wrap_content"
            android:layout_height="40dp"
            android:layout_toRightOf="@id/iv_item_pic"
            android:layout_marginLeft="10dp"
            android:layout_below="@id/tv_item_name"
            android:gravity="center_vertical"
            android:textSize="18sp"/>
        <Button
            android:id="@+id/btn1_item"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_below="@id/tv_item_introduce"
            android:layout_toRightOf="@id/iv_item_pic"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="10dp"
            android:gravity="center"
            android:textSize="20sp"
            android:text="操作1"
            android:background="@drawable/btn_selector"/>
        <Button
            android:id="@+id/btn2_item"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_marginLeft="20dp"
            android:layout_below="@id/tv_item_introduce"
            android:layout_toRightOf="@id/btn1_item"
            android:layout_marginTop="10dp"
            android:gravity="center"
            android:textSize="20sp"
            android:text="操作2"
            android:background="@drawable/btn_selector"/>
    </RelativeLayout>
</RelativeLayout>

在这个布局文件中,我们用一个ImageView来显示item的图片,用两个TextView来显示对item的描述信息,用两个Button来模拟对item的操作。

3)布局文件准备完成后,就可以在MainActivity中对ListView进行初始化了。

package com.example.conan.pulltorefreshdemo;

import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import com.handmark.pulltorefresh.library.ILoadingLayout;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshListView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    private PullToRefreshListView myListView;
    private List<Map<String,Object>> dataList;
    private ListViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myListView = (PullToRefreshListView) findViewById(R.id.lv_mylistview);

        /**
         * PullToRefreshListView的setMode方法有三个可选参数:
         * Mode.BOTH、Mode.PULL_FROM_END、Mode.PULL_FROM_START
         * Mode.BOTH:同时支持下拉刷新和上拉加载,需要设置刷新Listener为OnRefreshListener2,
         *           并实现onPullDownToRefresh()方法和onPullUpToRefresh()方法
         * Mode.PULL_FROM_START仅支持下拉刷新,Mode.PULL_FROM_END仅支持上拉加载,这两种模式需要设置
         *          Listener为OnRefreshListener,并实现onRefresh()方法;也可以设置刷新Listener
         *          为OnRefreshListener2,并实现onPullDownToRefresh()方法和onPullUpToRefresh()方法,
         *          但是Mode.PULL_FROM_START只调用onPullDownToRefresh()方法,Mode.PULL_FROM_END只调
         *          用onPullUpToRefresh()方法
         */
        myListView.setMode(PullToRefreshBase.Mode.BOTH);
        //设置下拉刷新时显示的文本
        ILoadingLayout headerLayout = myListView.getLoadingLayoutProxy(true, false);
        headerLayout.setPullLabel("下拉可以刷新");
        headerLayout.setRefreshingLabel("玩儿命刷新中...");
        headerLayout.setReleaseLabel("释放立即刷新");
        //设置上拉加载时显示的文本
        ILoadingLayout tailerLayout = myListView.getLoadingLayoutProxy(false, true);
        tailerLayout.setPullLabel("上拉可以加载");
        tailerLayout.setRefreshingLabel("玩儿命加载中...");
        tailerLayout.setReleaseLabel("释放立即加载");
        //设置刷新监听器
        myListView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<ListView>() {
            //下拉时执行的方法
            @Override
            public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
                //模拟网络请求数据
                new LoadDataAsyncTask(MainActivity.this).execute();
            }
            //上拉时执行的方法
            @Override
            public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
                //模拟网络请求数据
                new LoadDataAsyncTask(MainActivity.this).execute();
            }
        });
        //初始化数据dataList
        getData();
        //实例化自定义的适配器ListViewAdapter,将dataList中的数据设置到my_list_item布局的控件中
        adapter = new ListViewAdapter(this, R.layout.my_list_item, dataList);
        myListView.setAdapter(adapter);
    }

    public void getData() {
        dataList = new ArrayList<>();
        for (int i = 0;i < 10;i ++) {
            Map<String,Object> map = new HashMap<>();
            map.put("itemPic",R.drawable.error_img);
            map.put("name","Item" + i);
            map.put("introduce","introduce of item " + i);
            dataList.add(map);
        }
    }

    /**
     * 自定义适配器类ListViewAdapter,继承BaseAdapter,实例化时会先调用getCount()方法确定有多少个item,
     * 然后调用getView()方法一遍一遍的进行数据的渲染
     */
    private class ListViewAdapter extends BaseAdapter {

        private Context context;
        private List<Map<String,Object>> dataList;
        private int itemLayout;

        public ListViewAdapter (Context context, int itemLayout, List<Map<String,Object>> dataList) {
            super();
            this.context = context;
            this.dataList = dataList;
            this.itemLayout = itemLayout;
        }

        @Override
        public int getCount() {
            if (dataList != null && dataList.size() != 0) {
                return dataList.size();
            } else {
                return 0;
            }
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            final Map<String, Object> itemData = dataList.get(position);
            if (convertView == null) {
                holder = new ViewHolder();
                convertView  = View.inflate(context, itemLayout, null);
                holder.itemPic = convertView.findViewById(R.id.iv_item_pic);
                holder.name = convertView.findViewById(R.id.tv_item_name);
                holder.introduce = convertView.findViewById(R.id.tv_item_introduce);
                holder.btn1 = convertView.findViewById(R.id.btn1_item);
                holder.btn2 = convertView.findViewById(R.id.btn2_item);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            holder.itemPic.setBackgroundResource((Integer) itemData.get("itemPic"));
            holder.name.setText((String) itemData.get("name"));
            holder.introduce.setText((String) itemData.get("introduce"));
            holder.btn1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(context, "对" + itemData.get("name") + "进行操作1",Toast.LENGTH_SHORT).show();
                }
            });
            holder.btn2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(context, "对" + itemData.get("name") + "进行操作2",Toast.LENGTH_SHORT).show();
                }
            });
            return convertView;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public Object getItem(int position) {
            return dataList.get(position);
        }
    }

    private static class ViewHolder {
        ImageView itemPic;
        TextView name;
        TextView introduce;
        Button btn1;
        Button btn2;
    }

    /**
     * 模拟进行网络数据请求
     */
    private class LoadDataAsyncTask extends AsyncTask<Void, Void, String> {

        private MainActivity activity;
        public LoadDataAsyncTask(MainActivity activity) {
            this.activity = activity;
        }

        @Override
        protected String doInBackground(Void... params) {
            try {
                activity.getData();
                Thread.sleep(1000);
                return "SUCCESS";
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            if (s.equals("SUCCESS")) {
                adapter.notifyDataSetChanged();
                myListView.onRefreshComplete();
            }
        }
    }
}

最后,附上Demo链接:

https://github.com/fxdong/PullToRefreshDemo

 

fxdong6_6
粉丝 4
博文 12
码字总数 8654
作品 0
朝阳
程序员
私信 提问
加载中
请先登录后再评论。
PullToRefreshListView 应用讲解

转载于http://blog.csdn.net/mmjiajia132/article/details/40397813 PullToRefreshListView 用法和ListView 没有什么区别 listview能用的属性 pulltorefresh也能用 我一直认为动手是最好的学...

程序员小冰
2015/11/19
115
0
PullToRefreshListView 应用讲解

转载于http://blog.csdn.net/mmjiajia132/article/details/40397813 PullToRefreshListView 用法和ListView 没有什么区别 listview能用的属性 pulltorefresh也能用 我一直认为动手是最好的学...

程序袁_绪龙
2015/08/02
226
0
Android几种强大的下拉刷新库

BeautifulRefreshLayout 众多优秀的下拉刷新(除了我写的之外T_T) 说起下拉刷新,好像经历一段历史的洗礼。。。 (1)在我刚学android的时候,用的是XListView,在github上搜索有 MarkMjw/Pull...

osc_gazfrwgi
2018/05/02
1
0
【转载】Android几种强大的下拉刷新库

转载自:https://github.com/android-cjj/BeautifulRefreshLayout。 总结来说,一些好用的下拉加载库: chrisbanes/Android-PullToRefresh chrisbanes/ActionBar-PullToRefresh google自己的......

osc_i9jmzjxx
2018/08/14
1
0
开源项目Actionbar-pulltorefesh的使用

下拉刷新功能 ActionBar-PullToRefresh-master 提供了两套方案: 1. actionbarcompat 使用Android兼容包Compat 功能较弱, 用户体验较差 2. actionbarsherlock(建议使用) 在Fragment中使用Act...

胡文城
2014/05/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Maven中dependencyManagement和依赖关系之间的区别

问题: What is the difference between dependencyManagement and dependencies ? dependencyManagement和dependencies什么区别? I have seen the docs at Apache Maven web site. 我已经在......

富含淀粉
27分钟前
7
0
Confluence 如何查看页面 ID

如果你希望查看页面的 ID 你有 2 个方法。 例如,你希望查看 https://www.cwiki.us/display/CONFLUENCEWIKI/Get+started 页面的 Page ID 的话。 如果你的标题栏没有特殊字符,那么将会使用英...

honeymoose
30分钟前
7
0
Linux系统 Centos7 环境基于Docker部署Rocketmq服务

消息队列 基本概述 MQ,Message Queue,基于TCP协议构建的简单协议,区别于具体的通信协议。 基于通信协议定义和抽象的更高层次的通信模型,一般都是生产者和消费者模型,又或者说服务端和客户端...

mazhilin
44分钟前
12
0
我可以在.gitconfig中为自己指定多个用户吗? - Can I specify multiple users for myself in .gitconfig?

问题: In my ~/.gitconfig , I list my personal email address under [user] , since that's what I want to use for Github repos. 在~/.gitconfig ,我在[user]我的个人电子邮件地址,因......

法国红酒甜
57分钟前
19
0
C++11好用的写法

https://stackoverflow.com/questions/12944002/capture-by-value-class-members

剑是SR剑
今天
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部