Android开发之ListView列表刷新和加载更多实现方法

本文实例讲述了Android开发之ListView列表刷新和加载更多实现方法。分享给大家供大家参考。具体如下:

上下拉实现刷新和加载更多的ListView,如下:

package com.sin.android.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
 * 动态刷新和加载数据ListView
 * @author RobinTang
 *
 */
public class DynamicListView extends ListView implements OnScrollListener {
  /**
   * 监听器
   * 监听控件的刷新或者加载更多事件
   * 所有的条目事件都会有一个偏移量,也就是position应该减1才是你适配器中的条目
   * @author RobinTang
   *
   */
  public interface DynamicListViewListener {
    /**
     *
     * @param dynamicListView
     * @param isRefresh 为true的时候代表的是刷新,为false的时候代表的是加载更多
     * @return true:刷新或者加载更多动作完成,刷新或者加载更多的动画自动消失 false:刷新或者加载更多为完成,需要在数据加载完成之后去调用控件的doneRefresh()或者doneMore()方法
     */
    public boolean onRefreshOrMore(DynamicListView dynamicListView, boolean isRefresh);
  }
  /**
   * 状态控件(StatusView,列表头上和底端的)的状态枚举
   * @author RobinTang
   *
   */
  enum RefreshStatus {
    none, normal, willrefresh, refreshing
  }
  /**
   * 状态控件
   * @author RobinTang
   *
   */
  class StatusView extends LinearLayout {
    public int height;
    public int width;
    private ProgressBar progressBar = null;
    private TextView textView = null;
    private RefreshStatus refreshStatus = RefreshStatus.none;
    private String normalString = "下拉刷新";
    private String willrefreshString = "松开刷新";
    private String refreshingString = "正在刷新";
    public StatusView(Context context, AttributeSet attrs) {
      super(context, attrs);
      initThis(context);
    }
    public StatusView(Context context) {
      super(context);
      initThis(context);
    }
    private void initThis(Context context) {
      this.setOrientation(LinearLayout.HORIZONTAL);
      this.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
      progressBar = new ProgressBar(context);
      progressBar.setLayoutParams(new LinearLayout.LayoutParams(30, 30));
      textView = new TextView(context);
      textView.setPadding(5, 0, 0, 0);
      this.addView(progressBar);
      this.addView(textView);
      int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
      int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
      this.measure(w, h);
      height = this.getMeasuredHeight();
      width = this.getMeasuredWidth();
      this.setRefreshStatus(RefreshStatus.normal);
    }
    public RefreshStatus getRefreshStatus() {
      return refreshStatus;
    }
    public void setRefreshStatus(RefreshStatus refreshStatus) {
      if (this.refreshStatus != refreshStatus) {
        this.refreshStatus = refreshStatus;
        if(refreshStatus == RefreshStatus.refreshing){
          this.progressBar.setVisibility(View.VISIBLE);
        }
        else{
          this.progressBar.setVisibility(View.GONE);
        }
        refreshStatusString();
        this.invalidate();
      }
    }
    private void refreshStatusString() {
      switch (refreshStatus) {
      case normal:
        textView.setText(normalString);
        progressBar.setProgress(0);
        break;
      case willrefresh:
        textView.setText(willrefreshString);
        break;
      case refreshing:
        textView.setText(refreshingString);
        break;
      default:
        break;
      }
    }
    /**
     * 设置状态字符串
     * @param normalString 平时的字符串
     * @param willrefreshString 松开后刷新(或加载)的字符串
     * @param refreshingString 正在刷新(或加载)的字符串
     */
    public void setStatusStrings(String normalString, String willrefreshString, String refreshingString){
      this.normalString = normalString;
      this.willrefreshString = willrefreshString;
      this.refreshingString = refreshingString;
      this.refreshStatusString();
    }
  }
  private StatusView refreshView;
  private StatusView moreView;
  private int itemFlag = -1;
  private boolean isRecorded = false;
  private int downY = -1;
  private final float minTimesToRefresh = 1.5f;
  private final static int ITEM_FLAG_FIRST = 1;
  private final static int ITEM_FLAG_NONE = 0;
  private final static int ITEM_FLAG_LAST = -1;
  // 两个监听器
  private DynamicListViewListener onRefreshListener;
  private DynamicListViewListener onMoreListener;
  // 滚动到低端的时候是否自动加载更多
  private boolean doMoreWhenBottom = false;
  public DynamicListView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    initThis(context);
  }
  public DynamicListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initThis(context);
  }
  public DynamicListView(Context context) {
    super(context);
    initThis(context);
  }
  private void initThis(Context context) {
    refreshView = new StatusView(context);
    moreView = new StatusView(context);
    refreshView.setStatusStrings("继续下拉刷新数据...", "松开之后刷新数据...", "正在刷新数据...");
    moreView.setStatusStrings("继续上拉加载数据...", "松开之后加载数据...", "正在加载数据...");
    this.addHeaderView(refreshView, null, false);
    this.addFooterView(moreView, null, false);
    this.setOnScrollListener(this);
    doneRefresh();
    doneMore();
  }
  // 监听器操作
  public DynamicListViewListener getOnRefreshListener() {
    return onRefreshListener;
  }
  public void setOnRefreshListener(DynamicListViewListener onRefreshListener) {
    this.onRefreshListener = onRefreshListener;
  }
  public DynamicListViewListener getOnMoreListener() {
    return onMoreListener;
  }
  public void setOnMoreListener(DynamicListViewListener onMoreListener) {
    this.onMoreListener = onMoreListener;
  }
  // 设置
  public boolean isDoMoreWhenBottom() {
    return doMoreWhenBottom;
  }
  public void setDoMoreWhenBottom(boolean doMoreWhenBottom) {
    this.doMoreWhenBottom = doMoreWhenBottom;
  }
  @Override
  public void onScroll(AbsListView l, int t, int oldl, int count) {
    // log("%d %d %d", t, oldl, count);
    if (t == 0)
      itemFlag = ITEM_FLAG_FIRST;
    else if ((t + oldl) == count){
      itemFlag = ITEM_FLAG_LAST;
      if(doMoreWhenBottom && onMoreListener != null && moreView.getRefreshStatus() != RefreshStatus.refreshing){
          doMore();
      }
    }
    else {
      itemFlag = ITEM_FLAG_NONE;
//     isRecorded = false;
    }
  }
  @Override
  public void onScrollStateChanged(AbsListView arg0, int arg1) {
  }
  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
    case MotionEvent.ACTION_DOWN:
      if (isRecorded == false && (itemFlag == ITEM_FLAG_FIRST && onRefreshListener != null && refreshView.getRefreshStatus() == RefreshStatus.normal || itemFlag == ITEM_FLAG_LAST && onMoreListener != null && moreView.getRefreshStatus() == RefreshStatus.normal)) {
        downY = (int) ev.getY(0);
        isRecorded = true;
//       log("按下,记录:%d flag:%d", downY, itemFlag);
      }
      break;
    case MotionEvent.ACTION_UP: {
      isRecorded = false;
      if (onRefreshListener != null && refreshView.getRefreshStatus() == RefreshStatus.willrefresh) {
        doRefresh();
      } else if (refreshView.getRefreshStatus() == RefreshStatus.normal) {
        refreshView.setPadding(0, -1 * refreshView.height, 0, 0);
      }
      if (onMoreListener != null && moreView.getRefreshStatus() == RefreshStatus.willrefresh) {
        doMore();
      } else if (moreView.getRefreshStatus() == RefreshStatus.normal) {
        moreView.setPadding(0, 0, 0, -1 * moreView.height);
      }
      break;
    }
    case MotionEvent.ACTION_MOVE: {
      if (isRecorded == false && (itemFlag == ITEM_FLAG_FIRST && onRefreshListener != null && refreshView.getRefreshStatus() == RefreshStatus.normal ||
          itemFlag == ITEM_FLAG_LAST && onMoreListener != null && moreView.getRefreshStatus() == RefreshStatus.normal)) {
        downY = (int) ev.getY(0);
        isRecorded = true;
//       log("按下,记录:%d flag:%d", downY, itemFlag);
      } else if (isRecorded) {
        int nowY = (int) ev.getY(0);
        int offset = nowY - downY;
        if (offset > 0 && itemFlag == ITEM_FLAG_FIRST) {
          // 下拉
          setSelection(0);
          if (offset >= (minTimesToRefresh * refreshView.height)) {
            refreshView.setRefreshStatus(RefreshStatus.willrefresh);
          } else {
            refreshView.setRefreshStatus(RefreshStatus.normal);
          }
          refreshView.setPadding(0, -1 * (refreshView.height - offset), 0, 0);
        } else if(itemFlag == ITEM_FLAG_LAST){
          // 上拉
          setSelection(this.getCount());
          if (offset <= -1 * (minTimesToRefresh * moreView.height)) {
            moreView.setRefreshStatus(RefreshStatus.willrefresh);
          } else {
            moreView.setRefreshStatus(RefreshStatus.normal);
          }
          moreView.setPadding(0, 0, 0, -1 * (moreView.height + offset));
        }
//       log("位移:%d", offset);
      }
      break;
    }
    default:
      break;
    }
    return super.onTouchEvent(ev);
  }
  /**
   * 开始刷新
   */
  private void doRefresh(){
//   log("开始刷新");
    refreshView.setRefreshStatus(RefreshStatus.refreshing);
    refreshView.setPadding(0, 0, 0, 0);
    if(onRefreshListener.onRefreshOrMore(this, true))
      doneRefresh();
  }
  /**
   * 开始加载更多
   */
  private void doMore(){
//   log("加载更多");
    moreView.setRefreshStatus(RefreshStatus.refreshing);
    moreView.setPadding(0, 0, 0, 0);
    if(onMoreListener.onRefreshOrMore(this, false))
      doneMore();
  }
  /**
   * 刷新完成之后调用,用于取消刷新的动画
   */
  public void doneRefresh() {
//   log("刷新完成!");
    refreshView.setRefreshStatus(RefreshStatus.normal);
    refreshView.setPadding(0, -1 * refreshView.height, 0, 0);
  }
  /**
   * 加载更多完成之后调用,用于取消加载更多的动画
   */
  public void doneMore() {
//   log("加载完成!");
    moreView.setRefreshStatus(RefreshStatus.normal);
    moreView.setPadding(0, 0, 0, -1 * moreView.height);
  }
  /**
   * 获取刷新的状态
   * @return 一般 将要刷新 刷新完成
   */
  public RefreshStatus getRefreshStatus(){
    return refreshView.getRefreshStatus();
  }
  /**
   * 获取加载更多的状态
   * @return 一般 将要加载 加载完成
   */
  public RefreshStatus getMoreStatus(){
    return moreView.getRefreshStatus();
  }
