整理了下以前写的小项目,ListView的下拉刷新,虽然小但还是想纪念下。。适合新手看,大神略过。。。

效果图:

   

代码:  实体类

package com.example.listviewrefreshdemo;
/**
* @author 超超boy
*/
public class ApkEntity {
private String name;
private String des;
private String info;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
} }

MainActivity:

package com.example.listviewrefreshdemo;

import java.util.ArrayList;

import com.example.listviewrefreshdemo.RefreshListView.IReflashListener;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
/**
* @author 超超boy
*/
public class MainActivity extends Activity implements IReflashListener{
ArrayList<ApkEntity> apk_list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setData();
showList(apk_list);
} MyAdapter adapter;
RefreshListView listview;
private void showList(ArrayList<ApkEntity> apk_list) {
if (adapter == null) {
listview = (RefreshListView) findViewById(R.id.listview);
listview.setIReflashListener(this);
adapter = new MyAdapter(this, apk_list);
listview.setAdapter(adapter);
} else {
adapter.onDateChange(apk_list);
}
} private void setData() {
apk_list = new ArrayList<ApkEntity>();
for (int i = 0; i < 10; i++) {
ApkEntity entity = new ApkEntity();
entity.setName("默认数据");
entity.setDes("这是一个神奇的应用");
entity.setInfo("50w用户");
apk_list.add(entity);
}
} private void setReflashData() { for (int i = 0; i < 2; i++) {
ApkEntity entity = new ApkEntity();
entity.setName("刷新数据");
entity.setDes("这是一个神奇的应用");
entity.setInfo("50w用户");
apk_list.add(i,entity);
}
}
@Override
public void onReflash() {
// TODO Auto-generated method stub\
Handler handler = new Handler();
handler.postDelayed(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
//获取最新数据
setReflashData();
//通知界面显示
showList(apk_list);
//通知listview 刷新数据完毕;
listview.reflashComplete();
}
}, 2000); } /**
* 回掉方法
*/
/*public void onReflash() {
//获取最新数据
setReflashData();
//通知界面显示
showList(apk_list);
//通知listview刷新数据完毕
listview.reflashComplete();
}*/
}

  RefreshListView:

package com.example.listviewrefreshdemo;

