一、ListView分页:
(一)、目的:
Android 应用开发中,采用ListView组件来展示数据是很常用的功能,当一个应用要展现很多的数据时,一般情况下都不会把所有的数据一次就展示出来,而是通过 分页的形式来展示数据,这样会有更好的用户体验。因此,很多应用都是采用分批次加载的形式来获取用户所需的数据。例如:微博客户端可能会在用户滑 动至列表底端时自动加载下一页数据,也可能在底部放置一个"查看更多"按钮,用户点击后,加载下一页数据。
(二)、核心技术点:
1. 借助 ListView组件的OnScrollListener监听事件,去判断何时该加载新数据;
2. 往服务器get传递表示页码的参数:page。而该page会每加载一屏数据后自动加一;
3. 利用addAll()方法不断往list集合末端添加新数据,使得适配器的数据源每新加载一屏数据就发生变化;
4. 利用适配器对象的notifyDataSetChanged()方法。该方法的作用是通知适配器自己及与该数据有关的view,数据已经发生变动,要刷新自己、更新数据。
(三)、OnScrollListener监听事件 :
1、该监听器中有两个需要实现的方法:
· onScrollStateChanged(AbsListView view, int scrollState):监听屏幕的滚动状态的变动情况
· onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount):监听屏幕滚动的item的数量
2、scrollState 回调顺序如下:
· 第1次:scrollState = SCROLL_STATE_TOUCH_SCROLL(1):表示正在滚动。当屏幕滚动且用户使用的触碰或手指还在屏幕上时为1
· 第2次:scrollState =SCROLL_STATE_FLING(2) :表示手指做了抛的动作(手指离开屏幕前,用力滑了一下,屏幕产生惯性滑动)。
· 第3次:scrollState =SCROLL_STATE_IDLE(0) :表示屏幕已停止。屏幕停止滚动时为0。
3、onScroll中参数讲解:
· firstVisibleItem:当前窗口中能看见的第一个列表项ID(从0开始)
· visibleItemCount:当前窗口中能看见的列表项的个数(小半个也算)
· totalItemCount:列表项的总数
4、思路:
· 当滚到最后一条,加载新数据;
· 适配器的数据源要进行累加:totalList.addAll(list);
· 数据发生变化,适配器通知:adapter.notifyDataSetChanged();【牢记】
· 判断是否滚到最后一行。
示例代码:
if (firstVisibleItem + visibleItemCount == totalItemCount ) {
isBottom = true;
}
(四)、页面效果:
【要求:】
当屏幕滑动到最后一条时,显示“点击加载数据”的提示。点击后可以加载新的数据。当向上滑动或者没有到最后一条时,不显示“点击加载数据”的提示。
(五)、核心代码:
1、布局文件的核心代码:
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="@+id/listView_main"
android:layout_below="@+id/button_main_init"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/layout_main_nextpage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#000"
android:visibility="invisible"
android:gravity="center"
android:onClick="clickButton"
android:padding="5dp">
<ProgressBar
android:id="@+id/progressBar_main"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/text_main_nextpage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:textSize="18sp"
android:onClick="clickButton"
android:textColor="#fff"
android:text="点击加载更多数据" />
2、Activity页面核心代码:
public class MainActivity extends Activity {
private String TAG = "MainActivity";
private ListView listView_main;
private LinearLayout layout_main_nextpage;
private MySQLiteDatabaseHelper dbHelper = null;
// 用于分页显示数据的属性
private int pageSize = 30;// 每页显示的条数
private int curPage = 1;
private int rowCount = 0;
private int pageCount = 0;// 总页数
private boolean isBottom = false;// 判断是否滚动到数据最后一条
private List<Map<String, Object>> totalList = null;// 加载到适配器中的数据源
private SimpleAdapter adapter = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView_main = (ListView) findViewById(R.id.listView_main);
layout_main_nextpage = (LinearLayout) findViewById(R.id.layout_main_nextpage);
// 实例化访问数据库帮助类
dbHelper = new MySQLiteDatabaseHelper();
// 获取数据表一共有多少条,从而计算共有多少页
rowCount = dbHelper.selectCount("select id from android_basic", null);
// 计算总页码数
pageCount = (int) Math.ceil(rowCount / (float) pageSize);
// 如果当前页为第一页,则数据源集合中就是第一页的内容
if (curPage == 1) {
totalList = getCurpageList(1);
}
adapter = new SimpleAdapter(this, totalList,
R.layout.item_listview_main, new String[] { "_id", "title" },
new int[] { R.id.text_item_listview_id,
R.id.text_item_listview_title });
listView_main.setAdapter(adapter);
// 给ListView对象设置滚动监听器,以此来判断是否已经滚动到最后一条,从而决定是否加载新数据
listView_main.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (isBottom) {
// 如果滚到最后一条数据(即:屏幕最底端),则显示:“加载更多新数据”
if (curPage < pageCount) {
layout_main_nextpage.setVisibility(View.VISIBLE);
}
} else {
layout_main_nextpage.setVisibility(View.GONE);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// Log.i(TAG, "==" + firstVisibleItem + ":::" + visibleItemCount
// + ":::" + totalItemCount);
// 判断是否已经滚动到了最后一条,从而决定是否提示加载新数据
isBottom = (firstVisibleItem + visibleItemCount == totalItemCount);
}
});
}
public void clickButton(View view) {
switch (view.getId()) {
case R.id.layout_main_nextpage:
// Log.i(TAG, "==" + curPage + ":::" + pageCount);
// 如果不是最后一页,则让当前页码累加,让数据源累加新数据,并通知适配器信息发生变化
if (curPage < pageCount) {
curPage++;
totalList.addAll(getCurpageList(curPage));
adapter.notifyDataSetChanged();
}
// 只要点击了提示“加载新数据”的信息,就让其隐藏
layout_main_nextpage.setVisibility(View.GONE);
break;
default:
break;
}
}
// 获取每一页的数据,返回List集合
private List<Map<String, Object>> getCurpageList(int currentPage) {
int offset = (currentPage - 1) * pageSize;
String sql = "select id _id ,title from android_basic limit ? , ?";
return dbHelper.selectData(sql, new String[] { offset + "",
pageSize + "" });
}
}