Android Demo之旅 ListView底部添加加载更多按钮实现数据分页

在我们的实际项目中,数据应该说是很多的,我们的ListView不可能一下子把数据全部加载进来,我们可以当滚动条滚动到ListView的底部的时候,给一个更多的提示,当我们点击它即加载下一页的数据,相当与我们的分页效果,参考网上的东西,写了一个小小的demo,并总结了一些知识点,功能图如下:

  

源代码下载地址:http://download.csdn.net/detail/harderxin/7762625

掌握知识点:

1)自定义Adapter,将数据和ListView绑定起来

2)理解LayoutInflater动态加载xml布局的用法

3)Handler机制  4)ListView滚动事件

详细的代码大家可以在我的资源中进行下载,下面给大家说一下核心代码的实现:

1、我们定义的Activity继承自ListActivity,我们也可以在xml中定义ListView,然后通过findViewById获取,初始化:

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handler=new Handler();
        //继承ListActivity,所以可以用这个方法取得
        listView=getListView();
        initData();
        //添加底部按钮
        View bottomView=getLayoutInflater().inflate(R.layout.bottom, null);
        loadMore=(Button)bottomView.findViewById(R.id.load);
        loadMore.setOnClickListener(new ButtonClickListener());

        listView.addFooterView(bottomView);
        //setListAdapter(adapter);
        listView.setAdapter(adapter);
        //给listView设置事件
        listView.setOnItemClickListener(new OnItemListener());
        listView.setOnScrollListener(new OnScrollListener());
    }

我们的底部按钮可以通过listView.addFooterView(View view);加载进来,定义我们的按钮布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal" >

   <Button
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:id="@+id/load"
       android:text="加载更多"/>

</LinearLayout>

然后我们可以通过View bottomView=getLayoutInflater().inflate(R.layout.bottom, null);获得View对象,然后通过View对象的findViewById获得我们的按钮:loadMore=(Button)bottomView.findViewById(R.id.load);

2)初始化数据,在里面我们初始化数据为10条,并实例化我们自定义的适配器MyAdapter

    public void initData(){
    	List<Integer> datas=new ArrayList<Integer>();
        for(int i=0;i<10;i++){
        	datas.add(i+1);
        }
        adapter=new MyAdapter(datas, this);
    }

3)自定义适配器MyAdapter:ListView在界面初始化或者滚动加载的时候,里面的getCount、getView等方法会被时时调用执行,每绘制ListView的一行,就会调用getView一次,然后取得相应的组件添加进去;

package com.xin.activity;

import java.util.List;

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

public class MyAdapter extends BaseAdapter{

	private List<Integer> datas;
	private LayoutInflater flater;

	//构造函数
	public MyAdapter(List<Integer> datas,Context context){
		this.datas=datas;
		flater=LayoutInflater.from(context);
	}
	//得到数据总数
	@Override
	public int getCount() {
		System.out.println("aaa");
		return datas.size();
	}

	//得到每一条数据
	@Override
	public Object getItem(int position) {
		return datas.get(position);
	}

	//得到项目的位置
	@Override
	public long getItemId(int position) {
		return position;
	}

