当前位置: 首页 > 编程笔记 >

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

温嘉玉
2023-03-14
本文向大家介绍Android开发之ListView列表刷新和加载更多实现方法,包括了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程序设计有所帮助。

 类似资料:
  • 本文向大家介绍Android ListView实现上拉加载更多和下拉刷新功能,包括了Android ListView实现上拉加载更多和下拉刷新功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家介绍了Android ListView下拉刷新功能的实现方法和功能,供大家参考,具体内容如下 1、ListView优化方式 界面缓存:ViewHolder+convertView 分页加载:上拉刷新

  • 本文向大家介绍Android中Listview下拉刷新和上拉加载更多的多种实现方案,包括了Android中Listview下拉刷新和上拉加载更多的多种实现方案的使用技巧和注意事项,需要的朋友参考一下  listview经常结合下来刷新和上拉加载更多使用,本文总结了三种常用到的方案分别作出说明。      方案一:添加头布局和脚布局         android系统为listview提供了addf

  • 本文向大家介绍Android实现上拉加载更多以及下拉刷新功能(ListView),包括了Android实现上拉加载更多以及下拉刷新功能(ListView)的使用技巧和注意事项,需要的朋友参考一下 首先为大家介绍Andorid5.0原生下拉刷新简单实现。 先上效果图; 相对于上一个19.1.0版本中的横条效果好看了很多。使用起来也很简单。 几行代码就可以实现下拉刷新,效果也还不错,不用引入第三方ja

  • 本文向大家介绍Android ExpandableListView实现下拉刷新和加载更多效果,包括了Android ExpandableListView实现下拉刷新和加载更多效果的使用技巧和注意事项,需要的朋友参考一下 支持下拉刷新和加载更多的ExpandableListView,供大家参考,具体内容如下 模拟器有点卡,滑动的时候鼠标不方便 怎么用: XML中声明 UI中配置下拉刷新的回调以及是否

  • 本文向大家介绍Android中ListView下拉刷新的实现方法,包括了Android中ListView下拉刷新的实现方法的使用技巧和注意事项,需要的朋友参考一下 ListView中的下拉刷新是非常常见的,也是经常使用的,看到有很多同学想要,那我就整理一下,供大家参考。那我就不解释,直接上代码了。 这里需要自己重写一下ListView,重写代码如下: 重写完ListView之后,在布局文件中是这么

  • 本文向大家介绍Android XListView下拉刷新和上拉加载更多,包括了Android XListView下拉刷新和上拉加载更多的使用技巧和注意事项,需要的朋友参考一下 市面上有好多的类比ListView刷新数据的开源框架,如:v4包自带的SwipeRefreshLayout ,以及集ListView、GridView甚至WebView于一身的Pulltorefresh等等。前述的两个开源框