文档章节

android使用PullToRefresh实现下拉刷新

fxdong6_6
 fxdong6_6
发布于 2017/09/11 01:21
字数 2019
阅读 16
收藏 0
点赞 0
评论 0

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
博文 11
码字总数 8654
作品 0
朝阳
程序员
Jaynm/PullToRefreshListView

PullToRefreshScrollViewDemo Android使用PullToRefresh完成ListView下拉刷新和左滑删除 一、本文主要内容: 使用PullToRefresh完成ListView下拉、上拉刷新; 扩展PullToRefresh完美的实现L...

Jaynm ⋅ 2016/11/03 ⋅ 0

Android之PullToRefresh的使用方法

android studio 导入 PullToRefresh 使用 PullToRefresh 刷新 ListView ---------------------------------------------------------------------------------------上面转载自点击查看如果需......

有名者赫赫 ⋅ 2015/04/18 ⋅ 0

使用PullToRefresh实现下拉刷新和上拉加载

PullToRefresh是一套实现非常好的下拉刷新库,它支持:1.ListView2.ExpandableListView3.GridView4.WebView等多种常用的需要刷新的View类型,而且使用起来也十分方便。(下载地址:https://g...

ForingY ⋅ 2016/12/19 ⋅ 0

SwipeRefreshLayout,用最少的代码定制最美的上下拉刷新样式

下拉刷新框架其实有很多,而且质量都比较高。但是在日常开发中,每一款产品都会有一套自己独特的一套刷新样式。相信有很多小伙伴在个性化定制中都或多或少的遇到过麻烦。今天我就给大家推荐一...

codeGoogle ⋅ 05/18 ⋅ 0

PullToRefreshListView 应用讲解

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

程序袁_绪龙 ⋅ 2015/08/02 ⋅ 0

PullToRefresh几种实现方式

方案一:继承想下拉刷新的View类(ListView RecyclerView ScrollView等),重写dispatchTouchEvent或者onTouchEvent方法,改变顶部刷新RefreshView的LayoutParams.height。需要借助Scroller类在...

GalaxyBruce ⋅ 2016/06/19 ⋅ 0

【Android】打造下拉放大效果

前言 在其他App上看到了这样的一个效果,感觉有点意思,于是决定实现一个类似的效果。 (其实是iOS的同学在是现功能的时候秀了一波操作) 效果大概是这样子的: UI看完后 “这个效果不错啊”...

带心情去旅行 ⋅ 06/19 ⋅ 0

下拉刷新动画合集(1)

边拉边吃的动画 一直对大众点评的下拉刷新的动画非常喜欢,所以就自己实现了一个。项目是基于chrisbanes的PullToRefresh做的。之后我会继续加上其他的下拉刷新的动画效果。 下面是实现效果 ...

ufo.22940268 ⋅ 2014/08/04 ⋅ 0

android高仿抖音、点餐界面、天气项目、自定义view指示、爬取美女图片等源码

Android精选源码 一个爬取美女图片的app(http://www.apkbus.com/thread-600077-1-1.html) Android高仿抖音(http://www.apkbus.com/thread-600081-1-1.html) android一个可以上拉下滑的Ui效果......

逆鳞龙 ⋅ 06/12 ⋅ 0

开源项目Actionbar-pulltorefesh的使用

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

胡文城 ⋅ 2014/05/10 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

tcp/ip详解-链路层

简介 设计链路层的目的: 为IP模块发送和接收IP数据报 为ARP模块发送ARP请求和接收ARP应答 为RARP模块发送RARP请求和接收RARP应答 TCP/IP支持多种链路层协议,如以太网、令牌环往、FDDI、RS-...

loda0128 ⋅ 42分钟前 ⋅ 0

spring.net aop代码例子

https://www.cnblogs.com/haogj/archive/2011/10/12/2207916.html

whoisliang ⋅ 58分钟前 ⋅ 0

发送短信如何限制1小时内最多发送11条短信

发送短信如何限制1小时内最多发送11条短信 场景: 发送短信属于付费业务,有时为了防止短信攻击,需要限制发送短信的频率,例如在1个小时之内最多发送11条短信. 如何实现呢? 思路有两个 截至到当...

黄威 ⋅ 昨天 ⋅ 0

mysql5.7系列修改root默认密码

操作系统为centos7 64 1、修改 /etc/my.cnf,在 [mysqld] 小节下添加一行:skip-grant-tables=1 这一行配置让 mysqld 启动时不对密码进行验证 2、重启 mysqld 服务:systemctl restart mysql...

sskill ⋅ 昨天 ⋅ 0

Intellij IDEA神器常用技巧六-Debug详解

在调试代码的时候,你的项目得debug模式启动,也就是点那个绿色的甲虫启动服务器,然后,就可以在代码里面断点调试啦。下面不要在意,这个快捷键具体是啥,因为,这个keymap是可以自己配置的...

Mkeeper ⋅ 昨天 ⋅ 0

zip压缩工具、tar打包、打包并压缩

zip 支持压缩目录 1.在/tmp/目录下创建目录(study_zip)及文件 root@yolks1 study_zip]# !treetree 11└── 2 └── 3 └── test_zip.txt2 directories, 1 file 2.yum...

蛋黄Yolks ⋅ 昨天 ⋅ 0

聊聊HystrixThreadPool

序 本文主要研究一下HystrixThreadPool HystrixThreadPool hystrix-core-1.5.12-sources.jar!/com/netflix/hystrix/HystrixThreadPool.java /** * ThreadPool used to executed {@link Hys......

go4it ⋅ 昨天 ⋅ 0

容器之上传镜像到Docker hub

Docker hub在国内可以访问,首先要创建一个账号,这个后面会用到,我是用126邮箱注册的。 1. docker login List-1 Username不能使用你注册的邮箱,要用使用注册时用的username;要输入密码 ...

汉斯-冯-拉特 ⋅ 昨天 ⋅ 0

SpringBoot简单使用ehcache

1,SpringBoot版本 2.0.3.RELEASE ①,pom.xml <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.3.RELE......

暗中观察 ⋅ 昨天 ⋅ 0

Spring源码解析(八)——实例创建(下)

前言 来到实例创建的最后一节,前面已经将一个实例通过不同方式(工厂方法、构造器注入、默认构造器)给创建出来了,下面我们要对创建出来的实例进行一些“加工”处理。 源码解读 回顾下之前...

MarvelCode ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部