注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

创新改变世界

you changed the world

 
 
 

日志

 
 

Android--ListView下拉刷新数据功能  

2013-03-27 15:57:02|  分类: android |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
文章来源:http://blog.sina.com.cn/s/blog_7575ed8b01013cnp.html
下拉滑动工单列表时(GridView/ListView实现)刷新最新数据,类似新浪微博中顶端下拉刷新数据功能。
在网上搜了一些解决方案,很多方法看起来很复杂,看了几个方案,选择了一个简单的,自己也修改了一下,实现起来比较好的与大家一起分享,相信大家以后会用的到(本篇先分享ListView的实现方式,下一篇在实现GridView的下拉刷新数据功能),乍一看比较长,大家细看一下,就知道比较简单了。
先把图依次展示一下吧(图中刷新了2次了所以时间会出现2个)


Android--ListView下拉刷新数据功能

Android--ListView下拉刷新数据功能

Android--ListView下拉刷新数据功能




//复写了ListView的带下拉刷新功能的PullToRefreshListView
package src.com.lyg.refreshlist;
import java.text.SimpleDateFormat;
import java.util.Date;
import src.com.lyg.R;
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.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
public class PullToRefreshListView extends ListView implements OnScrollListener {

private static final String TAG = "listview";
private final static int RELEASE_To_REFRESH = 0; // 释放
private final static int PULL_To_REFRESH = 1;// 下拉刷新
private final static int REFRESHING = 2; // 正在刷新
private final static int DONE = 3; // 按下
private final static int LOADING = 4;
// 实际的padding的距离与界面上偏移距离的比例
private final static int RATIO = 3;
private LayoutInflater inflater;
private LinearLayout headView;
private TextView tipsTextview;
private TextView lastUpdatedTextView;
private ImageView arrowImageView;
private ProgressBar progressBar;
private RotateAnimation animation;
private RotateAnimation reverseAnimation;
// 用于保证startY的值在一个完整的touch事件中只被记录一次
private boolean isRecored;
private int headContentWidth;
private int headContentHeight;
private int startY;
private int firstItemIndex;
private int state;
private boolean isBack;
private OnRefreshListener refreshListener;
private boolean isRefreshable;

 
 public PullToRefreshListView(Context context) {  
     super(context);  
init(context);  
  }  
 
    public PullToRefreshListView(Context context, AttributeSet attrs) {  
       super(context, attrs);  
        init(context);  
    } 
   