	/**
	 * ListView中所显示的item都是通过调用Adapter对象的getView方法来得到一个View对象
	 * 然后把这个View对象放在这个item中,这样的一个过程,这就是ListView和Adapter之间的关系
	 */
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder viewHolder;
		if(convertView==null){
			//生成一个LayoutInflater对象
			//inflater=LayoutInflater.from(context);
			//调用LayoutInflater对象的inflate方法生成一个view对象
			//LayoutInflater 填充器,通过一个xml对象来填充ListView
			//inflate作用:填充一个新的视图层次结构从指定的XML资源文件中
			//参数:View的layout的ID、生成的层次结构的根视图
			//return 填充的层次结构的根视图。如果参数root提供了,那么root就是根视图;否则填充的XML文件的根就是根视图。
			convertView=flater.inflate(R.layout.list, null);
			//生成ViewHolder对象
			viewHolder=new ViewHolder();
			//将convertView中的相关组件赋给ViewHolder中的成员变量
			viewHolder.img=(ImageView)convertView.findViewById(R.id.img);
			viewHolder.info=(TextView)convertView.findViewById(R.id.info);
			//设置tag
			convertView.setTag(viewHolder);
		}else{
			//从convertView中得到我们的viewHolder
			viewHolder=(ViewHolder)convertView.getTag();
		}
		//给viewHolder中的组件添加相应的属性
		viewHolder.img.setBackgroundResource(R.drawable.ic_launcher);
		viewHolder.info.setText("选项"+datas.get(position));
		return convertView;
	}

	//ViewHolder类,保存我们的组件信息,其中的变量值为我们在xml中定义的组件信息,
	//当我们的View通过convertView=flater.inflate(R.layout.list, null);生成出来后
	//我们就可以在convertView取得ViewHolder组件中的相关信息,而不需要重新inflate一遍,减少内存的使用
	class ViewHolder{
		private ImageView img;
		private TextView info;
	}

	//添加数据
	public void addItem(Integer i){
		datas.add(i);
	}
}

ListView中每一行的xml布局:通过convertView=flater.inflate(R.layout.list, null);得到View,然后得到里面相应的组件一条一条的添加到ListView中,

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

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/img"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/info"/>

</LinearLayout>

4)点击按钮加载我们的数据,在这里主要用到的方法是adapter.notifyDataSetChanged();它会通知适配器数据的变化

使用Handler中postDelayed方法,延迟2000毫秒执行里面的代码,虽然用到了Runnable类,但是它也是运行在主线程中的,并没有另外开启一个线程;

    class ButtonClickListener implements OnClickListener{
		@Override
		public void onClick(View v) {
			loadMore.setText("数据加载中");
			handler.postDelayed(new Runnable() {
				@Override
				public void run() {
					System.out.println("hello");
					loadData();
					adapter.notifyDataSetChanged();
					//listView.setSelection(5);
					loadMore.setText("加载更多");
				}
			}, 2000);
		}
    }

    //加载数据
    public void loadData(){
    	int count=adapter.getCount()+1;
    	for(int i=count;i<count+10;i++){
    		adapter.addItem(i);
    	}
    }

5)ListView中的事件:

单击一行事件:

    /**
     * 单击ListView中某一项触发的事件
     * @author dell
     *
     */
    class OnItemListener implements OnItemClickListener{
		@Override
		public void onItemClick(AdapterView<?> arg0, View arg1, int position,
				long id) {
			System.out.println("123");
		}
    }

滚动加载事件:

    //是否到达ListView底部
    boolean isLastRow=false;
    /**
     * 滚动时产生的事件
     * @author dell
     *
     */
    class OnScrollListener implements android.widget.AbsListView.OnScrollListener{

    	//滚动的时候一直回调,直到停止滚动时才停止回调,单击时回调一次
    	//firstVisibleItem:当前嫩看见的第一个列表项ID(从0开始,小半个也算)
    	//visibleItemCount:当前能看见的列表项个数(小半个也算)
    	//totalItemCount:列表项总共数
		@Override
		public void onScroll(AbsListView view, int firstVisibleItem,
				int visibleItemCount, int totalItemCount) {
			System.out.println("firstVisibleItem="+firstVisibleItem);

			System.out.println("visibleItemCount="+visibleItemCount);
			//判断是否滚动到最后一行
			if(firstVisibleItem+visibleItemCount==totalItemCount&&totalItemCount>0){
				System.out.println("已经到最后一行了");
				isLastRow=true;
			}
		}

		//正在滚动时回调,回调2-3次,手指没抛则回调2次,scrollState=2的这次不回调
		//回调顺序如下:
		//第一次:scrollState=SCROLL_STATE_TOUCH_SCROLL(1)正在滚动
		//第二次:scrollState = SCROLL_STATE_FLING(2)手指做了抛的动作(手指离开屏幕前,用力滑了一下)
		//第三次:scrollState = SCROLL_STATE_IDLE(0) 停止滚动       

		//当屏幕停止滚动时为0;当屏幕滚动且用户使用的触碰或手指还在屏幕上时为1;
        //由于用户的操作,屏幕产生惯性滑动时为2
		@Override
		public void onScrollStateChanged(AbsListView view, int scrollState) {
			System.out.println("789");
			//当滚动到最后一行并且停止滚动时,执行加载
			if(isLastRow&&scrollState==OnScrollListener.SCROLL_STATE_IDLE){
				//执行加载代码
				isLastRow=false;
			}
		}

    }

