listview实现上拉加载


Android实现listview的上拉加载更多

当前实例为最基本的上拉加载实现,  学习者可根据逻辑自创建...

实现逻辑:

1、创建自定义ListView,并且监听其滚动的事件
2、自定义ListView的类中应实现一个内部接口,用来实现加载更多数据的逻辑
3、使用该listview,且在引用类中实现加载更多数据的内部接口
4、(最好自定义Adapter)

最终效果



下图为最基本的项目结构:

下为每一个步骤的详解:

1、创建自定义ListView,并且监听其滚动的事件


继承ListView:下拉的时候需要动态的加载一个布局文件提示给用户,告知我们现在正在帮您刷新数据 。
实现OnScrollListener: 只有在第一个item为最顶部的时候才开始进行我们的‘下拉加载’更多的代码逻辑,需要程序员知道我们现在能否进行触发该逻辑代码

1.1 类属性的声明
    private int firstVisibleItem;       // 表示当前listview是否在第一行
    private View v;                     // 提示的加载布局
    private IReflashListener iReflashListener;  // 实现刷新的内部接口
1.2 类初始化
public MyListView(Context context) {
        super(context, null);
        init();
    }

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    private void init() {
        setOnScrollListener(this);
    }
1.3 对其OnScrollListener的方法实现
@Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        /**
         * firstVisibleItem==0: 表示在第一个Item项
         * scrollState!=0: 该listview正在移动
         */
        if (firstVisibleItem == 0 && scrollState != 0) {
            // 进行添加顶部布局
            v = LayoutInflater.from(getContext()).inflate(R.layout.item_top_layout, null);
            this.addHeaderView(v);

            if (iReflashListener != null)
                iReflashListener.onReflash();        // 加载数据

        } else {
            if (v != null) {
                // 隐藏顶部布局
                this.removeHeaderView(v);
            }

        }

    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        this.firstVisibleItem = firstVisibleItem;
    }
动态加载数据的操作放在 onScrollStateChanged中的原因:只有用户在滚动该listview的时候才能进行加载数据。
onScroll方法中的firstVisibleItem:  当前listview的操作缓存中的第一条item是该数据源的第几条。

2、自定义ListView的类中应实现一个内部接口,用来实现加载更多数据的逻辑

以上的内容基本上已经实现了该上拉刷新的功能。

3、动态布局的创建

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/seekBar"
        style="@android:style/Widget.ProgressBar.Small" />


    <TextView android:text="下拉加载"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
将该组件放在任意的layout中即可。

4、使用该listview,且在引用类中实现加载更多数据的内部接口

稍微值得注意的是,在我们listview的引用文件中,该组件需要使用以下方式
<com.example.administrator.listviewautoload.MyListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
此方式为使用自定义组件。

5、adapter实现

在该listview中,建议使用自定义adapter。(或者可以说任何listview都建议使用自定义adapter)
adapter大家都用过不少了,就直接将adapter源码贴出

package com.example.administrator.listviewautoload;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.List;

/**
 * 进行数据与listview的绑定
 */
public class MyAdapter extends BaseAdapter {

    private List<String> lists; // item总数据
    private Context context;    // 上下文(此处级别因为activity)
    private ViewHolder viewHolder;
    private boolean flag; // 是否可以加载更多


    public MyAdapter(List<String> lists, Context context) {
        this.lists = lists;
        this.context = context;
    }


    @Override
    public int getCount() {
        return lists.size();
    }

    @Override
    public Object getItem(int position) {
        return lists.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        /**
         * 做出一定的listview优化
         */
        if (convertView == null) {

            convertView = LayoutInflater.from(context).inflate(R.layout.item_layout, null);
            viewHolder = new ViewHolder();
            viewHolder.textView = (TextView) convertView.findViewById(R.id.text);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        viewHolder.textView.setText(lists.get(position));

        return convertView;
    }


    class ViewHolder {

        TextView textView;

    }


}


这个adapter还是非常简单的,内部定义了一个ViewHolder类。 包含了一个listview item的组件。使用此种getView方法方式可以最优化的帮组我们节省Android内存(建议使用)。



最后一步,那就是动态的添加数据


现为listview绑定一个数据适配器


在该类中,我们需要实现该listview的动态加载数据接口
public class MainActivity extends Activity implements MyListView.IReflashListener

我们实现它的方法,在该方法中就可以调用自己特有的加载数据方法,只要放入到adapter的数据源中,调用adapte的notifyDataSetChanged即可
(notifyDataSetChanged: 通知进行适配的Adapter, 表示这个数据源的数据已经更新了,你现在要在主界面中同时做出刷新 )

 @Override
    public void onReflash() {
        Toast.makeText(this, "MainActivity   onReflash", Toast.LENGTH_SHORT).show();
        /**
         * 开始加载刷新的数据(此为模拟动态加载出来的数据)
         */
        for (int i = 0; i < 2; i++) {
            lists.add(Integer.valueOf(lists.get(lists.size() - 1)) + 1 + "");
        }

        adapter.notifyDataSetChanged();

    }

至此,我们的功能就基本实现了,有木有特别简单。 因仔细注意MainActivity的init方法中listview.setiReflashListener(this) ;
这句代码一定要有, 否则在listview中就不能实现动态加载了。



这是笔者的第一篇博客,可能讲的不是很详细,但代码几乎全部都贴出来了。 学习者们应该很容易理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值