   private void init(Context context) {  

// setCacheColorHint(context.getResources().getColor(R.color.transparent));

inflater = LayoutInflater.from(context);
// head 布局文件
headView = (LinearLayout) inflater.inflate(R.layout.head, null);
// 下拉箭头
arrowImageView = (ImageView) headView.findViewById(R.id.head_arrowImageView);
arrowImageView.setMinimumWidth(70);
arrowImageView.setMinimumHeight(50);
// 进度条
progressBar = (ProgressBar) headView.findViewById(R.id.head_progressBar);
// 下拉提示 刷新
tipsTextview = (TextView) headView.findViewById(R.id.head_tipsTextView);
//最新一次刷新时间
lastUpdatedTextView = (TextView)                          headView.findViewById(R.id.head_lastUpdatedTextView);
        //计算head的高宽
measureView(headView);
headContentHeight = headView.getMeasuredHeight();
headContentWidth = headView.getMeasuredWidth();
//初始状态是 隐藏掉head 布局
headView.setPadding(0, -1 * headContentHeight, 0, 0);
headView.invalidate();
         Log.v("size", "width:" + headContentWidth + " height:" + headContentHeight); 
         //list添加头文件
     addHeaderView(headView, null, false);  
     setOnScrollListener(this);
     //下拉以及恢复动画
     animation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f,RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
         animation.setInterpolator(new LinearInterpolator());  
         animation.setDuration(250);  
         animation.setFillAfter(true);  
        reverseAnimation = new RotateAnimation(-180, 0,  
                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,  
                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
       reverseAnimation.setInterpolator(new LinearInterpolator());  
       reverseAnimation.setDuration(200);  
       reverseAnimation.setFillAfter(true);  
       state = DONE;  
       isRefreshable = false;  
     }  
   public void onScroll(AbsListView arg0, int firstVisiableItem, int arg2, int arg3) {  
      firstItemIndex = firstVisiableItem;  
     }  
   public void onScrollStateChanged(AbsListView arg0, int arg1) {  
   }  

public boolean onTouchEvent(MotionEvent event) {

if (isRefreshable) {
switch (event.getAction()) {
// 在down时候记录当前Y的位置
case MotionEvent.ACTION_DOWN:
if (firstItemIndex == 0 && !isRecored) {
isRecored = true;
startY = (int) event.getY();
Log.v(TAG, "在down时候记录当前位置‘");
}
break;
case MotionEvent.ACTION_UP:
if (state != REFRESHING && state != LOADING) {
if (state == DONE) {
// 什么都不做
}
//由下拉刷新状态,到done状态
if (state == PULL_To_REFRESH) {
state = DONE;
changeHeaderViewByState();
Log.v(TAG, "由下拉刷新状态,到done状态");
}

if (state == RELEASE_To_REFRESH) {
state = REFRESHING;
changeHeaderViewByState();
onRefresh();
Log.v(TAG, "由松开刷新状态,到done状态");
}
}
isRecored = false;
isBack = false;
break;

case MotionEvent.ACTION_MOVE:
int tempY = (int) event.getY();
if (!isRecored && firstItemIndex == 0) {
Log.v(TAG, "在move时候记录下位置");
isRecored = true;
startY = tempY;
}
if (state != REFRESHING && isRecored && state != LOADING) {
// 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
// 可以松手去刷新了
if (state == RELEASE_To_REFRESH) {
setSelection(0);
// 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
if (((tempY - startY) / RATIO < headContentHeight)&& (tempY - startY) > 0) {
state = PULL_To_REFRESH;
changeHeaderViewByState();
Log.v(TAG, "由松开刷新状态转变到下拉刷新状态");
}
// 一下子推到顶了
else if (tempY - startY <= 0) {
state = DONE;
changeHeaderViewByState();
Log.v(TAG, "由松开刷新状态转变到done状态");
}
// 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步
else {
// 不用进行特别的操作,只用更新paddingTop的值就行了
}
}
// 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
if (state == PULL_To_REFRESH) {
setSelection(0);
// 下拉到可以进入RELEASE_TO_REFRESH的状态
if ((tempY - startY) / RATIO >= headContentHeight) {
state = RELEASE_To_REFRESH;
isBack = true;
changeHeaderViewByState();
Log.v(TAG, "由done或者下拉刷新状态转变到松开刷新");
}
// 上推到顶了
else if (tempY - startY <= 0) {
state = DONE;
changeHeaderViewByState();
Log.v(TAG, "由DOne或者下拉刷新状态转变到done状态");
}
}
// done状态下
if (state == DONE) {
if (tempY - startY > 0) {
state = PULL_To_REFRESH;
changeHeaderViewByState();
}
}
// 更新headView的size
if (state == PULL_To_REFRESH) {
headView.setPadding(0, -1 * headContentHeight
+ (tempY - startY) / RATIO, 0, 0);
}
// 更新headView的paddingTop
if (state == RELEASE_To_REFRESH) {
headView.setPadding(0, (tempY - startY) / RATIO- headContentHeight, 0, 0);
}
}
break;
}
}
return super.onTouchEvent(event);
}
    private void changeHeaderViewByState() {  
         switch (state) { 
         //松开刷新状态 
          case RELEASE_To_REFRESH:  
             arrowImageView.setVisibility(View.VISIBLE);  
            progressBar.setVisibility(View.GONE);  
            tipsTextview.setVisibility(View.VISIBLE);  
            lastUpdatedTextView.setVisibility(View.VISIBLE);      
            arrowImageView.clearAnimation();  
            arrowImageView.startAnimation(animation);      
             tipsTextview.setText("松开刷新");      
             Log.v(TAG, "当前状态,松开刷新");  
             break;  
             //下拉刷新
         case PULL_To_REFRESH:  
             progressBar.setVisibility(View.GONE);  
             tipsTextview.setVisibility(View.VISIBLE);  
             lastUpdatedTextView.setVisibility(View.VISIBLE);  
             arrowImageView.clearAnimation();  
              arrowImageView.setVisibility(View.VISIBLE);  
            // 是由RELEASE_To_REFRESH状态转变来的
              //箭头反转向上
           if (isBack) {  
                isBack = false;  
                arrowImageView.clearAnimation();  
                 arrowImageView.startAnimation(reverseAnimation);  
                 tipsTextview.setText("下拉刷新");  
            } else {  
                 tipsTextview.setText("下拉刷新");  
             }  
           Log.v(TAG, "当前状态,下拉刷新");  
           break;  
           //刷新中 状态
       case REFRESHING:      
             headView.setPadding(0, 0, 0, 0);      
            progressBar.setVisibility(View.VISIBLE);  
           arrowImageView.clearAnimation();  
           arrowImageView.setVisibility(View.GONE);  
           tipsTextview.setText("正在刷新...");  
            lastUpdatedTextView.setVisibility(View.VISIBLE);     
            Log.v(TAG, "当前状态,正在刷新...");  
            break; 
            //刷新完毕
        case DONE:  
           headView.setPadding(0, -1 * headContentHeight, 0, 0);  
           progressBar.setVisibility(View.GONE);  
            arrowImageView.clearAnimation();  
             arrowImageView.setImageResource(R.drawable.goicon);  
             tipsTextview.setText("下拉刷新");  
            lastUpdatedTextView.setVisibility(View.VISIBLE);      
             Log.v(TAG, "当前状态,done");  
            break;  
        }  
    }  
    public void setonRefreshListener(OnRefreshListener refreshListener) {  
         this.refreshListener = refreshListener;  
         isRefreshable = true;  
    }       
     public interface OnRefreshListener {  
         public void onRefresh();  
     }     
   public void onRefreshComplete() {  
        state = DONE;  
         SimpleDateFormat format=new SimpleDateFormat("yyyy年MM月dd日  HH:mm");  
         String date=format.format(new Date());  
        lastUpdatedTextView.setText("最近更新:" + date);  
        changeHeaderViewByState();  
     }  
     private void onRefresh() {  
       if (refreshListener != null) {  
            refreshListener.onRefresh();  
       }  
     }   
    // 此方法直接照搬自网络上的一个下拉刷新的demo,此处是“估计”headView的width以及height  
     private void measureView(View child) {  
        ViewGroup.LayoutParams p = child.getLayoutParams();  
           if (p == null) {  
                p = new ViewGroup.LayoutParams(  
                       ViewGroup.LayoutParams.FILL_PARENT,  
                        ViewGroup.LayoutParams.WRAP_CONTENT);  
            }  
         int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);  
           int lpHeight = p.height;  
            int childHeightSpec;  
            if (lpHeight > 0) {  
                childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);  
             } else {  
               childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);  
            }  
             child.measure(childWidthSpec, childHeightSpec);  
   }  
    public void setAdapter(BaseAdapter adapter) {  
        SimpleDateFormat format=new SimpleDateFormat("yyyy年MM月dd日  HH:mm");  
       String date=format.format(new Date());  
        lastUpdatedTextView.setText("最近更新:" + date);  
       super.setAdapter(adapter);  
     }  
}
//head.xml 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#ffffff">
<!-- 内容 --> 
   <RelativeLayout 
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" 
  android:id="@+id/head_contentLayout" 
  android:paddingLeft="30dp" 
  >  
  <!-- 箭头图像、进度条 --> 
   <FrameLayout 
   android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_alignParentLeft="true" 
   android:layout_centerVertical="true" 
  >  
   <!-- 箭头 --> 
   <ImageView 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_gravity="center" 
  android:src="@drawable/goicon" 
   android:id="@+id/head_arrowImageView" 
  />  
  <!-- 进度条 --> 
  <ProgressBar 
   android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
   style="?android:attr/progressBarStyleSmall" 
  android:layout_gravity="center" 
  android:id="@+id/head_progressBar"      
   android:visibility="gone" 
  />  
  </FrameLayout>  
  <!-- 提示、最近更新 --> 
   <LinearLayout 
   android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_centerHorizontal="true" 
   android:orientation="vertical" 
  android:gravity="center_horizontal" 
  >  
 <!-- 提示 --> 
  <TextView 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:text="下拉刷新" 
  android:textSize="15dp" 
   android:id="@+id/head_tipsTextView" 
  />  
  <!-- 最近更新 --> 
   <TextView 
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
   android:id="@+id/head_lastUpdatedTextView" 
   android:text="上次更新" 
   android:textSize="12dp" 
   />  
  </LinearLayout>  
  </RelativeLayout>  
