android UI进阶之实现listview的分页加载

当用户从网络上读取微薄的时候,若是一会儿所有加载用户未读的微薄这将耗费比较长的时间,形成很差的用户体验,同时一屏的内容也不足以显示如此多的内容。这时候,咱们就须要用到另外一个功能,那就是listview的分页了。经过分页分次加载数据,用户看多少就去加载多少。
一般这也分为两种方式,一种是设置一个按钮,用户点击即加载。另外一种是当用户滑动到底部时自动加载。今天我就和你们分享一下这个功能的实现。
首先,写一个xml文件,moredata.xml,该文件即定义了放在listview底部的视图:
<? xml version ="1.0" encoding ="utf-8" ?>
< LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android"
         android:layout_width ="match_parent"
         android:layout_height ="match_parent"
         android:orientation ="vertical" >
     < Button        
             android:id ="@+id/bt_load"        
             android:layout_width ="fill_parent"        
             android:layout_height ="wrap_content"    
             android:text ="加载更多数据" />    
     < ProgressBar
             android:id ="@+id/pg"
             android:layout_width ="wrap_content"
             android:layout_height ="wrap_content"
             android:layout_gravity ="center_horizontal"
             android:visibility ="gone"
             />
</ LinearLayout >
 
能够看到是一个按钮和一个进度条。由于只作一个演示,这里简单处理,经过设置控件的visibility,未加载时显示按钮,加载时就显示进度条。
写一个item.xml,你们应该很熟悉了。用来定义listview的每一个item的视图。
 
<? xml version ="1.0" encoding ="utf-8" ?>
< LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android"
         android:layout_width ="match_parent"
         android:layout_height ="match_parent"
         android:orientation ="vertical" >
        
         < TextView
                 android:id ="@+id/tv_title"
                 android:textSize ="20sp"
                 android:layout_width ="wrap_content"
                 android:layout_height ="wrap_content"
                 android:layout_marginTop ="5dp"
                 />
         < TextView
                 android:textSize ="12sp"
                 android:id ="@+id/tv_content"
                 android:layout_width ="wrap_content"
                 android:layout_height ="wrap_content"
                 android:layout_marginTop ="5dp"
                 />

</ LinearLayout >
 
 
main.xml就不贴了,整个主界面就一个listview。
直接先看下Activity的代码,在里面实现分页效果。
 
package com.notice.moredate;

import java.util.ArrayList;
import java.util.HashMap;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;
import android.widget.Toast;

public class MoreDateListActivity extends Activity implements OnScrollListener {
        
         // ListView的Adapter
         private SimpleAdapter mSimpleAdapter;
         private ListView lv;
         private Button bt;
         private ProgressBar pg;
         private ArrayList<HashMap<String,String>> list;
         // ListView底部View
         private View moreView;
         private Handler handler;
         // 设置一个最大的数据条数,超过即再也不加载
         private int MaxDateNum;
         // 最后可见条目的索引
         private int lastVisibleIndex;
        
         /** Called when the activity is first created. */
        @Override
         public void onCreate(Bundle savedInstanceState) {
                 super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                
                
                MaxDateNum = 22; // 设置最大数据条数

                lv = (ListView) findViewById(R.id.lv);

                 // 实例化底部布局
                moreView = getLayoutInflater().inflate(R.layout.moredate, null);

                bt = (Button) moreView.findViewById(R.id.bt_load);
                pg = (ProgressBar) moreView.findViewById(R.id.pg);
                handler = new Handler();

                 // 用map来装载数据,初始化10条数据
                list = new ArrayList<HashMap<String,String>>();
                 for ( int i = 0; i < 10; i++) {
                        HashMap<String, String> map = new HashMap<String, String>();
                        map.put( "ItemTitle", "第" + i + "行标题");
                        map.put( "ItemText", "第" + i + "行内容");
                        list.add(map);
                }
                 // 实例化SimpleAdapter
                mSimpleAdapter = new SimpleAdapter( this, list, R.layout.item,
                                 new String[] { "ItemTitle", "ItemText" },
                                 new int[] { R.id.tv_title, R.id.tv_content });
                 // 加上底部View,注意要放在setAdapter方法前
                lv.addFooterView(moreView);
                lv.setAdapter(mSimpleAdapter);
                 // 绑定监听器
                lv.setOnScrollListener( this);

                bt.setOnClickListener( new OnClickListener() {

                        @Override
                         public void onClick(View v) {
                                pg.setVisibility(View.VISIBLE); // 将进度条可见
                                bt.setVisibility(View.GONE); // 按钮不可见

                                handler.postDelayed( new Runnable() {

                                        @Override
                                         public void run() {
                                                loadMoreDate(); // 加载更多数据
                                                bt.setVisibility(View.VISIBLE);
                                                pg.setVisibility(View.GONE);
                                                mSimpleAdapter.notifyDataSetChanged(); // 通知listView刷新数据
                                        }

                                }, 2000);
                        }
                });

        }