import java.text.SimpleDateFormat;
import java.util.Date; import android.R.anim;
import android.R.interpolator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* @author 超超boy
*/
public class RefreshListView extends ListView implements OnScrollListener{ LayoutInflater inflater;
View header;
int headerHeight; //顶部布局文件的高度
int firstVisibleItem; //当前第一个可见的item的位置
int scrollState; //listview当前滚动状态
boolean isRemark; //标记,当前是在listview的最顶部摁下的
int startY; //摁下时的Y值
int state; //当前的状态
final int NONE = 0;// 正常状态;
final int PULL = 1;// 提示下拉状态;
final int RELESE = 2;// 提示释放状态;
final int REFLASHING = 3;// 刷新状态; IReflashListener reflashListener;
public RefreshListView(Context context) {
super(context);
initView(context);
} public RefreshListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
} public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
/**
* 初始化界面,添加顶部布局文件到ListView
* @param context
*/
private void initView(Context context){
inflater = LayoutInflater.from(context);
header =inflater.inflate(R.layout.header, null);
measureView(header);
headerHeight = header.getMeasuredHeight();
Log.i("tag", "headerHeight="+headerHeight);
topPadding(-headerHeight); //负的高度,把它能没啦
this.addHeaderView(header);
this.setOnScrollListener(this);
}
/**
* 通知父布局,占用的宽高。
* @param view
*/
private void measureView(View view){
ViewGroup.LayoutParams p = view.getLayoutParams();
if(p == null){
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
//spec:header的左右边距,padding内边距,childDimension字布局的宽度
int width = ViewGroup.getChildMeasureSpec(0, 0, p.width);
int height;
int tempHeight = p.height;
if(tempHeight > 0){ //高度不是空,需要填充这个布局
//EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;
height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY);
}else{
//UNSPECIFIED(未指定),父元素不对子元素施加任何束缚,子元素可以得到任意想要的大小;
height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
view.measure(width, height);
}
/**
* 设置header布局的上边距
* @param topPadding
*/
private void topPadding(int topPadding){ //header的上边距
header.setPadding(header.getPaddingLeft(), topPadding, header.getPaddingRight(), header.getPaddingBottom());
header.invalidate();
} /**
* 取得当前的滚动状态
*/
public void onScrollStateChanged(AbsListView view, int scrollState) { this.scrollState = scrollState;
} @Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.firstVisibleItem = firstVisibleItem; //当前第一个可见的item的位置 } /**
* 触摸事件
*/
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: //下拉
if (firstVisibleItem == 0) { //在界面最顶端
isRemark = true; //标记,当前是在listview的最顶部摁下的
startY = (int) ev.getY();
}
break; case MotionEvent.ACTION_MOVE:
onMove(ev);
break;
case MotionEvent.ACTION_UP: //抬起
if (state == RELESE) { //释放
state = REFLASHING; //正在刷新
// 加载最新数据;
reflashViewByState();
reflashListener.onReflash();
} else if (state == PULL) { //下拉过程中,没到一定距离的时候
state = NONE; // 正常状态;
isRemark = false; //在顶部的标记
reflashViewByState();
}
break;
}
return super.onTouchEvent(ev);
}
/**
* 判断移动过程的操作
* @param ev
*/
private void onMove(MotionEvent ev) {
if(!isRemark){ //不在顶的时候移动
return;
}
//移动的过程中状态是不断改变的
int tempY = (int) ev.getY();
int sapce = tempY-startY; //移动的距离
int topPadding = sapce - headerHeight; //移动过程中不断设置topPadding
switch (state) {
case NONE: // 正常状态;
if(sapce>0){
state = PULL; // 提示下拉状态
reflashViewByState();
}
break;
case PULL: // 提示下拉状态;
topPadding(topPadding); //不断设置上边距
if(sapce > headerHeight+30
&& scrollState == SCROLL_STATE_TOUCH_SCROLL){
state = RELESE; // 提示释放状态;
reflashViewByState();
} break;
case RELESE: // 提示释放状态;
topPadding(topPadding);
if(sapce<headerHeight+30){
state = PULL;
reflashViewByState();
}else if(sapce <= 0){
state = NONE;
isRemark = false;
reflashViewByState();
}
break;
default:
break;
} }
/**
* 根据当前的状态,改变页面显示
*/
private void reflashViewByState(){
TextView tip = (TextView) header.findViewById(R.id.tip);
ImageView arrow = (ImageView) header.findViewById(R.id.arrow);
ProgressBar bar = (ProgressBar) header.findViewById(R.id.progress);
RotateAnimation animation = new RotateAnimation(0, 180
,RotateAnimation.RELATIVE_TO_SELF,0.5f,
RotateAnimation.RELATIVE_TO_SELF,0.5f);
animation.setDuration(500);
animation.setFillAfter(true);
RotateAnimation animation2 = new RotateAnimation(180, 0
,RotateAnimation.RELATIVE_TO_SELF,0.5f,
RotateAnimation.RELATIVE_TO_SELF,0.5f);
animation2.setDuration(500);
animation2.setFillAfter(true);
switch (state) {
case NONE:
arrow.clearAnimation();
topPadding(-headerHeight);
break;
case PULL: //下拉
arrow.setVisibility(View.VISIBLE);
bar.setVisibility(View.GONE);
tip.setText("下拉可以刷新");
arrow.clearAnimation();
arrow.setAnimation(animation2);
break;
case RELESE: //释放
arrow.setVisibility(View.VISIBLE);
bar.setVisibility(View.GONE);
tip.setText("松开可以刷新");
arrow.clearAnimation();
arrow.setAnimation(animation);
break;
case REFLASHING: //刷新
topPadding(50);
arrow.setVisibility(View.GONE);
bar.setVisibility(View.VISIBLE);
tip.setText("正在刷新");
arrow.clearAnimation();
break; default:
break;
}
}
/**
* 获取完数据
*/
public void reflashComplete(){
state = NONE;
isRemark = false; //不在顶部
reflashViewByState();
TextView lastupdatetime = (TextView) header.findViewById(R.id.lastUpdate_time);
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
Date date = new Date(System.currentTimeMillis());
String time = format.format(date);
lastupdatetime.setText(time); }
/**
* 回调接口
* @author user
*
*/
public interface IReflashListener{
public void onReflash();
}
public void setIReflashListener(IReflashListener listener){
this.reflashListener = listener;
}
}

  适配器:

