当前位置: 代码迷 >> Android >> android UI进阶之兑现listview的分页加载
  详细解决方案

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

热度:130   发布时间:2016-05-01 20:21:32.0
android UI进阶之实现listview的分页加载

上篇博文和大家分享了下拉刷新,这是一个用户体验非常好的操作方式。新浪微薄就是使用这种方式的典型。

还有个问题,当用户从网络上读取微薄的时候,如果一下子全部加载用户未读的微薄这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容。这时候,我们就需要用到另一个功能,那就是listview的分页了。通过分页分次加载数据,用户看多少就去加载多少。

通常这也分为两种方式,一种是设置一个按钮,用户点击即加载。另一种是当用户滑动到底部时自动加载。今天我就和大家分享一下这个功能的实现。

首先,写一个xml文件,moredata.xml,该文件即定义了放在listview底部的视图:

?

[html]?view plaincopy
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
  3. ????android:layout_width="match_parent"??
  4. ????android:layout_height="match_parent"??
  5. ????android:orientation="vertical"?>??
  6. ??<Button??????
  7. ??????android:id="@+id/bt_load"??????
  8. ??????android:layout_width="fill_parent"??????
  9. ??????android:layout_height="wrap_content"????
  10. ??????android:text="加载更多数据"?/>???
  11. ??<ProgressBar??
  12. ??????android:id="@+id/pg"??
  13. ??????android:layout_width="wrap_content"??
  14. ??????android:layout_height="wrap_content"??
  15. ??????android:layout_gravity="center_horizontal"??
  16. ??????android:visibility="gone"??
  17. ??????/>??
  18. </LinearLayout>??


?

可以看到是一个按钮和一个进度条。因为只做一个演示,这里简单处理,通过设置控件的visibility,未加载时显示按钮,加载时就显示进度条。

写一个item.xml,大家应该很熟悉了。用来定义listview的每个item的视图。

?

[html]?view plaincopy
  1. <?xml?version="1.0"?encoding="utf-8"?>??
  2. <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
  3. ????android:layout_width="match_parent"??
  4. ????android:layout_height="match_parent"??
  5. ????android:orientation="vertical"?>??
  6. ??????
  7. ????<TextView??
  8. ????????android:id="@+id/tv_title"??
  9. ????????android:textSize="20sp"??
  10. ????????android:layout_width="wrap_content"??
  11. ????????android:layout_height="wrap_content"??
  12. ????????android:layout_marginTop="5dp"??
  13. ????????/>??
  14. ????<TextView??
  15. ????????android:textSize="12sp"??
  16. ????????android:id="@+id/tv_content"??
  17. ????????android:layout_width="wrap_content"??
  18. ????????android:layout_height="wrap_content"??
  19. ????????android:layout_marginTop="5dp"??
  20. ????????/>??
  21. ??
  22. </LinearLayout>??


?

main.xml就不贴了,整个主界面就一个listview。

直接先看下Activity的代码,在里面实现分页效果。

?

[java]?view plaincopy
  1. package?com.notice.moredate;??
  2. ??
  3. import?java.util.ArrayList;??
  4. import?java.util.HashMap;??
  5. ??
  6. import?android.app.Activity;??
  7. import?android.os.Bundle;??
  8. import?android.os.Handler;??
  9. import?android.view.View;??
  10. import?android.view.View.OnClickListener;??
  11. import?android.widget.AbsListView;??
  12. import?android.widget.AbsListView.OnScrollListener;??
  13. import?android.widget.Button;??
  14. import?android.widget.ListView;??
  15. import?android.widget.ProgressBar;??
  16. import?android.widget.SimpleAdapter;??
  17. import?android.widget.Toast;??
  18. ??
  19. public?class?MoreDateListActivity?extends?Activity?implements?OnScrollListener?{??
  20. ??????
  21. ????//?ListView的Adapter??
  22. ????private?SimpleAdapter?mSimpleAdapter;??
  23. ????private?ListView?lv;??
  24. ????private?Button?bt;??
  25. ????private?ProgressBar?pg;??
  26. ????private?ArrayList<HashMap<String,String>>?list;??
  27. ????//?ListView底部View??
  28. ????private?View?moreView;??
  29. ????private?Handler?handler;??
  30. ????//?设置一个最大的数据条数,超过即不再加载??
  31. ????private?int?MaxDateNum;??
  32. ????//?最后可见条目的索引??
  33. ????private?int?lastVisibleIndex;??
  34. ??????
  35. ????/**?Called?when?the?activity?is?first?created.?*/??
  36. ????@Override??
  37. ????public?void?onCreate(Bundle?savedInstanceState)?{??
  38. ????????super.onCreate(savedInstanceState);??
  39. ????????setContentView(R.layout.main);??
  40. ??????????
  41. ??????????
  42. ????????MaxDateNum?=?22;?//?设置最大数据条数??
  43. ??
  44. ????????lv?=?(ListView)?findViewById(R.id.lv);??
  45. ??
  46. ????????//?实例化底部布局??
  47. ????????moreView?=?getLayoutInflater().inflate(R.layout.moredate,?null);??
  48. ??
  49. ????????bt?=?(Button)?moreView.findViewById(R.id.bt_load);??
  50. ????????pg?=?(ProgressBar)?moreView.findViewById(R.id.pg);??
  51. ????????handler?=?new?Handler();??
  52. ??
  53. ????????//?用map来装载数据,初始化10条数据??
  54. ????????list?=?new?ArrayList<HashMap<String,String>>();??
  55. ????????for?(int?i?=?0;?i?<?10;?i++)?{??
  56. ????????????HashMap<String,?String>?map?=?new?HashMap<String,?String>();??
  57. ????????????map.put("ItemTitle",?"第"?+?i?+?"行标题");??
  58. ????????????map.put("ItemText",?"第"?+?i?+?"行内容");??
  59. ????????????list.add(map);??
  60. ????????}??
  61. ????????//?实例化SimpleAdapter??
  62. ????????mSimpleAdapter?=?new?SimpleAdapter(this,?list,?R.layout.item,??
  63. ????????????????new?String[]?{?"ItemTitle",?"ItemText"?},??
  64. ????????????????new?int[]?{?R.id.tv_title,?R.id.tv_content?});??
  65. ????????//?加上底部View,注意要放在setAdapter方法前??
  66. ????????lv.addFooterView(moreView);??
  67. ????????lv.setAdapter(mSimpleAdapter);??
  68. ????????//?绑定监听器??
  69. ????????lv.setOnScrollListener(this);??
  70. ??
  71. ????????bt.setOnClickListener(new?OnClickListener()?{??
  72. ??
  73. ????????????@Override??
  74. ????????????public?void?onClick(View?v)?{??
  75. ????????????????pg.setVisibility(View.VISIBLE);//?将进度条可见??
  76. ????????????????bt.setVisibility(View.GONE);//?按钮不可见??
  77. ??
  78. ????????????????handler.postDelayed(new?Runnable()?{??
  79. ??
  80. ????????????????????@Override??
  81. ????????????????????public?void?run()?{??
  82. ????????????????????????loadMoreDate();//?加载更多数据??
  83. ????????????????????????bt.setVisibility(View.VISIBLE);??
  84. ????????????????????????pg.setVisibility(View.GONE);??
  85. ????????????????????????mSimpleAdapter.notifyDataSetChanged();//?通知listView刷新数据??
  86. ????????????????????}??
  87. ??
  88. ????????????????},?2000);??
  89. ????????????}??
  90. ????????});??
  91. ??
  92. ????}??
  93. ??
  94. ????private?void?loadMoreDate()?{??
  95. ????????int?count?=?mSimpleAdapter.getCount();??
  96. ????????if?(count?+?5?<?MaxDateNum)?{??
  97. ????????????//?每次加载5条??
  98. ????????????for?(int?i?=?count;?i?<?count?+?5;?i++)?{??
  99. ????????????????HashMap<String,?String>?map?=?new?HashMap<String,?String>();??
  100. ????????????????map.put("ItemTitle",?"新增第"?+?i?+?"行标题");??
  101. ????????????????map.put("ItemText",?"新增第"?+?i?+?"行内容");??
  102. ????????????????list.add(map);??
  103. ????????????}??
  104. ????????}?else?{??
  105. ????????????//?数据已经不足5条??
  106. ????????????for?(int?i?=?count;?i?<?MaxDateNum;?i++)?{??
  107. ????????????????HashMap<String,?String>?map?=?new?HashMap<String,?String>();??
  108. ????????????????map.put("ItemTitle",?"新增第"?+?i?+?"行标题");??
  109. ????????????????map.put("ItemText",?"新增第"?+?i?+?"行内容");??
  110. ????????????????list.add(map);??
  111. ????????????}??
  112. ????????}??
  113. ??
  114. ????}??
  115. ??
  116. ????@Override??
  117. ????public?void?onScroll(AbsListView?view,?int?firstVisibleItem,??
  118. ????????????int?visibleItemCount,?int?totalItemCount)?{??
  119. ????????//?计算最后可见条目的索引??
  120. ????????lastVisibleIndex?=?firstVisibleItem?+?visibleItemCount?-?1;??
  121. ??
  122. ????????//?所有的条目已经和最大条数相等,则移除底部的View??
  123. ????????if?(totalItemCount?==?MaxDateNum?+?1)?{??
  124. ????????????lv.removeFooterView(moreView);??
  125. ????????????Toast.makeText(this,?"数据全部加载完成,没有更多数据!",?Toast.LENGTH_LONG).show();??
  126. ????????}??
  127. ??
  128. ????}??
  129. ??
  130. ????@Override??
  131. ????public?void?onScrollStateChanged(AbsListView?view,?int?scrollState)?{??
  132. ????????//?滑到底部后自动加载,判断listview已经停止滚动并且最后可视的条目等于adapter的条目??
  133. ????????if?(scrollState?==?OnScrollListener.SCROLL_STATE_IDLE??
  134. ????????????????&&?lastVisibleIndex?==?mSimpleAdapter.getCount())?{??
  135. ????????????//?当滑到底部时自动加载??
  136. ????????????//?pg.setVisibility(View.VISIBLE);??
  137. ????????????//?bt.setVisibility(View.GONE);??
  138. ????????????//?handler.postDelayed(new?Runnable()?{??
  139. ????????????//??
  140. ????????????[email protected]??
  141. ????????????//?public?void?run()?{??
  142. ????????????//?loadMoreDate();??
  143. ????????????//?bt.setVisibility(View.VISIBLE);??
  144. ????????????//?pg.setVisibility(View.GONE);??
  145. ????????????//?mSimpleAdapter.notifyDataSetChanged();??
  146. ????????????//?}??
  147. ????????????//??
  148. ????????????//?},?2000);??
  149. ??
  150. ????????}??
  151. ??
  152. ????}??
  153. ??????
  154. }??


?

通过注释,大家应该很容易理解了。这里做下简单的解析。首先要注意的是,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条时加载剩余的)。

看下效果图:

? ?

? ?

?

?

就写这么多了,总的来说还是很简单的,但是确实非常有用的一个效果。欢迎留言交流。

  相关解决方案