ListView是android开发中比较常用的控件,
其中适配器模式可以选择:
ArrayAdapter:简单易用,通常用于将数组或者List集合的读个包值封装成多个列表项
SimpleAdapter:其实功能很强大将数组或者List集合的读个包值封装成多个列表项
SimpleCursorAdapter:与SimpleAdapter基本类似只是用于包装Cursor提供的数据
BaseAdapter:通常用于被扩展,扩展BaseAdapter可以对各列表项进行最大的定制
而且ListView组件提供了两个很实用的功能,那就是可以在顶部和底部添加自定义的视图,今天自己做了一下小Demo加深一下这个控件的使用,实现分批显示的功能,即在一个手机屏幕下方放置一个加载更多的按钮,点击之后更新下一页的内容,详细注释均在代码中
首先定义一个activity_main.xml,为了防止listview中点击有黄色背景或者滑动出现黑色背景加了 android:cacheColorHint="#000000" android:listSelector="@android:color/transparent"
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:paddingLeft="3dp" android:paddingRight="3dp" > <!-- 这里我们用到了Android内置名为list的id,后面要用到ListActivity --> <ListView android:id="@id/android:list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:cacheColorHint="#000000" android:listSelector="@android:color/transparent"/> </LinearLayout>
然后就是list_item.xml,作为listview的布局文件,比较简单
<?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/list_item_text" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:textSize="20sp" android:paddingTop="10dp" android:paddingBottom="10dp"/> </LinearLayout> <!-- 这里ListView中单个列表的布局文件 -->
接着就是底部加载更多的视图more.xml
<?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content"> <Button android:id="@+id/loadMoreButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="更多显示请点击" android:onClick="loadMore"/> </LinearLayout>
适配器作为连接Activity和数据格式的过度器件,这里定义如下,代码中有着详细的注释
package com.xsf.listviewtest; import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.example.listviewtest.R; /* * 继承BaseAdapter实例化需要Context对象来获取LayoutInflater实例和一个集合来充当适配器的数据收集 * 在getView方法中填充list_item.xml布局文件完成每一项的数据显示 * addItem方法用来加载数据时向数据集合中添加新的数据 */ public class ListViewAdapter extends BaseAdapter { private List<String> items; //LayoutInflater的作用类似于 findViewById(),不同点是LayoutInflater是用来找layout文件夹下的xml布局文件,并且实例化! private LayoutInflater inflater; public ListViewAdapter(Context context, List<String> items) { this.items = items; inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { return items.size(); } @Override public Object getItem(int position) { return items.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View view, ViewGroup parent) { if (view == null) { view = inflater.inflate(R.layout.list_item, null); } TextView text = (TextView) view.findViewById(R.id.list_item_text); text.setText(items.get(position)); return view; } /** * 添加列表项 * * @param item */ public void addItem(String item) { items.add(item); } }
最后就是MainActivity,主要用到了 onScroll(AbsListView view, int firstVisibleItem int visibleItemCount, int totalItemCount)其中firstVisibleItem表示在现时屏幕第一个ListItem(部分显示的ListItem也算)在整个ListView的位置(下标从0开始),visibleItemCount表示在现时屏幕可以见到的ListItem(部分显示的ListItem也算)总数,totalItemCount表示ListView的ListItem总数
package com.xsf.listviewtest; import java.util.ArrayList; import android.app.ListActivity; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.Button; import android.widget.ListView; import com.example.listviewtest.R; public class MainActivity extends ListActivity implements OnScrollListener { private ListView listView; private int visibleLastIndex = 0; // 最后的可视项索引 private int visibleItemCount; // 当前窗口可见项总数 private ListViewAdapter adapter; private View loadMoreView; private Button loadMoreButton; private Handler handler = new Handler();// 多线程处理handler @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** * LayoutInflater这个类的作用类似于findViewById(), 不同点: * LayoutInflater是用来找layout下xml布局文件的,而且它会实例化 * findViewById()是找具体xml布局文件下的具体widget控件,比如:Button按钮 * * inflate就相当于将一个xml中定义的布局找出来. * 因为如果在一个Activity文件里直接用findViewById()这个方法的话, * 那么它所对应的是setConentView()中调用的那个layout里的组件. * 因此如果在同样的Activity里用到别的layout的话, * 而且你还要设置这个layout里的组件(比如:ImageView,TextView)上的内容, * 那么你就必须用inflate()先将这个layout找出来, 然后再用这个layout对象去找到它上面的组件 然后进行一系列的操作 * * inflate()方法中参数: 1.想要用的布局文件的id 2.持有选项卡的内容,获取加载视图的xml * 3.null:将此处解析的xml文件不做为根视图View */ loadMoreView = getLayoutInflater().inflate(R.layout.more, null);// 每次解析都会出现新的视图不会出现引用问题 loadMoreButton = (Button) loadMoreView .findViewById(R.id.loadMoreButton); listView = getListView(); // 获取id是list的ListView /*ListView组件提供了两个很实用的功能,那就是可以在顶部和底部添加自定义的视图*/ listView.addFooterView(loadMoreView); //设置列表底部视图 initAdapter(); setListAdapter(adapter); // 自动为id是list的ListView设置适配器 listView.setOnScrollListener(this); // 添加滑动监听 } /** * 初始化适配器 */ private void initAdapter() { ArrayList<String> items = new ArrayList<String>(); for (int i = 0; i <10; i++) { items.add(String.valueOf(i + 1)); } adapter = new ListViewAdapter(this, items); } /* * 滑动时被调用 */ @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { this.visibleItemCount = visibleItemCount; visibleLastIndex = firstVisibleItem + visibleItemCount - 1; } /* * 滑动状态改变时被调用 */ @Override public void onScrollStateChanged(AbsListView view, int scrollState) { int itemsLastIndex = adapter.getCount() - 1; // 数据集最后一项的索引 int lastIndex = itemsLastIndex + 1; // 加上底部的loadMoreView项 if (scrollState == OnScrollListener.SCROLL_STATE_IDLE && visibleLastIndex == lastIndex) { Log.i("MORE", "loading..."); } } /* * 点击按钮的事件 */ public void loadMore(View view) { loadMoreButton.setText("玩命加载中.....");// 设置按钮加载文字 handler.postDelayed(new Runnable() { @Override public void run() { loadData(); adapter.notifyDataSetChanged();// 数据集变化后通知adapter listView.setSelection(visibleLastIndex - visibleItemCount + 1);// 设置选中项 loadMoreButton.setText("more");// 回复按钮文字 } }, 3000); } /* * 模拟加载数据 */ protected void loadData() { int count = adapter.getCount(); for (int i = count; i < count + 10; i++) { adapter.addItem(String.valueOf(i + 1)); } } }