Android开源项目PullToRefresh下拉刷新功能详解
作者:Developer_Kale 发布时间:2022-02-02 15:14:54
先看看效果图:
开源项地址:https://github.com/chrisbanes/Android-PullToRefresh
下拉刷新这个功能我们都比较常见了,今天介绍的就是这个功能的实现。我将按照这个开源库的范例来一点一点介绍,今天是介绍比较常见的PullToRefreshListView,是让listView有下拉刷新功能。
1.下载项目包,将library包导入即可,其他的包暂时不用
2.分析源码,看我们可以设置的有哪些
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="PullToRefresh">
<!-- A drawable to use as the background of the Refreshable View -->
<!-- 设置刷新view的背景 -->
<attr name="ptrRefreshableViewBackground" format="reference|color" />
<!-- A drawable to use as the background of the Header and Footer Loading Views -->
<!-- 设置头部view的背景 -->
<attr name="ptrHeaderBackground" format="reference|color" />
<!-- Text Color of the Header and Footer Loading Views -->
<!-- 设置头部/底部文字的颜色 -->
<attr name="ptrHeaderTextColor" format="reference|color" />
<!-- Text Color of the Header and Footer Loading Views Sub Header -->
<!-- 设置头部/底部副标题的文字颜色 -->
<attr name="ptrHeaderSubTextColor" format="reference|color" />
<!-- Mode of Pull-to-Refresh that should be used -->
<!-- 设置下拉刷新的模式,有多重方式可选。无刷新功能,从顶部刷新,从底部刷新,二者都有,只允许手动刷新 -->
<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" />
<!-- These last two are depreacted -->
<!-- 这两个属性不推荐了,用上面的代替即可 -->
<flag name="pullDownFromTop" value="0x1" />
<flag name="pullUpFromBottom" value="0x2" />
</attr>
<!-- Whether the Indicator overlay(s) should be used -->
<!-- 是否显示指示箭头 -->
<attr name="ptrShowIndicator" format="reference|boolean" />
<!-- Drawable to use as Loading Indicator. Changes both Header and Footer. -->
<!-- 指示箭头的图片 -->
<attr name="ptrDrawable" format="reference" />
<!-- Drawable to use as Loading Indicator in the Header View. Overrides value set in ptrDrawable. -->
<!-- 顶部指示箭头的图片,设置后会覆盖ptrDrawable中顶部的设置 -->
<attr name="ptrDrawableStart" format="reference" />
<!-- Drawable to use as Loading Indicator in the Fooer View. Overrides value set in ptrDrawable. -->
<!-- 底部指示箭头的图片,设置后会覆盖ptrDrawable中底部的设置 -->
<attr name="ptrDrawableEnd" format="reference" />
<!-- Whether Android's built-in Over Scroll should be utilised for Pull-to-Refresh. -->
<attr name="ptrOverScroll" format="reference|boolean" />
<!-- Base text color, typeface, size, and style for Header and Footer Loading Views -->
<!-- 设置文字的基本字体 -->
<attr name="ptrHeaderTextAppearance" format="reference" />
<!-- Base text color, typeface, size, and style for Header and Footer Loading Views Sub Header -->
<!-- 设置副标题的基本字体 -->
<attr name="ptrSubHeaderTextAppearance" format="reference" />
<!-- Style of Animation should be used displayed when pulling. -->
<!-- 设置下拉时标识图的动画,默认为rotate -->
<attr name="ptrAnimationStyle">
<flag name="rotate" value="0x0" />
<flag name="flip" value="0x1" />
</attr>
<!-- Whether the user can scroll while the View is Refreshing -->
<!-- 设置刷新时是否允许滚动,一般为true -->
<attr name="ptrScrollingWhileRefreshingEnabled" format="reference|boolean" />
<!--
Whether PullToRefreshListView has it's extras enabled. This allows the user to be
able to scroll while refreshing, and behaves better. It acheives this by adding
Header and/or Footer Views to the ListView.
-->
<!-- 允许在listview中添加头/尾视图 -->
<attr name="ptrListViewExtrasEnabled" format="reference|boolean" />
<!--
Whether the Drawable should be continually rotated as you pull. This only
takes effect when using the 'Rotate' Animation Style.
-->
<!-- 当设置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>
看到有这么多可以设置的属性,别以为真的就可以定制了。真正要定制还得到layout中改变刷新布局
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.找到这个控件,并且设置 *
这里面用到了一个日期的工具类,其实就是设置上次下拉的时间的。此外在下拉后会触发一个异步任务
/**
* 设置下拉刷新的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);
}
2.从上面的那个控件中,得到它包含的listView,并且设置适配器
//普通的listview对象
private ListView actualListView;
//添加一个链表数组,来存放string数组,这样就可以动态增加string数组中的内容了
private LinkedList<String> mListItems;
//给listview添加一个普通的适配器
private ArrayAdapter<String> mAdapter;
这里用到了一个LinkedList的对象,这个是一个类似于ArrayList的链表数组,比较方便在开头和末尾添加String
/**
* 设置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.写一个异步任务,来模仿从网络加载数据
这里要注意的是,加载完后要出发刷新完成和通知适配器改变的方法
package com.kale.ptrlistviewtest;
import java.util.LinkedList;
import android.os.AsyncTask;
import android.widget.ArrayAdapter;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;
/**
* @author:Jack Tony
* @tips :通过异步任务来加载网络中的数据,进行更新
* @date :2014-10-14
*/
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();
}
}
贴上acitivty中的全部代码
MainActivity.java
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);
}
}
源码下载:http://xiazai.jb51.net/201609/yuanma/AndroidListView(jb51.net).rar
猜你喜欢
- 一、SpringCache介绍Spring Cache 是一个优秀的缓存组件。自Spring 3.1起,提供了类似于@Transaction
- 前言大家都知道MySQL数据库很好用,但数据量到了千万以上了,想增加字段是非常痛苦的,这个在MongoDB里就不存在,字段想怎么加就怎么加,
- 实现原理: 长连接的维持,是要客户端程序,定时向服务端程序,发送一个
- 实践过程效果代码public partial class Form1 : Form{ public Form1()
- 写在前面Linux:CentOS7.5Spark: spark-3.0.0-bin-hadoop3.2IDE:IntelliJ IDEA20
- 一个简单的网格布局activity_main.xml<?xml version="1.0" encoding=&q
- 一Map特性:1 Map提供一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够实现根据key快速查找value;2
- Android 想判断 Activity 是否是全屏,网上找了些方法,看到有直接获取 flags 和一个具体的值比较,并没有用,其实分析下来
- Docker 是一种“轻量级”容器技术,它几乎动摇了传统虚拟化技术的地位,现在国内外已经有越来越多的公司开始逐步使用 Docker 来替换现
- 尝试了各种防止中文乱码的方式,但是还是乱码;最后还是细节问题导致;解决方式:以及俩种方式是百度的,我的问题不是这俩块1.在requestMa
- 介绍本篇给大家带了的是ViewFlipper,它是Android自带的一个多页面管理控件,且可以自动播放! 和ViewPager不同,Vie
- jar包打包实现jar包打包可以使用jar指令实现打包,在命令行中输入jar可以查看jar指令的内容 从最后显示的两个示例看出存在两种打包的
- 多数据源创建数据库CREATE DATABASE mybatis_plus_1;USE mybatis_plus_1;CREATE TABL
- 可以用抽象工厂模式来造车。车的品牌有很多,而且车的属性也不少,比如车的类型、排量、门的数量,等等。可以提炼出有关车的一个抽象类:public
- 本文主要和大家分享介绍了关于Java JDK * 使用的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍:前言代理是一种常用的
- 目录前言一、Spring Boot对Redis的支持二、实战1、添加依赖2、redis配置3、实现序列化4、创建Redis连接工厂,同时注册
- EventBus 可以很方便地进行各组件间的通信,解耦性更强,比广播更好用。EventBus 3 简介EventBus是一种为了优化Andr
- 前言单元测试是编写测试代码,用来检测特定的、明确的、细颗粒的功能。单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的。单元测试不
- 通常C#使用基于XML的配置文件,不过如果有需要的话,比如要兼顾较老的系统,可能还是要用到INI文件。但C#本身并不具备读写INI文件的AP
- 实现了一个自定义的密码输入框和自定义数字键盘,用作用户支付密码设置界面。先上效果图如下,方格样式,以及点击空白处隐藏软键盘。 控件实现清单: