AndroidListView专题之十二分页不同的解决方案

(2011-12-15 11:51:51) 转载
标签:

android

listview

分页

it

分类:Android技术
方法一 问题 ListView 内容循环显示大家试想 假如ListView待显示的数据很庞大 从0-100 如果按照ListView默认行为 用户要找到50记录 可能要滚动很久 这显然会影响用户体验 本文的宗旨:解决这一问题 思路 1. 自定义BaseAdapter 2. 其 getCount() 返回一个固定值 比如:5 那么ListView就会只显示5个记录 3. 其 getView() 必须返回0-100记录 但需要分批显示 那如何实现呢? 定义 int index = 0; 用于记录显示当前数据的次序 用户显示下批数据 那么index++ 反之 显示以前 就index- 遗留问题 1. 当数据已经取到最后一批 那么应该使"向下翻页"Button 反白 即:不可单击 2. 同理 若此前目标是第一批数据 "向上翻页"Button 也应该反白
Java代码 public class ItemAdapter extends BaseAdapter{ Activity a; String[] data = { //....... }; @Override public int getCount() { // TODO Auto-generated method stub return 5; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return position; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub TextView tv = new TextView(a); tv.setText(data[position+index*VIEW_COUNT]); return null; } } public class ListMoreTest extends Activity{ ListView lv; Button btnLeft, btnRight; View.OnClickListener cl; MoreAdapter ma; String[] data = {"0","1","2","3","4","5","6","7","8","9","10", …..}; int VIEW_COUNT = 5; int index = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initView(); ma = new MoreAdapter(this); lv.setAdapter(ma); cl = new Button.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub switch(v.getId()) { case R.id.btnLeft: leftView(); break; case R.id.btnRight: rightView(); break; } } }; btnLeft.setOnClickListener(cl); btnRight.setOnClickListener(cl); checkButton(); } public void initView() { lv = (ListView)findViewById(R.id.list); btnLeft = (Button)findViewById(R.id.btnLeft); btnRight = (Button)findViewById(R.id.btnRight); } public void leftView() { index--; ma.notifyDataSetChanged(); checkButton(); } public void rightView() { index++; ma.notifyDataSetChanged(); checkButton(); } public void checkButton() { if(index <=0) { btnLeft.setEnabled(false); } else if(data.length - index*VIEW_COUNT <= VIEW_COUNT) { btnRight.setEnabled(false); } else { btnLeft.setEnabled(true); btnRight.setEnabled(true); } } } 方法二 Android应用开发中,采用ListView组件来展示数据是很常用的功能,当一个应用要展现很多的数据时,一般情况下都不会把所有的数据一次就展示出来,而是通过分页的形式来展示数据,个人觉得这样会有更好的用户体验。因此,很多应用都是采用分批次加载的形式来获取用户所需的数据。例如:微博客户端可能会在用户滑动至列表底端时自动加载下一页数据,也可能在底部放置一个"查看更多"按钮,用户点击后,加载下一页数据

com.andyidea.bean中News.java类是新闻实体类,包com.andyidea.listview中paginationListViewActivity.java类是用来展示ListView列表。布局layout中包含三个布局文件,分别为:list_item.xml , loadmore.xml , main.xml 。下面分别贴下源码: layout中的 list_item.xml源码: view plain 1. <span style="font-size:13px;"><?xml version="1.0" encoding="utf-8"?> 2. <LinearLayout 3. xmlns:android="http://schemas.android.com/apk/res/android" 4. android:layout_width="fill_parent" 5. android:layout_height="fill_parent" 6. android:orientation="vertical"> 7. <TextView 8. android:id="@+id/newstitle" 9. android:layout_width="fill_parent" 10. android:layout_height="wrap_content"/> 11. <TextView 12. android:id="@+id/newscontent" 13. android:layout_width="fill_parent" 14. android:layout_height="wrap_content"/> 15. </LinearLayout></span> layout中loadmore.xml源码: view plain 1. <?xml version="1.0" encoding="utf-8"?> 2. <LinearLayout 3. xmlns:android="http://schemas.android.com/apk/res/android" 4. android:layout_width="fill_parent" 5. android:layout_height="fill_parent"> 6. <Button 7. android:id="@+id/loadMoreButton" 8. android:layout_width="fill_parent" 9. android:layout_height="wrap_content" 10. android:text="查看更多..." /> 11. </LinearLayout>
layout中main.xml源码:
1. <?xml version="1.0" encoding="utf-8"?> 2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3. android:orientation="vertical" 4. android:layout_width="fill_parent" 5. android:layout_height="fill_parent"> 6. <ListView 7. android:id="@+id/lvNews" 8. android:layout_width="fill_parent" 9. android:layout_height="wrap_content"/> 10. </LinearLayou
包 com.andyidea.bean中News.java类源码:
1. public class News{ 2. 3. private String title; //标题 4. private String content; //内容 5. 6. public String getTitle() { 7. return title; 8. } 9. public void setTitle(String title) { 10. this.title = title; 11. } 12. public String getContent() { 13. return content; 14. } 15. public void setContent(String content) { 16. this.content = content; 17. } 18. 19. }
包com.andyidea.listview中paginationListViewActivity.java类源码:
2. public class PaginationListViewActivity extends Activity implements OnScrollListener{ 3. 4. private ListView listView; 5. private int visibleLastIndex = 0; //最后的可视项索引 6. private int visibleItemCount; // 当前窗口可见项总数 7. private int datasize = 38; //模拟数据集的条数 8. private PaginationAdapter adapter; 9. private View loadMoreView; 10. private Button loadMoreButton; 11. private Handler handler = new Handler(); 14. @Override 15. public void onCreate(Bundle savedInstanceState){ 16. super.onCreate(savedInstanceState); 17. setContentView(R.layout.main); 18. 19. loadMoreView = getLayoutInflater().inflate(R.layout.loadmore, null); 20. loadMoreButton = (Button)loadMoreView.findViewById(R.id.loadMoreButton); 21. loadMoreButton.setOnClickListener(new View.OnClickListener() { 22. 23. @Override 24. public void onClick(View v) { 25. loadMoreButton.setText("正在加载中..."); //设置按钮文字 26. handler.postDelayed(new Runnable() { 27. 28. @Override 29. public void run() { 30. loadMoreData(); 31. adapter.notifyDataSetChanged(); 32. loadMoreButton.setText("查看更多..."); //恢复按钮文字 33. } 34. },2000); 35. 36. } 37. }); 38. 39. listView = (ListView)findViewById(R.id.lvNews); 40. listView.addFooterView(loadMoreView); //设置列表底部视图 41. initializeAdapter(); 42. listView.setAdapter(adapter); 43. listView.setOnScrollListener(this); 44. } 45. 46. @Override 47. public void onScrollStateChanged(AbsListView view, int scrollState){ 48. int itemsLastIndex = adapter.getCount()-1; //数据集最后一项的索引 49. int lastIndex = itemsLastIndex + 1; 50. if (scrollState == OnScrollListener.SCROLL_STATE_IDLE 51. && visibleLastIndex == lastIndex) { 52. // 如果是自动加载,可以在这里放置异步加载数据的代码 53. } 54. } 55. 56. 57. @Override 58. public void onScroll(AbsListView view, int firstVisibleItem, 59. int visibleItemCount, int totalItemCount){ 60. this.visibleItemCount = visibleItemCount; 61. visibleLastIndex = firstVisibleItem + visibleItemCount - 1; 62. 63. Log.e("========================= ","========================"); 64. Log.e("firstVisibleItem = ",firstVisibleItem+""); 65. Log.e("visibleItemCount = ",visibleItemCount+""); 66. Log.e("totalItemCount = ",totalItemCount+""); 67. Log.e("========================= ","========================"); 68. 69. //如果所有的记录选项等于数据集的条数,则移除列表底部视图 70. if(totalItemCount == datasize+1){ 71. listView.removeFooterView(loadMoreView); 72. Toast.makeText(this, "数据全部加载完!", Toast.LENGTH_LONG).show(); 73. } 74. } 75. 76. 79. private void initializeAdapter(){ 80. List<News> newnews = new ArrayList<News>(); 81. for(int i=1;i<=10;i++){ 82. News items = new News(); 83. items.setTitle("Title"+i); 84. items.setContent("This is News Content"+i); 85. news.add(items); 86. } 87. adapter = new PaginationAdapter(news); 88. } 89. 90. 93. private void loadMoreData(){ 94. int count = adapter.getCount(); 95. 96. if(count+10 <= datasize){ 97. for(int i=count+1; i<=count+10; i++){ 98. News item = new News(); 99. item.setTitle("Title"+i); 100. item.setContent("This is News Content"+i); 101. adapter.addNewsItem(item); 102. } 103. }else{ 104. for(int i=count+1; i<=datasize; i++){ 105. News item = new News(); 106. item.setTitle("Title"+i); 107. item.setContent("This is News Content"+i); 108. adapter.addNewsItem(item); 109. } 110. } 111. 112. } 113. 114. 115. class PaginationAdapter extends BaseAdapter{ 116. 117. List<News> newsItems; 118. 119. public PaginationAdapter(List<News> newsitems){ 120. this.newsItems = newsitems; 121. } 122. 123. @Override 124. public int getCount(){ 125. return newsItems.size(); 126. } 127. 128. @Override 129. public Object getItem(int position){ 130. return newsItems.get(position); 131. } 132. 133. @Override 134. public long getItemId(int position){ 135. return position; 136. } 137. 138. @Override 139. public View getView(int position, View view, ViewGroup parent){ 140. if(view == null){ 141. view = getLayoutInflater().inflate(R.layout.list_item, null); 142. } 143. 144. //新闻标题 145. TextView tvTitle = (TextView)view.findViewById(R.id.newstitle); 146. tvTitle.setText(newsItems.get(position).getTitle()); 147. //新闻内容 148. TextView tvContent = (TextView)view.findViewById(R.id.newscontent); 149. tvContent.setText(newsItems.get(position).getContent()); 150. 151. return view; 152. } 153. 154. 158. public void addNewsItem(News newsitem){ 159. newsItems.add(newsitem); 160. } 161. 162. } 163. 164. } 最后,运行程序的结果截图如下: 通过上面的截图,当我们点击"查看更多..."按钮时,就会加载下10条记录,当加载完所有的记录后,ListView的底部视图将会移除。 方法三 Android market里软件列表,每页显示10条记录,没有显示上一页,下一页的按钮,依靠手滑动动态加载数据,当向下滚动时,最下边显示 Loading… 。数据加载结束,Loading底栏消失。 关于ListView的分段显示,有现成的库可用,比如 cwac-endless, 这个库不好之处,就是底部Loading的View无法定制。还有一个在google code上的androidpageablelistview 这个可以实现基本的分页,有手动操作显示上一页,下一页的按钮。 查阅了很多资料,发现其实ListView自带一个实现分页加载的方法,用到addFooterView/removeView 这两个函数“添加”或“去掉“ListView页脚。下面是一个研究ListView分页时做的一个Demo,比较简单,我把思路我源码和大家分享一下,希望对大家有所帮助 ListView专题之十二分页不同的解决方案" style="margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; list-style-type:none; list-style-position:initial;border:1px solid black;">
实现思路如下: 用onScroll方法实现”滑动“后处理检查是否还有新的记录,如果有,调用addFooterView,添加记录到adapter, adapter调用 notifyDataSetChanged 更新数据;如果没有记录了, 把自定义的mFooterView去掉。这里没有重写onScrollStateChanged函数,那么在onScroll就需要一个外部变量mFirstCell记录滑动位置。
public class MainActivity extends ListActivity implements OnScrollListener{ private static final String TAG = "MainActivity"; private listViewAdapter adapter = new listViewAdapter(); ListView listView ; private int lastItem = 0; LinearLayout loadingLayout; private LayoutParams mLayoutParams =new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); private LayoutParams FFlayoutParams =new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); Log.i(TAG, "onCreate(Bundle savedInstanceState)>>>>>>>>>>>>>>>" ); //线性布局 LinearLayout layout = new LinearLayout(this); //设置布局 水平方向 layout.setOrientation(LinearLayout.HORIZONTAL); //进度条 progressBar = new ProgressBar(this); //进度条显示位置 progressBar.setPadding(0, 0, 15, 0); //把进度条加入到layout中 layout.addView(progressBar, mLayoutParams); //文本内容 TextView textView = new TextView(this); textView.setText("加载中..."); textView.setGravity(Gravity.CENTER_VERTICAL); //把文本加入到layout中 layout.addView(textView, FFlayoutParams); //设置layout的重力方向,即对齐方式是 layout.setGravity(Gravity.CENTER); //设置ListView的页脚layout loadingLayout = new LinearLayout(this); loadingLayout.addView(layout, mLayoutParams); loadingLayout.setGravity(Gravity.CENTER); //得到一个ListView用来显示条目 listView = getListView(); //添加到脚页显示 listView.addFooterView(loadingLayout); //给ListView添加适配器 setListAdapter(adapter); //给ListView注册滚动监听 listView.setOnScrollListener(this); } @Override public void onScroll(AbsListView v, int firstVisibleItem, int visibleItemCount, int totalItemCount) { Log.i(TAG , "Scroll>>>first: " + firstVisibleItem + ", visible: " + visibleItemCount + ", total: " + totalItemCount); lastItem = firstVisibleItem + visibleItemCount - 1; Log.i(TAG , "Scroll>>>lastItem:" + lastItem); //显示50条ListItem,即0-49,因为onScroll是在“滑动”执行过之后才触发,所以用adapter.count<= 41 作条件 if (adapter.count<=41) { if (firstVisibleItem+visibleItemCount==totalItemCount) { adapter.count += 10; adapter.notifyDataSetChanged(); listView.setSelection(lastItem); int currentPage=adapter.count/10; Toast.makeText(getApplicationContext(), "第"+currentPage+"页", Toast.LENGTH_LONG).show(); } } else { listView.removeFooterView(loadingLayout); }
} @Override public void onScrollStateChanged(AbsListView v, int state) { if (lastItem == adapter.count && state == OnScrollListener.SCROLL_STATE_IDLE) { Log.i(TAG,"ScrollStateChanged>>>state:"+state+"lastItem:" + lastItem); //显示50条ListItem,即0-49,因为onScrollStateChanged是在“拖动滑动”执行过之后才触发,所以 用 adapter.count<=41作条件 if (adapter.count<=41) { adapter.count += 10; adapter.notifyDataSetChanged(); } } } class listViewAdapter extends BaseAdapter{ int count = 10; public int getCount() { Log.i(TAG, "getCount>>>count:" + count); return count; }
public Object getItem(int pos) { Log.i(TAG, "getItem>>>pos:" + pos); return pos; }
public long getItemId(int pos) { Log.i(TAG, "getItemId>>>ItemId:" + pos); return pos; }
public View getView(int pos, View v, ViewGroup p) { Log.i(TAG, "getView>>>pos:" + pos); TextView view; if (v==null) { view = new TextView(MainActivity.this); } else { view=(TextView)v; } view.setText("ListItem " + pos); view.setTextSize(20f); view.setGravity(Gravity.CENTER); view.setHeight(60); return view; } } }

更多相关文章

  1. mybatisplus的坑 insert标签insert into select无参数问题的解决
  2. python起点网月票榜字体反爬案例
  3. android之sqliteDatabase,sqliteOpenHelper,ContentProvider
  4. Android日志系统Logcat源代码简要分析
  5. 【Android(安卓)初学者】开发工具介绍:studio
  6. android 一个SQLite数据库多个数据表的基本使用框架 (带demo)
  7. 3-14 servlet 传出对象给 Android
  8. 全程不用usb数据线,adb通过网络连接Android设备
  9. android(NDK+JNI)---Android使用JNI实现Java与C之间传递数据

随机推荐

  1. What Android(安卓)Chipset Can Support
  2. Android(安卓)获取CPU架构(指令集)
  3. Android(安卓)使用广播(BroadcastReceiver
  4. Android(安卓)创建与解析XML(五)—— Dom4j
  5. Android(安卓)自定义seekbar
  6. Android(安卓)代码中实现返回键功能
  7. Android中ContextMenu的使用
  8. android 对话框总结
  9. Android(安卓)中三种使用线程的方法
  10. Android(安卓)监听网络变化