package com.example.listviewrefreshdemo;

import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
/**
* @author 超超boy
*/
public class MyAdapter extends BaseAdapter {
ArrayList<ApkEntity> apk_list;
LayoutInflater inflater; public MyAdapter(Context context, ArrayList<ApkEntity> apk_list) {
this.apk_list = apk_list;
this.inflater = LayoutInflater.from(context);
} public void onDateChange(ArrayList<ApkEntity> apk_list) {
this.apk_list = apk_list;
this.notifyDataSetChanged(); //更新数据
} @Override
public int getCount() {
// TODO Auto-generated method stub
return apk_list.size();
} @Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return apk_list.get(position);
} @Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ApkEntity entity = apk_list.get(position);
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.item_layout, null);
holder.name_tv = (TextView) convertView
.findViewById(R.id.item3_apkname);
holder.des_tv = (TextView) convertView
.findViewById(R.id.item3_apkdes);
holder.info_tv = (TextView) convertView
.findViewById(R.id.item3_apkinfo);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.name_tv.setText(entity.getName());
holder.des_tv.setText(entity.getDes());
holder.info_tv.setText(entity.getInfo());
return convertView;
} class ViewHolder {
TextView name_tv;
TextView des_tv;
TextView info_tv;
}
}

  activity_main.xml:

<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="com.example.listviewrefreshdemo.MainActivity" > <com.example.listviewrefreshdemo.RefreshListView
android:id="@+id/listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:cacheColorHint="#00000000"
android:dividerHeight="5dip" /> </RelativeLayout>

  布局文件还有header.xml和item_layout.xml,就不粘贴了,想看的可以去下我的源代码,下边有下载链接。。

二、代码逻辑

1.自定义状态:PULL下拉状态,RELESE释放状态,REFLASHING刷新状态

2. AbsListView的触摸事件:

下拉的时候设置startY(开始滑动时的位置),之后就是不断的滑动过程,滑动的过程中,用自定义的onMove方法改变状态和header界面(下拉刷新,释放刷新,刷新中);

刷新:

case MotionEvent.ACTION_UP: //抬起
       if (state == RELESE) { //释放
         state = REFLASHING; //正在刷新
        reflashViewByState();// 加载最新数据;

reflashListener.onReflash(); //在回调接口刷新  }

3.自定义的move时判断状态信息:

下拉->释放:sapce > headerHeight+30 判断距离,距离够了就改变状态:释放状态,释放更新

	int sapce = tempY-startY;  //移动的距离
int topPadding = sapce - headerHeight; //移动过程中不断设置topPadding
switch (state) {
case NONE: // 正常状态;
if(sapce>0){
state = PULL; // 提示下拉状态
reflashViewByState();
}
break;
case PULL: // 提示下拉状态;
topPadding(topPadding); //不断设置上边距
if(sapce > headerHeight+30
&& scrollState == SCROLL_STATE_TOUCH_SCROLL){
state = RELESE; // 提示释放状态;
reflashViewByState();
} break;
case RELESE: // 提示释放状态;
topPadding(topPadding);
if(sapce<headerHeight+30){
state = PULL;
reflashViewByState();
}else if(sapce <= 0){
state = NONE;
isRemark = false;
reflashViewByState();
}
break;

    ok。。代码很简单。。。

Demo源代码下载:http://download.csdn.net/detail/jycboy/9588195

附一篇很好的博文:Android 下拉刷新框架实现:http://blog.csdn.net/leehong2005/article/details/12567757

转发请注明出处:http://www.cnblogs.com/jycboy/p/5712620.html

Android--ListView下拉刷新的更多相关文章

  1. Android ListView下拉刷新时卡的问题解决小技巧

    问题:ListView下拉刷新时看上去非常的卡 解决方案: 在BaseAdapter的getView方法中,有三个参数 public View getView(int position, View c ...

  2. Android listview下拉刷新 SwipeRefreshLayout

    今天在Google+上看到了SwipeRefreshLayout这个名词,遂搜索了下,发现竟然是刚刚google更新sdk新增加的一个widget,于是赶紧抢先体验学习下. SwipeRefreshL ...

  3. android ListView下拉刷新 上拉加载更多

    背景 最近在公司的项目中要使用到ListView的下拉刷新和上拉加载更多(貌似现在是个项目就有这个功能!哈哈),其实这个东西GitHub上很多,但是我感觉那些框架太大,而且我这个项目只用到了ListV ...

  4. Android—自定义控件实现ListView下拉刷新

    这篇博客为大家介绍一个android常见的功能——ListView下拉刷新(参考自他人博客,网址忘记了,阅读他的代码自己理解注释的,希望能帮助到大家): 首先下拉未松手时候手机显示这样的界面: 下面的 ...

  5. 【转载】Android中ListView下拉刷新的实现

    在网上看到一个下拉刷新的例子,很的很棒,转载和更多的人分享学习 原文:http://blog.csdn.net/loongggdroid/article/details/9385535 ListVie ...

  6. Android中ListView下拉刷新的实现

    ListView中的下拉刷新是非常常见的,也是经常使用的,看到有很多同学想要,那我就整理一下,供大家参考.那我就不解释,直接上代码了. 这里需要自己重写一下ListView,重写代码如下: packa ...

  7. Xamarin. Android实现下拉刷新功能

    PS:发现文章被其他网站或者博客抓取后发表为原创了,给图片加了个水印 下拉刷新功能在安卓和iOS中非常常见,一般实现这样的功能都是直接使用第三方的库,网上能找到很多这样的开源库.然而在Xamarin. ...

  8. ListView下拉刷新

    本内容为复制代码: 一.自定义ListView控件: package com.xczl.smart.view; import java.util.Date; import com.suliang.R; ...

  9. ListView下拉刷新、上拉载入更多之封装改进

    在Android中ListView下拉刷新.上拉载入更多示例一文中,Maxwin兄给出的控件比较强大,前面有详细介绍,但是有个不足就是,里面使用了一些资源文件,包括图片,String,layout,这 ...

  10. Android智能下拉刷新加载框架—看这些就够了

    一些值得学习的几个下拉刷新上拉加载开源库 Android智能下拉刷新框架-SmartRefreshLayout 支持所有的 View(AbsListView.RecyclerView.WebView. ...

随机推荐

  1. C#中string.format的格式和用法

    String.Format 方法的几种定义: String.Format (String, Object) 将指定的 String 中的格式项替换为指定的 Object 实例的值的文本等效项. Str ...

  2. Elasticsearch增删改查 之 —— Delete删除

    删除文档也算是常用的操作了...如果把Elasticsearch当做一款普通的数据库,那么删除操作自然就很常用了.如果仅仅是全文检索,可能就不会太常用到删除. Delete API 删除API,可以根 ...

  3. DirectShow .Net 实现视频

    DirectShow .Net 实现视频 .获取视频采集设备IBaseFilter接口对象的方法 //获取所有视频设备名称 public ArrayList GetVideoInputDevice() ...

  4. jQuery实用的语法总结

    1.关于页面元素的引用 通过jquery的$()引用元素包括通过id.class.元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用do ...

  5. EF更新,数据库值变化,前台页面并不变化,刷新也不变化,重新运行程序则变化----开发中遇到的问题(已解决)

    首先说一下我遇到这个情况的代码情景,首先上错误代码 UserInfo userInfo = Session["UserInfo"] as UserInfo; ); 这段代码所呈现的 ...

  6. 如何获取配置文件Web.config的AppSetting节点数据

    ConfigurationManager必须要先在工程里添加system.configuration.dll程序集的引用. 1 System.Configuration.ConfigurationMa ...

  7. qt 自动产生 Guid 方法

    strcpy(cmd->uid,QUuid::createUuid().toString().toStdString().c_str());

  8. Delphi Mac App 名称支持国际化多语显示

    作用:在 OSX 图标下方显示 App 中文繁体或简体的名称(系统自动选取) 适用:XE7, XE8 for OSX 操作: 创建一个新工程. 在工程目录下创建二个文件夹(zh_??.lproj)文件 ...

  9. 优秀的技术Leader

    在一个"情怀"已经泛滥的年代里,任何拿着"情怀"出来说事的人都不太受待见.犀利者会吐槽:"我早已看穿了一切". 但你是否想过,如果这世界所有 ...

  10. MongoDB-query查询接口

    在上一篇中简要使用了C# 对MongoDB进行数据操作,这里补充一些MongoDB query查询条件文档: Query.All("name", "a",&qu ...