         private void loadMoreDate() {
                 int count = mSimpleAdapter.getCount();
                 if (count + 5 < MaxDateNum) {
                         // 每次加载5条
                         for ( int i = count; i < count + 5; i++) {
                                HashMap<String, String> map = new HashMap<String, String>();
                                map.put( "ItemTitle", "新增第" + i + "行标题");
                                map.put( "ItemText", "新增第" + i + "行内容");
                                list.add(map);
                        }
                } else {
                         // 数据已经不足5条
                         for ( int i = count; i < MaxDateNum; i++) {
                                HashMap<String, String> map = new HashMap<String, String>();
                                map.put( "ItemTitle", "新增第" + i + "行标题");
                                map.put( "ItemText", "新增第" + i + "行内容");
                                list.add(map);
                        }
                }

        }

        @Override
         public void onScroll(AbsListView view, int firstVisibleItem,
                         int visibleItemCount, int totalItemCount) {
                 // 计算最后可见条目的索引
                lastVisibleIndex = firstVisibleItem + visibleItemCount - 1;

                 // 全部的条目已经和最大条数相等,则移除底部的View
                 if (totalItemCount == MaxDateNum + 1) {
                        lv.removeFooterView(moreView);
                        Toast.makeText( this, "数据所有加载完成,没有更多数据!", Toast.LENGTH_LONG).show();
                }

        }

        @Override
         public void onScrollStateChanged(AbsListView view, int scrollState) {
                 // 滑到底部后自动加载,判断listview已经中止滚动而且最后可视的条目等于adapter的条目
                 if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
                                && lastVisibleIndex == mSimpleAdapter.getCount()) {
                         // 当滑到底部时自动加载
                         // pg.setVisibility(View.VISIBLE);
                         // bt.setVisibility(View.GONE);
                         // handler.postDelayed(new Runnable() {
                         //
                         // @Override
                         // public void run() {
                         // loadMoreDate();
                         // bt.setVisibility(View.VISIBLE);
                         // pg.setVisibility(View.GONE);
                         // mSimpleAdapter.notifyDataSetChanged();
                         // }
                         //
                         // }, 2000);

                }

        }
        
}
 
 
 
经过注释,你们应该很容易理解了。这里作下简单的解析。首先要注意的是,addFootView方法必定要在setAdapter方法以前,不然会无效。addFootView方法为listview底部加入一个视图,在本例中就是那个Button加progressbar的视图。当用户点击按钮时,调用loadmoreDate方法,为listview绑定更多的数据,经过adapter的notifyDataSetChanged方法通知listview刷新,显示刚加入的数据。
这里用handler异步延迟2秒操做,模仿加载过程。同时listview绑定了onScrollListener监听器,而且实现了onScroll和onScrollStateChanged方法。在后者方法中,咱们经过判断listview已经中止滚动而且最后可视的条目等于adapter的条目,能够知道用户已经滑动到底部而且自动加载,代码中将这部分代码注释掉了,你们能够本身试下。
代码中还加入了一个MaxDateNum变量,用来记录最大的数据数量。也就是说网络或者其余地方一共的数据。经过onScroll方法判断用户加载完这些数据后,移除listview底部视图,不让继续加载。同时在loadmoreDate方法中也对最大数据量作相应的操做来判断加载数量。(默认加载5条,不足5条时加载剩余的)。
看下效果图:
 
 
 
 
相关文章
相关标签/搜索