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

 更新时间:2015年06月26日 09:54:44   转载 作者:RobinTang  
这篇文章主要介绍了Android开发之ListView列表刷新和加载更多实现方法,实例分析了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程序设计有所帮助。

相关文章

  • Android使用TextView,设置onClick属性无效的解决方法

    Android使用TextView,设置onClick属性无效的解决方法

    下面小编就为大家带来一篇Android使用TextView,设置onClick属性无效的解决方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • android中对文件加密解密的实现

    android中对文件加密解密的实现

    本文主要介绍了android中对文件加密解密的实现,文件加密现在的应用很广,有需要的朋友可以了解一下。
    2016-10-10
  • Android封装MVP实现登录注册功能

    Android封装MVP实现登录注册功能

    这篇文章主要为大家详细介绍了Android封装MVP实现登录注册功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Andorid 系统实现多种开机动画和logo切换功能

    Andorid 系统实现多种开机动画和logo切换功能

    这篇文章主要介绍了Andorid 系统实现多种开机动画和logo切换功能,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-12-12
  • 详解Android UI更新的几种方法

    详解Android UI更新的几种方法

    本篇文章主要介绍了Android UI更新的几种方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Android自定义View Flyme6的Viewpager指示器

    Android自定义View Flyme6的Viewpager指示器

    这篇文章主要为大家详细介绍了Android自定义View Flyme6的Viewpager指示器,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • Android-App增量更新的使用姿势

    Android-App增量更新的使用姿势

    增量更新根据字面理解就是下载增加的那部分来达到更新的目获取旧的Apk安装包的签名和已合并成新的Apk安装包的签名,对比签名是否一致当你下载差异文件时,可以让服务器给你返回新的Apk合并成功后文件的md5,当你合并成功后,通过校验文件的md5值,达到校验文件完整性。
    2016-04-04
  • Android 安全退出应用程序的方法总结

    Android 安全退出应用程序的方法总结

    这篇文章主要介绍了Android 安全退出应用程序的方法总结的相关资料,需要的朋友可以参考下
    2017-03-03
  • Android实现发送短信功能实例详解

    Android实现发送短信功能实例详解

    这篇文章主要介绍了Android实现发送短信功能的方法,结合实例形式较为详细的分析了Android实现发送短信的原理、步骤与相关实现技巧,需要的朋友可以参考下
    2016-02-02
  • 详解Android中Notification通知提醒

    详解Android中Notification通知提醒

    这篇文章主要为大家介绍了Android中Notification通知提醒,本文演示了普通的通知和自定义视图通知
    2016-01-01

最新评论