// private void log(Object obj) {
//   log("%s", obj.toString());
// }
//
// private void log(String format, Object... args) {
//   Log.i("DynamicListView", String.format(format, args));
// }
}

使用例子:

package com.sin.android.ui;
import java.util.ArrayList;
import java.util.Date;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import com.sin.android.ui.DynamicListView.DynamicListViewListener;
@SuppressLint("HandlerLeak")
public class MainActivity extends Activity implements DynamicListViewListener {
  DynamicListView listView;
  ArrayList<String> data;
  ArrayAdapter<String> adapter;
  // 用于刷新控件状态
  Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      if (msg.what == 0) {
        adapter.notifyDataSetChanged();
        listView.doneRefresh();
        Toast.makeText(MainActivity.this, "新加载"+msg.arg1+"条数据!", Toast.LENGTH_LONG).show();
      } else if (msg.what == 1) {
        adapter.notifyDataSetChanged();
        listView.doneMore();
      } else {
        super.handleMessage(msg);
      }
    }
  };
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    listView = new DynamicListView(this);
    setContentView(listView);
    data = new ArrayList<String>();
    for (int i = 1; i < 10; ++i) {
      data.add("原始数据" + i);
    }
    adapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, data);
    listView.setAdapter(adapter);
    listView.setOnItemClickListener(new OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        Log.i("",data.get(arg2-1));
      }
    });
    listView.setDoMoreWhenBottom(false);  // 滚动到低端的时候不自己加载更多
    listView.setOnRefreshListener(this);
    listView.setOnMoreListener(this);
  }
  @Override
  public boolean onRefreshOrMore(DynamicListView dynamicListView, boolean isRefresh) {
    if (isRefresh) {
      new Thread(new Runnable() {
        @Override
        public void run() {
          // 刷新
          ArrayList<String> temp = new ArrayList<String>();
          for (int i = 0; i < 3; ++i) {
            temp.add(0, new Date().toLocaleString());
            try {
              Thread.sleep(1000);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          synchronized (data) {
            data.addAll(0, temp);
          }
          Message message = new Message();
          message.what = 0;
          message.arg1 = temp.size();
          handler.sendMessage(message);
        }
      }).start();
    } else {
      new Thread(new Runnable() {
        @Override
        public void run() {
          // 加载更多
          ArrayList<String> temp = new ArrayList<String>();
          for (int i = 0; i < 3; ++i) {
            temp.add(new Date().toLocaleString());
            try {
              Thread.sleep(1000);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          synchronized (data) {
            data.addAll(temp);
          }
          handler.sendEmptyMessage(1);
        }
      }).start();
    }
    return false;
  }
}

运行截图如下:

希望本文所述对大家的Android程序设计有所帮助。

(0)

相关推荐

  • ASP.NET中ListView(列表视图)的使用前台绑定附源码

    1.A,运行效果图 1.B,源代码 复制代码 代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="DropLvw.aspx.cs" Inherits="DropLvw" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "htt

  • Android ExpandableListView展开列表控件使用实例

    你是否觉得手机QQ上的好友列表那个控件非常棒? 不是..... 那也没关系,学多一点知识对自己也有益无害. 那么我们就开始吧. 展开型列表控件, 原名ExpandableListView 是普通的列表控件进阶版, 可以自由的把列表进行收缩, 非常的方便兼好看. 首先看看我完成的截图, 虽然界面不漂亮, 但大家可以自己去修改界面. 该控件需要一个主界面XML 一个标题界面XML及一个列表内容界面XML 首先我们来看看 mian.xml 主界面 复制代码 代码如下: //该界面非常简单, 只要一个E

  • android开发教程之使用listview显示qq联系人列表

    首先还是xml布局文件,在其中添加ListView控件: 主布局layout_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 ListView实现简单列表功能

    ListView如何实现简单列表,供大家参考,具体内容如下 效果图: 啥也没干的ListView张这样: fry.Activity01 package fry; import com.example.ListView.R; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.

  • android二级listview列表实现代码

    今天来实现以下大众点评客户端的横向listview二级列表,先看一下样式.  这种横向的listview二级列表在手机软件上还不太常见,但是使用过平板的都应该知道,在平板上市比较常见的.可能是因为平板屏幕比较大,而且也能展现更多的内容. 下面来看一下我的实现步骤. 首先自定义一个listview,代码如下: 复制代码 代码如下: public class MyListView extends ListView implements Runnable { private float mLastDo

  • listview控件实现点击列表头进行listview排序示例分享

    复制代码 代码如下: using System;using System.Collections;using System.Windows.Forms;namespace Common{    /// <summary>    /// 对ListView点击列标题自动排序功能    /// </summary>    public class ListViewHelper    {        /// <summary>        /// 构造函数       

  • pp列表之分组ListView详解

    吸引用户的眼球,是我们至死不渝的追求:第一时间呈现最有价值的信息,简明大方,告诉客户,你的选择是多么的明智,这正是你寻觅已久的东西. 分组的应用场合还是很多的,有数据集合的地方往往要分组显示:分组的形式也很多,最常见的就是镶嵌在列表中,网上说的很多ExpandListView的也是一种.Android自带的通讯录中的联系人是按照拼音首字母(A,B,C,D......)分组分类的,效果如下:我们今天也是要实现这样类似的一个效果.1.样本数据:为了突出重点,直击要点,这里提供一个整理好的数据样本:

  • Android通过LIstView显示文件列表的两种方法介绍

    在Android中通过ListView显示SD卡中的文件列表一共有两种方法,一是:通过继承ListActivity显示;二是:利用BaseAdapter显示.BaseAdapter是一个公共基类适配器,用于对ListView和Spinner等 一些控件提供显示数据.下面是利用BaseAdapter类来实现通过LIstView显示SD卡的步骤: 1.main.xml界面设计,如下图 复制代码 代码如下: <?xml version="1.0" encoding="utf-

  • Android编程使用ListView实现数据列表显示的方法

    本文实例讲述了Android编程使用ListView实现数据列表显示的方法.分享给大家供大家参考,具体如下: 要将数据库中的数据列表显示在屏幕上,我们要使用ListView这个控件,当用户从数据库中取出数据时,要将数据绑定到显示控件上,如何绑定呢,我们需要创建适配器进行绑定,创建适配器有两种方式: 第一种是用SimpleAdapter创建(要求绑定的数据是List<HashMap<String, Object>>数据类型) 第二种是用SimpleCursorAdapter创建(要求

  • Android用ListView显示SDCard文件列表的小例子

    复制代码 代码如下: filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/ADASiteMaps/SigRecord";        File file=new File(filePath);        File[] files = file.listFiles(); 构造Adapter, 复制代码 代码如下: for(File mCurrentFile:files){       

随机推荐