第一次写博客,可能格式,排版什么的会非常不美观,不过我主要是为了记录自己的Android学习之路,为了以后能有些东西回顾。既然是为了学习,那我肯定会吸收各位大大们的知道经验,有不足的地方请指出。
通过本次小Demo我学到了:
- ListView的小小的一个分页功能
- 加深了对自定义控件的理解
- 对ListView的优化
- 对BaseAdapter的使用
- 自定义Adapter
- 接口的回调
本次我是通过慕课网(视频链接:http://www.imooc.com/learn/136)学习,要实现下面的效果--当拖动ListView到底部的时候,显示一个ProgressBar和一个"正在加载..."的TextView。并且过两秒钟后,在下面加载出新的数据。项目的目录结构和程序要实现的效果如下:
首先是布局部分:
我为了实现此效果,首先在布局文件中新建了一个footer_layout.xml的布局文件:
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 <LinearLayout 7 android:id="@+id/load_layout" 8 android:layout_width="match_parent" 9 android:layout_height="wrap_content" 10 android:orientation="horizontal" 11 android:paddingTop="10dip" 12 android:paddingBottom="10dip" 13 android:gravity="center" 14 > 15 <ProgressBar 16 android:layout_width="wrap_content" 17 android:layout_height="wrap_content" 18 style="?android:attr/progressBarStyleSmall" 19 android:background="#ff0000" 20 /> 21 <TextView 22 android:layout_width="wrap_content" 23 android:layout_height="wrap_content" 24 android:text="正在加载..." 25 /> 26 27 </LinearLayout> 28 29 </LinearLayout>
然后新建了一个item.xml用于作为ListView的子项:
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/tv1" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:text="哈哈哈" /> 12 <TextView 13 android:id="@+id/tv2" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 android:text="嘎嘎嘎嘎嘎" 17 /> 18 </LinearLayout>
最后在主布局文件中添加了一个自定义的ListView控件:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 > 6 7 <com.lx.loadListView.LoadListView 8 android:id="@+id/list" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:layout_alignParentTop="true" 12 android:layout_centerHorizontal="true" 13 android:cacheColorHint="#00000000" > 14 </com.lx.loadListView.LoadListView> 15 16 </RelativeLayout>
然后为了实现ListView的这种效果,我们需要一个自定义的ListView,并在上面的布局文件中引用我们自定义的ListView,代码如下:
1 package com.lx.loadListView; 2 3 import com.example.listviewloaddemo.R; 4 5 import android.content.Context; 6 import android.util.AttributeSet; 7 import android.view.LayoutInflater; 8 import android.view.View; 9 import android.widget.AbsListView; 10 import android.widget.ListView; 11 import android.widget.AbsListView.OnScrollListener; 12 13 public class LoadListView extends ListView implements OnScrollListener { 14 15 View footer; 16 int lastVisiableItem;// 最后一个可见的Item 17 int totalItemCount;// Item的总数量 18 boolean isLoading; // 正在加载 19 ILoadListener iLoadListener; 20 21 public LoadListView(Context context, AttributeSet attrs, int defStyle) { 22 super(context, attrs, defStyle); 23 // TODO 自动生成的构造函数存根 24 initView(context); 25 } 26 27 public LoadListView(Context context, AttributeSet attrs) { 28 super(context, attrs); 29 // TODO 自动生成的构造函数存根 30 initView(context); 31 } 32 33 public LoadListView(Context context) { 34 super(context); 35 // TODO 自动生成的构造函数存根 36 initView(context); 37 } 38 39 /*** 40 * 添加底部提示加载布局到listView 41 * 42 * @param context 43 */ 44 public void initView(Context context) { 45 LayoutInflater inflater = LayoutInflater.from(context); 46 footer = inflater.inflate(R.layout.footer_layout, null); 47 // 初始时候让底部布局不可见 48 footer.findViewById(R.id.load_layout).setVisibility(View.GONE); 49 this.addFooterView(footer); 50 this.setOnScrollListener(this); 51 } 52 53 @Override 54 public void onScrollStateChanged(AbsListView view, int scrollState) { 55 // TODO 自动生成的方法存根 56 // 当总共的Item数量等于最后一个Item的位置,并且滚动停止时 57 if (totalItemCount == lastVisiableItem 58 && scrollState == SCROLL_STATE_IDLE) { 59 if (!isLoading) { 60 isLoading = true; 61 footer.findViewById(R.id.load_layout).setVisibility( 62 View.VISIBLE); 63 //加载更多 64 iLoadListener.onLoad(); 65 } 66 } 67 } 68 69 /** 70 *firstVisibleItem 第一个可见Item的位置 71 *visibleItemCount 可见的Item的数量 72 *totalItemCount Item的总数量 73 **/ 74 @Override 75 public void onScroll(AbsListView view, int firstVisibleItem, 76 int visibleItemCount, int totalItemCount) { 77 // TODO 自动生成的方法存根 78 this.lastVisiableItem = firstVisibleItem + visibleItemCount; 79 this.totalItemCount = totalItemCount; 80 } 81 82 //加载完毕将footer隐藏 83 public void loadComplete(){ 84 isLoading=false; 85 footer.findViewById(R.id.load_layout).setVisibility(View.GONE); 86 } 87 88 public void setInterface(ILoadListener iLoadListener) { 89 this.iLoadListener = iLoadListener; 90 } 91 92 //加载更多数据回调接口 93 public interface ILoadListener { 94 public void onLoad(); 95 } 96 97 }
我们自定义的ListView继承自ListView,并实现其中父类的三个构造方法,为了将底部我们想要的布局加载到ListView中来,我们自定义了一个initView方法,用于找到并实例化footer_layout.xml使其添加到ListView底部。在父类的三个构造方法中添加初始化方法initView(),在initView方法的最后还要调用ListView的addFooterView(View)方法,将底部布局add进来。由于在ListView刚加载进来的时候我们不想显示这个footer,所以要设置它的Visible为GONE。想要实现ListView拉到底部的时候才显示footer,要实现ListView的OnScrollListener接口,并实现其父类中的两个方法。在OnScrollStateChanged()方法中判断是否滚动到底部(我们定义了一个全局变量lastVisibleItem=firstVisibleItem+VisibleItemCount,若此值和totalItemCount相等,则证明滚动到ListView的底端了)和此时ListView是否停止滚动(scrollState=SCROLL_STATE_IDLE)。
为了向ListView中添加数据我们定义了一个实体类Apk_Entity:
1 package com.lx.entity; 2 3 public class ApkEntity { 4 5 private String name; 6 private String info; 7 public String getName() { 8 return name; 9 } 10 public void setName(String name) { 11 this.name = name; 12 } 13 public String getInfo() { 14 return info; 15 } 16 public void setInfo(String info) { 17 this.info = info; 18 } 19 20 }