拓展知识点LayoutInflater:

我们在onCreate方法中总会有:setContentView(R.layout.main);出现,其实也可以使用LayoutInflater来加载:

      setContentView(R.layout.main);
        show=(Button)findViewById(R.id.btn);
        //下面的方式和上面的方式是等同的
        //LayoutInflater layoutInflater=LayoutInflater.from(this);
        //View vv=layoutInflater.inflate(R.layout.main, null);
        //setContentView(vv);
        //show=(Button)vv.findViewById(R.id.btn);

区别是:

setContentView()一旦调用, layout就会立刻显示UI;而inflate只会把Layout形成一个以view类实现成的对象,有需要时再用setContentView(view)显示出来。

一般在activity中通过setContentView()将界面显示出来, 但是如果在非activity中如何对控件布局设置操作了,这就需要LayoutInflater动态加载。

LayoutInflater笔记:

/**

* 使用LayoutInflater来动态载入AlertDialog页面显示的内容,AlertDialog使用的布局方式在layout目录下定义的custom_dialog.xml

*

在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById()。

不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;而findViewById()是找xml布局文件下的具体widget控件(如Button、TextView等)。

具体作用:

1、对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入;

2、对于一个已经载入的界面,就可以使用Activiyt.findViewById()方法来获得其中的界面元素。

什么是已经被载入的layout,什么是还没有载入的.我们启动一个应用,与入口Activity相关的layout{常见的是main.xml}就是被载入的,即在Oncreate()中的.

而其他的layout是没有被载入的.就要动态载入了或通过另一个activity.

LayoutInflater作用是将layout的xml布局文件实例化为View类对象。

获取LayoutInflater的方法有如下三种:

LayoutInflater inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

View layout = inflater.inflate(R.layout.main, null);

LayoutInflater inflater = LayoutInflater.from(context); (该方法实质就是第一种方法,可参考源代码)

View layout = inflater.inflate(R.layout.main, null);

LayoutInflater inflater = getLayoutInflater();(在Activity中可以使用,实际上是View子类下window的一个函数)

View layout = inflater.inflate(R.layout.main, null);

注意:

·inflate方法与 findViewById 方法不同;

·inflater 是用来找 res/layout下的 xml 布局文件,并且实例化;

·findViewById() 是找具体 xml 布局文件中的具体 widget 控件(如:Button、TextView 等)。

* @author dell

*

*/

Android Demo之旅 ListView底部添加加载更多按钮实现数据分页

时间: 2024-12-26 12:24:22

Android Demo之旅 ListView底部添加加载更多按钮实现数据分页的相关文章

探索SwipeRefreshLayout配合自定义ListView完成下拉刷新、滑到底部自动加载更多

在Android开发过程中经常需要实现上下拉刷新功能,Google推出的下拉刷新控件SwipeRefreshLayout(彩虹条),由于官方版本只有下拉刷新而没有上拉加载更多的功能,很多人也尝试在这个基础上进行改写.今天尝试一下使用SwipeRefreshLayout配合自定义ListView实现下拉刷新.滑到底部自动加载更多的功能. 效果图如下所示,在进入页面的时候加载自动刷新,滑到底部自动加载更多,当数据已经加载完成则显示已经加载完成,,否则上拉任可继续加载 先贴一下项目结构图吧,这样可能对

嗯嗯,一句代码就搞定 RecycleView 侧滑菜单、添加头部底部、加载更多