</LinearLayout>

//activity 页面展示
package src.com.lyg.refreshlist;

import java.util.LinkedList;
import src.com.lyg.R;
import src.com.lyg.refreshlist.PullToRefreshListView.OnRefreshListener;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class PullToRefreshListViewActivity extends Activity {
private LinkedList<String> data;
private BaseAdapter adapter;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 模拟数据
data = new LinkedList<String>();
for (int i = 0; i < 10; i++) {
data.add(String.valueOf(i));
}
// 带下拉刷新功能复写了ListView的PullToRefreshListView
final PullToRefreshListView listView = (PullToRefreshListView)findViewById(R.id.order_form_list);
// 适配器
adapter = new BaseAdapter() {
public long getItemId(int position) {
return position;
}

public Object getItem(int position) {
return data.get(position);
}

public int getCount() {
return data.size();
}

public View getView(int position, View convertView, ViewGroup parent) {
convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null);
TextView textView = (TextView) convertView.findViewById(R.id.textView_item);
textView.setText(data.get(position));
return convertView;
}
};
listView.setAdapter(adapter);
// 下拉刷新监听
listView.setonRefreshListener(new OnRefreshListener() {
public void onRefresh() {
new AsyncTask<Void, Void, Void>() {
protected Void doInBackground(Void... params) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
data.addFirst("刷新后的内容");
return null;
}

@Override
protected void onPostExecute(Void result) {
adapter.notifyDataSetChanged();
listView.onRefreshComplete();
}
}.execute(null);
}
});
}
}

//activity里面的main.xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:text="List下拉刷新测试" />

    <src.com.lyg.refreshlist.PullToRefreshListView
                android:id="@+id/order_form_list"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:cacheColorHint="@android:color/transparent"
                android:listSelector="@drawable/left_list_xuanzhong"
                android:padding="1dip"
                android:divider="@drawable/dash_line_h_repeat"
                android:scrollingCache="false" >
            </src.com.lyg.refreshlist.PullToRefreshListView>
</LinearLayout>
  评论这张
 
阅读(434)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017