学习android也有一段时间了,老是想要通过总结的形式形成文档保存起来,但是一直都没能实现起来,一是本人挺懒的,有严重的拖延症,而是确实没什么时间来弄,每天回到宿舍已经是九点多了,宿舍人多,洗个澡,洗一下衣服,已经是十一点多了,不想明天的状态又是顶着两个黑眼圈来学习。所以,唉,还是自己的问题!
写总结,我越来越觉的很有必要,俗话说好记性不如烂笔头,你记性再好都会忘光光的,所以记录总结是最好的方式了。
好的,今天要总计的是ListView,就是一个列表视图,不要小看这个组件,很多的主流的app都用到了ListView,所先,这个ListView要怎么用呢?
ListView可以看成是一个容器,他所要存放的就是数据,然而,数据又不能直接存放在里面,必须通过一个中间件——适配器(Adapter),所以我们的重点就是了解并用好这个适配器。
适配器有三种,分别是数组适配器(ArrayAdapter),简单适配器(SimpleAdapter),通用适配器(BaseAdapter)。
数组设配器:
这个是三者中最简单的,我们通过代码来学习:
public class ListViewByEntity extends ActionBarActivity {
private ListView lvObj;
private String citys[]=new String[]{
"北京",
"上海",
"广州",
"成都",
"安徽"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view_by_entity);
lvObj=(ListView)findViewById(R.id.listView);
ArrayAdapter<String> dataAdpater=new ArrayAdapter<String>(
this,
R.layout.item01,
R.id.city,citys);*/
ArrayAdapter<String> dataAdpater=new ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,citys);
//将适配器组件对象加载到ListView组件中
lvObj.setAdapter(dataAdpater);
}
}
如代码中所见,实例化一个ArrayAdapter对象,他的构造器有三个参数,是 context:指当前窗体对象(上下文),resource:每个item对应布局文件的索引值,textViewResourceId:每个item对应布局文件里面对应TextView组件的ID值,objects:数组数据,里面的item布局一般是用android自带的布局R.layout.item01,实例化添加数据后,设配器里面就有数据了,ListView类中有setAdapter的方法,然后把设配器添加就去就可以了。
简单设配器(SimpleAdapter):
SimpleAdapter跟ArrayAdapter差不多一样,只不过SimpleAdapter是用ArrayList来存放数据,而且数据也比较复杂起来,示例代码如下,
private ListView lvObj;
private ArrayList<HashMap<String,Object>> data=new ArrayList<>();
private int qqiconIds[]=new int[]{
R.drawable.orange_pic,
R.drawable.apple_pic,
R.drawable.banana_pic,
R.drawable.pineapple_pic
};
private String qqnames[]=new String[]{
"橘子",
"苹果",
"香蕉",
"菠萝"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view_by_simple_adpater);
for(int index=0;index<qqnames.length;index++)
{
HashMap<String,Object> rowData=new HashMap<>();
rowData.put("qqicon",qqiconIds[index]);
rowData.put("qqname",qqnames[index]);
data.add(rowData);
}
SimpleAdapter simpleAdapterData=new SimpleAdapter(
this,
data,
R.layout.item02,
new String[]{"qqicon","qqname"},
new int[]{R.id.qqiconId,R.id.qqnameId}
);
lvObj=(ListView)findViewById(R.id.lvId);
lvObj.setAdapter(simpleAdapterData);
}
}
同样我们也是要实例化一个SimpleAdapter对象,他的构造方法也有这么几个参数,我们来看一下,context:指当前窗体对象(上下文),data:适配器的数据源,resource:每个item对应布局文件的索引值,from:每个item数据对应Map类型的key值,to:每个item对应布局文件里面的组件ID值(注意值顺序必须跟from一致),添加后就可以setAdapter进去了。
通用设配器(BaseAdapter):
这个设配器与前两个不同,这是需要我们自己来重写的一个适配器,其实,SimpleAdapter就是在ArrayAdapter里重写了一些代码,一般情况下,我们想要显示的数据都是比较复杂的,多种多样的,比如文本,图像,按钮,单选,复选等等,所以BaseAdapter是我们比较多用的设配器,这里我们用了一个内部类,继承BaseAdapter,实现他的几个方法,其中最主要的就是getView方法:
public class ListViewByBaseAdpater extends ActionBarActivity {
//自定义适配器
class MyAdpater extends BaseAdapter
{
ArrayList<QqinfoEntity> list=new ArrayList<>();
MyAdpater(ArrayList<QqinfoEntity> list) {
this.list = list;
}
//返回有多少个item
@Override
public int getCount() {
return list.size();
}
//获取item的数据对象
@Override
public Object getItem(int position) {
return list.get(position);
}
//获取item的对应索引值
@Override
public long getItemId(int position) {
return position;
}
public void addRowData(QqinfoEntity entity)
{
list.add(entity);
notifyDataSetChanged();
}
//获取每个item对应的布局对象
//convertView:存储item布局对象的缓冲
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//动态加载布局文件,将布局文件转化为View对象
View view;
SurfaceHolder surfaceHolder;
if(convertView==null)
{
view= LayoutInflater.from(ListViewByBaseAdpater.this).inflate(R.layout.item02,null);
//获取item02布局文件里面的组件对象
surfaceHolder=new SurfaceHolder();
surfaceHolder.qqIconIamgeViewObj=(ImageView)view.findViewById(R.id.qqiconId);
surfaceHolder.qqnameTvObj=(TextView)view.findViewById(R.id.qqnameId);
view.setTag(surfaceHolder);
}else{
view=convertView;
surfaceHolder=(SurfaceHolder)view.getTag();
}
QqinfoEntity entity=(QqinfoEntity)list.get(position);
//将数据赋值给到ImageView组件和TextView组件
surfaceHolder.qqIconIamgeViewObj.setImageDrawable(getResources().getDrawable(entity.getQqiconId()));
surfaceHolder.qqnameTvObj.setText(entity.getQqname());
return view;
}
class SurfaceHolder
{
ImageView qqIconIamgeViewObj;
TextView qqnameTvObj;
}
}
ArrayList<QqinfoEntity> data=new ArrayList<>();
private ListView lvObj;
private Button addBtnObj;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view_by_base_adpater);
initData();
lvObj=(ListView)findViewById(R.id.lvId);
addBtnObj=(Button)findViewById(R.id.btnaddId);
final MyAdpater myAdpaterObj=new MyAdpater(data);
lvObj.setAdapter(myAdpaterObj);
addBtnObj.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
QqinfoEntity entity=new QqinfoEntity();
// R.drawable.banana_pic
entity.setQqiconId(R.drawable.banana_pic);
entity.setQqname(“香蕉”);
myAdpaterObj.addRowData(entity);
}
});
}
//初始化集合数据
public void initData()
{
int qqiconIds[]=new int[]{
R.drawable.orange_pic,
R.drawable.apple_pic
};
String qqnames[]=new String[]{
"橘子",
"苹果"
};
for(int index=0;index<qqiconIds.length;index++)
{
QqinfoEntity entity=new QqinfoEntity();
entity.setQqiconId(qqiconIds[index]);
entity.setQqname(qqnames[index]);
data.add(entity);
} }
}
可以看到,adapter的主要功能实现就是在getView方法中,这里有一个技巧,就是如何优化adapter的数据,而不用每一次都是去findviewbyid,消耗内存,数据小看不出来,数据量一大就回不流畅起来,所以最好还是做一些优化,做法就是判断convertView缓存是否存在,不存在采取findviewbyid,存在就直接赋予就可以了。其中SurfaceHolder的这个类其实就是为了方便数据的存储而设置的,你也可以直接赋值。然后在oncreate实现添加adapter就可以了。
这些都是在Activity中用的比较多,现在基本用Fragment的比较多,那么如何在Fragment实现ListView,用之前的方法也是可以实现的,只是比较麻烦而已,最简单的就是让Fragment继承一个ListFragment的父类,但是你的布局文件中的listview中的id一定要是android:id/list,这是android规定的,具体的内容我会在后面的Fragment讲到。