很早就萌生了将这种方案封装为一个开源库的想法,旨在实现调用方式最简单,且又不失可定制性.本库最大的特点的是采用了 Glide 简洁明了的链式调用方式,一句代码即可添加侧滑菜单.头部底部等. 特性: 1.自定义侧滑菜单布局 2.添加头部.底部 3.轻松实现加载更多 4.设置 item 间距 5.多种 item 类型 6.支持 LinearLayout 及 GridLayout 7.一句代码实现所有功能 效果: 左侧滑菜单.右侧滑菜单.自定义菜单布局:      头部.多头部:      底部.多底

android ListView上拉加载更多 下拉刷新功能实现(采用pull-to-refresh)

Android实现上拉加载更多功能以及下拉刷新功能, 采用了目前比较火的PullToRefresh,他是目前实现比较好的下拉刷新的类库. 目前他支持的控件有:ListView, ExpandableListView,GridView,WebView等. 下载地址:https://github.com/chrisbanes/Android-PullToRefresh 首先第一步当然是导入libriay到咱们的项目了,具体导入方式,这里不再赘述. 下面是个例子采用的是ListView,当然其余的和这

Android中ListView上拉加载更多及下拉刷新

做几乎每一个Android应用开发,都少不了用到一个控件,那就是ListView,用于加载多条数据,并用一定的样式展示出来.但是为了性能问题(一次性加载太多数据,比如100000条,耗费时间长,消耗资源多等)及用户体验问题(比如用户只想看最新的10条数据,结果一下子把所有的上万条数据都加载了,不方便用户选择)等原因,所以我们要把ListView的数据进行分页加载,常用的就是ListView的上拉加载更多及下拉刷新最新数据. 我们可以自己封装一个带上下拉功能的ListView,通常就是加上头部He

android:ScrollView滑动到底部显示加载更多

这是效果 主要是onTouchListener监听事件,监视什么时候滑到底部 同时要理解getMeasuredHeight和getHeight的区别 getMeasuredHeight:全部的长度 包括隐藏的 getHeight:在布局中展示出来的长度 布局文件: <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_paren

Windows Phone 8.1开发:如何让ListView下拉加载更多?

Windows Phone 8.1开发中使用ListView作为数据呈现载体时,经常需要一个下拉(拇指向上滑动)加载更多的交互操作.如何完成这一操作呢?下面为您阐述. 思路是这样的: 1.在ListView的loaded事件中,获取ListView中的ScrollView对象. 如何获得ScrollViewer,这篇文章说的很清楚! Windows Phone 8.1开发:如何从ListView中,获取ScrollViewer对象 2. 给ScrollViewer创建事件,上篇文章也说了. 3.

Android实现下拉刷新和上拉加载更多的RecyclerView和ScrollView

PullRefreshRecyclerView.java /** * 类说明:下拉刷新上拉加载更多的RecyclerView * Author: gaobaiq * Date: 2016/5/9 18:09 */ public class PullRefreshRecyclerView extends PullRefreshView { /** * 内置的RecyclerView: */ private RecyclerView mRecyclerView; /** * 可见的最后一个item

【iOS开发-62】自定义cell制作团购页面、顶部图片轮播、底部模拟加载更多功能,核心是练习代理模式

(1)效果 (2)案例源代码免费下载 团购页面+iOS源代码+头部广告轮播+底部加载更多 (3)补充 在源代码中,有一处瑕疵:就是因为是单线程,所以在上下拖动页面的时候,上面的图片轮播会停止.所以我们需要兼顾,解决方案,把定时器加到当前的runLoop中. 即在WPTgHeaderView.m的playOn方法中添加一行代码: -(void)playOn{ timer=[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector

robotium listview上拉加载更多/下拉刷新

ListView listview = (ListView) solo.getView("id/list"); int[] location = new int[2]; listview.getLocationOnScreen(location); location[1] = location[1] + listview.getBottom(); Log.i(TAG, "[Location x]: " + Integer.toString(location[0]))