Android ListView列表 重新整理和載入更多
阿新 • • 發佈:2019-02-11
上下拉實現重新整理和載入更多的ListView,如下:
[java] view plaincopyprint?- 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
- *
- */
- publicclass DynamicListView extends ListView implements OnScrollListener {
- /**
- * 監聽器
- * 監聽控制元件的重新整理或者載入更多事件
- * 所有的條目事件都會有一個偏移量,也就是position應該減1才是你介面卡中的條目
- * @author RobinTang
- *
- */
- publicinterface DynamicListViewListener {
- /**
- *
- * @param dynamicListView
- * @param isRefresh 為true的時候代表的是重新整理,為false的時候代表的是載入更多
- * @return true:重新整理或者載入更多動作完成,重新整理或者載入更多的動畫自動消失 false:重新整理或者載入更多為完成,需要在資料載入完成之後去呼叫控制元件的doneRefresh()或者doneMore()方法
- */
- publicboolean onRefreshOrMore(DynamicListView dynamicListView, boolean isRefresh);
- }
- /**
- * 狀態控制元件(StatusView,列表頭上和底端的)的狀態列舉
- * @author RobinTang
- *
- */
- enum RefreshStatus {
- none, normal, willrefresh, refreshing
- }
- /**
- * 狀態控制元件
- * @author RobinTang
- *
- */
- class StatusView extends LinearLayout {
- publicint height;
- publicint 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);
- }
- privatevoid 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;
- }
- publicvoid 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();
- }
- }
- privatevoid 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 正在重新整理(或載入)的字串
- */
- publicvoid setStatusStrings(String normalString, String willrefreshString, String refreshingString){
- this.normalString = normalString;
- this.willrefreshString = willrefreshString;
- this.refreshingString = refreshingString;
- this.refreshStatusString();
- }
- }
- private StatusView refreshView;
- private StatusView moreView;
- privateint itemFlag = -1;
- privateboolean isRecorded = false;
- privateint downY = -1;
- privatefinalfloat minTimesToRefresh = 1.5f;
- privatefinalstaticint ITEM_FLAG_FIRST = 1;
- privatefinalstaticint ITEM_FLAG_NONE = 0;
- privatefinalstaticint ITEM_FLAG_LAST = -1;
- // 兩個監聽器
- private DynamicListViewListener onRefreshListener;
- private DynamicListViewListener onMoreListener;
- // 滾動到低端的時候是否自動載入更多
- privateboolean 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);
- }
- privatevoid 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;
- }
- publicvoid setOnRefreshListener(DynamicListViewListener onRefreshListener) {
- this.onRefreshListener = onRefreshListener;
- }
- public DynamicListViewListener getOnMoreListener() {
- return onMoreListener;
- }
- publicvoid setOnMoreListener(DynamicListViewListener onMoreListener) {
- this.onMoreListener = onMoreListener;
- }
- // 設定
- publicboolean isDoMoreWhenBottom() {
- return doMoreWhenBottom;
- }
- publicvoid setDoMoreWhenBottom(boolean doMoreWhenBottom) {
- this.doMoreWhenBottom = doMoreWhenBottom;
- }
- @Override
- publicvoid onScroll(AbsListView l, int t, int oldl, int count) {
- // log("%d %d %d", t, oldl, count);
- if (t == 0)
- itemFlag = ITEM_FLAG_FIRST;
- elseif ((t + oldl) == count){
- itemFlag = ITEM_FLAG_LAST;
- if(doMoreWhenBottom && onMoreListener != null && moreView.getRefreshStatus() != RefreshStatus.refreshing){
- doMore();
- }
- }
- else {
- itemFlag = ITEM_FLAG_NONE;
- // isRecorded = false;
- }
- }
- @Override
- publicvoid onScrollStateChanged(AbsListView arg0, int arg1) {
- }
- @Override
- publicboolean 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();
- } elseif (refreshView.getRefreshStatus() == RefreshStatus.normal) {
- refreshView.setPadding(0, -1 * refreshView.height, 0, 0);
- }
- if (onMoreListener != null && moreView.getRefreshStatus() == RefreshStatus.willrefresh) {
- doMore();
- } elseif (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);
- } elseif (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);
- } elseif(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;
- }
- returnsuper.onTouchEvent(ev);
- }
- /**
- * 開始重新整理
- */
- privatevoid doRefresh(){
- // log("開始重新整理");
- refreshView.setRefreshStatus(RefreshStatus.refreshing);
- refreshView.setPadding(0, 0, 0, 0);
- if(onRefreshListener.onRefreshOrMore(this, true))
- doneRefresh();
- }
- /**
- * 開始載入更多
- */
- privatevoid doMore(){
- // log("載入更多");
- moreView.setRefreshStatus(RefreshStatus.refreshing);
- moreView.setPadding(0, 0, 0, 0);
- if(onMoreListener.onRefreshOrMore(this, false))
- doneMore();
- }
- /**
- * 重新整理完成之後呼叫,用於取消重新整理的動畫
- */
- publicvoid doneRefresh() {
- // log("重新整理完成!");
- refreshView.setRefreshStatus(RefreshStatus.normal);
- refreshView.setPadding(0, -1 * refreshView.height, 0, 0);
- }
- /**
- * 載入更多完成之後呼叫,用於取消載入更多的動畫
- */
- publicvoid 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));
- // }
- }
使用例子: [java] view plaincopyprint?
- 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")
- publicclass MainActivity extends Activity implements DynamicListViewListener {
- DynamicListView listView;
- ArrayList<String> data;
- ArrayAdapter<String> adapter;
- // 用於重新整理控制元件狀態
- Handler handler = new Handler() {
- @Override
- publicvoid handleMessage(Message msg) {
- if (msg.what == 0) {
- adapter.notifyDataSetChanged();
- listView.doneRefresh();
- Toast.makeText(MainActivity.this, "新載入"+msg.arg1+"條資料!", Toast.LENGTH_LONG).show();
- } elseif (msg.what == 1) {
- adapter.notifyDataSetChanged();
- listView.doneMore();
- } else {
- super.handleMessage(msg);
- }
- }
- };
- @Override
- protectedvoid 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
- publicvoid 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
- publicboolean onRefreshOrMore(DynamicListView dynamicListView, boolean isRefresh) {
- if (isRefresh) {
- new Thread(new Runnable() {
- @Override
- publicvoid 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
- publicvoid 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();
- }
- returnfalse;
- }
- }
截圖: