ListView上拉加载更多

本文介绍了ListView实现上拉加载更多的原理,详细讲解了监听滑动事件、OnScrollListener接口的使用,包括onScroll()和onScrollStateChanged()方法,以及如何通过addFooterView()添加加载指示器。同时,文中给出了实际操作步骤,包括布局设置、数据源绑定、回调接口实现以及Handler在异步加载中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 原理图: ListView在滑动的时候,会不断的传递三个值,这三个值为:

1 int firstVisibleItem

2 int visibleItemCount

3 int totalItemCount

原理图

2 监听ListView的滑动事件

1 实现OnScrollListener接口
public class MListView extends ListView implements OnScrollListener

覆写两个方法:

@Override
public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {}
2 onScroll()方法

第一个方法是判断onScroll方法是判断是否滑动到底部的重点,我们上拉加载更多的操作在这里完成。

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {
    if (firstVisibleItem + visibleItemCount == totalItemCount) {
        Log.i(TAG, "add more");
        if (callBack != null && !loading) {
            callBack.onAddMore();
            loading = true;
        }
    }
}

在这里设置一个回调接口,将加载更多数据的耗时操作交给接口。

interface MCallBack { void onAddMore(); }
private MCallBack callBack;
public void setCallBack(MCallBack callBack) {
    this.callBack = callBack;
}

在这里还有一个loading标识符,当开始加载更多的时候,无法再次上拉进行加载。
所以这里也要设置一个对外的方法,当加载完成之后,把loading复位。

public void setLoading(boolean loading) {
    this.loading = loading;
}
3 onScrollStateChanged()方法

这个方法是判断用户滑动的模式,源码中有提到:

 /**
 * The view is not scrolling. Note navigating the list using the trackball counts as
 * being in the idle state since these transitions are not animated.
 */
public static int SCROLL_STATE_IDLE = 0;

/**
 * The user is scrolling using touch, and their finger is still on the screen
 */
public static int SCROLL_STATE_TOUCH_SCROLL = 1;

/**
 * The user had previously been scrolling using touch and had performed a fling. The
 * animation is now coasting to a stop
 */
public static int SCROLL_STATE_FLING = 2;

1 SCROLL_STATE_IDLE 表示缓慢的滑动

2 SCROLL_STATE_TOUCH_SCROLL 表示正常的滑动

3 SCROLL_STATE_FLING 表示飞快的滑动

这里不多做讨论

4 addFooterView()方法

作用:加载更多,可以用一个菊花或者文字表示 “正在加载”,这个View就放在FooterView当中。

这个方法,在4.4版本之前的API中,只能在设置适配器之前调用。

而在4.4或者更高版本的API中,可以在任意地方调用。

footerView的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="horizontal"
    android:padding="16dp" >

    <TextView
        android:id="@+id/footer_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/add_more" />

</LinearLayout>
5 初始化方法:
private void initInflater(Context context) {
    mInflater = LayoutInflater.from(context);
    footerView = mInflater.inflate(R.layout.view4addmore, null);
    addFooterView(footerView);
    setOnScrollListener(this);
}
6 完整代码:
package com.pullupaddmore.main;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.AbsListView.OnScrollListener;
import com.granton.pullupaddmore.R;

public class MListView extends ListView implements OnScrollListener {

    private static final String TAG = "MListView";
    private LayoutInflater mInflater;
    private View footerView;

    private void initInflater(Context context) {
        mInflater = LayoutInflater.from(context);
        footerView = mInflater.inflate(R.layout.view4addmore, null);
        addFooterView(footerView);
        setOnScrollListener(this);
    }

    public MListView(Context context) {
        super(context);
        initInflater(context);
    }

    public MListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initInflater(context);
    }

    public MListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initInflater(context);
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    private boolean loading = false;

    public void setLoading(boolean loading) {
        this.loading = loading;
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        if (firstVisibleItem + visibleItemCount == totalItemCount) {
            Log.i(TAG, "add more");
            if (callBack != null && !loading) {
                callBack.onAddMore();
                loading = true;
            }
        }
    }

    public void setCallBack(MCallBack callBack) {
        this.callBack = callBack;
    }

    private MCallBack callBack;

    interface MCallBack {
        void onAddMore();
    }
}

3 实际使用:

1 在Activity或者Fragment的布局文件中加入:
<com.pullupaddmore.main.MListView
    android:id="@+id/listview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
2 获取ListView 绑定数据源:
getData();
mListView = (MListView) findViewById(R.id.listview);
mListView.setCallBack(MainActivity.this);
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, list);
mListView.setAdapter(adapter);

获取数据源getData():

private void getData() {
    list.add("new---------new1");
    list.add("2---------2new");
    list.add("3-----new----3");
    list.add("4-------new--4");
    list.add("5-----new----5");
    list.add("6-------new--6");
    list.add("7----new-----7");
    list.add("8-------new--8");
    list.add("9---------9new");
    list.add("10-new--------10");
    list.add("11----new-----11");
    list.add("12-------new--12");
    list.add("13---new------13");
}
3 activity实现ListView中的回调接口:

加载更多数据这类操作一定要放在子线程中

否则会引起界面卡顿或者直接报错

并且使用Handler来处理数据在界面上的更新。

public class MainActivity extends Activity implements MCallBack

@Override
public void onAddMore() {
    new Thread() {
        public void run() {
            try {
                Thread.sleep(2 * 1000);
                list.add("1---------1");
                list.add("2---------2");
                list.add("3---------3");
                list.add("4---------4");
                list.add("5---------5");
                list.add("6---------6");
                list.add("7---------7");
                list.add("8---------8");
                list.add("9---------9");
                list.add("10---------10");
                list.add("11---------11");
                handler.sendEmptyMessage(0);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }.start();
}
4 Handler:
private Handler handler = new Handler() {
    public void handleMessage(android.os.Message msg) {
        switch (msg.what) {
        case 0:
            adapter.notifyDataSetChanged();
            mListView.setLoading(false);
            break;
        default:
            break;
        }
    };
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值