这几天学习了一下安卓的gridview和listview,其中难点感觉在适配器上,经过学习,感觉掌握了一些规律,今天打完球洗个澡,感觉状态刚刚好,总结一下作为我以后的笔记,如有不对,请指正。
适配器:我认为适配器就是一个类,在实例化适配器的过程中,将复杂的数据通过适配器有条理的在view中显示出来。
一、arrayadapter
这个适配器只能最简单只能显示一行字,一般用于spinner组件。数据源也很简单一般是string[]。上代码:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.ano2);
s2=new Spinner(this);
s2=(Spinner)findViewById(R.id.spinner1);
s2.setOnItemSelectedListener(this);//为点击每一项加监听
ArrayAdapter<CharSequence> array;
array=ArrayAdapter.createFromResource(this, R.array.xl, android.R.layout.simple_dropdown_item_1line);//实例化一个构造器,参数意义:context,数据源,布局方式(这里我采用安卓默认布局)
array.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);//spinner组件(下拉菜单)的显示方式,采用默认布局
s2.setAdapter(array);//将适配器与实例化的spinner组件绑定,从而将数据有规律的显示在spinner组件上。显示的数据每一行都是一个Textview,是一个组件。
}
数据源存放:
<string-array name="xl">
<item>小花</item>
<item>小明</item>
<item>小翠</item>
</string-array>
二、simpleadapter
说实话,这个适配器是我最喜欢的,感觉用起来非常舒服, 而且自由度挺高的(除了自定义适配器),可用于listview和gridview,重点是要记住实例化适配器时几个参数的意义。数据源为list。
这里以listview为例
public class Another1 extends Activity{
private ListView lv;
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.another1);
lv=(ListView)findViewById(R.id.listView1);
//重点
SimpleAdapter sa=new SimpleAdapter(this, getdata(), R.layout.another1one, new String[]{"img","t1","t2"}, new int[]{R.id.img,R.id.t1,R.id.t2});//参数意义:context,数据源,单个项布局, map里面填充K:V对时的K值,单个项布局时每个组件的位置
lv.setAdapter(sa);
}
//数据源,这里使用list里面包装map的形式,
private List<Map<String, Object>> getdata() {
// TODO Auto-generated method stub
List<Map<String, Object>> l=new ArrayList<Map<String,Object>>();//实例化list
//不要问我为什么不用循环,因为I’m a loser
Map<String, Object> m1=new HashMap<String, Object>();//实例化map
m1.put("img", R.drawable.ic_launcher);//以k:v形式填充数据
m1.put("t1", "loser");
m1.put("t2", "you are");
Map<String, Object> m2=new HashMap<String, Object>();
m2.put("img", R.drawable.ic_launcher);
m2.put("t1", "loser");
m2.put("t2", "you are");
Map<String, Object> m3=new HashMap<String, Object>();
m3.put("img", R.drawable.ic_launcher);
m3.put("t1", "loser");
m3.put("t2", "you are");
Map<String, Object> m4=new HashMap<String, Object>();
m4.put("img", R.drawable.ic_launcher);
m4.put("t1", "loser");
m4.put("t2", "you are");
Map<String, Object> m5=new HashMap<String, Object>();
m5.put("img", R.drawable.ic_launcher);
m5.put("t1", "loser");
m5.put("t2", "you are");
l.add(m1);//把map填充到list里
l.add(m2);
l.add(m3);
l.add(m4);
l.add(m5);
return l;//返回填充好的数据源
}
}
单个项的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="46dp"
android:orientation="vertical" >
<TextView
android:id="@+id/t1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<TextView
android:id="@+id/t2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:gravity="center" />
</LinearLayout>
</LinearLayout>
绑定布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
感悟:这个用起来非常舒服,不考虑别的,只要加参数就可以了。
三、自定义适配器(基于baseadapter)
这个适配器灵活性最大,继承baseadapter类之后需要重写四个方法, 重点是getView方法,等下会介绍。我的感觉时能用simpleadapter不用自定义的,不好玩
public class Another6 extends Activity{
private GridView gv;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.another6);
gv=(GridView)findViewById(R.id.gridView6);
liu l=new liu(this);//实例化适配器
gv.setAdapter(l);
}
}
class liu extends BaseAdapter{//外部类要找到上下文,需要重写构造方法引入Another6
private LayoutInflater lf=null;
public liu(Another6 a6){
this.lf=LayoutInflater.from(a6);
}
//获取数据的长度,即有几个数据项
@Override
public int getCount() {
// TODO Auto-generated method stub
return getdata().size();
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
//重点,获取view组件的方法
@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {//参数意义:position,convertview,父容器
// TODO Auto-generated method stub
viewholder2 vh;
if (arg1==null) {//将布局中的包含关系在这里实例化
arg1=lf.inflate(R.layout.another6one, null);
//将布局文件用填充器实例化 ,作用类似于findviewbyid
vh=new viewholder2();
vh.iv=(TextView)arg1.findViewById(R.id.textView1);
arg1.setTag(vh);//将每个组件实例化后以标签(tag)形式放到arg1中
} else {
vh=(viewholder2)arg1.getTag();//从tag中取出封转好的对象
}
vh.iv.setText((String)getdata().get(arg0).get("tit"));//将数据传给实例化的组件
return arg1;
}
//获得数据源的方法,与simpleadapter的一样
private List<Map<String, Object>> getdata(){//采用simpleadapter中数据的存放方式
List<Map<String, Object>> l=new ArrayList<Map<String,Object>>();
Map<String, Object> m=new HashMap<String, Object>();
for (int i = 0; i <15; i++) {
m.put("tit", "刘六六");
l.add(m);
}
return l;
}
class viewholder2{//用来存放组件地址,方便以后赋值不用再查找
TextView iv;
}
}
单项布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="14dp"
android:text="TextView" />
</RelativeLayout>
绑定布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<GridView
android:id="@+id/gridView6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="3" >
</GridView>
</LinearLayout>
当然自定义适配器还是有好处的,两个优化:
1、对于view的重复利用
利用convertview,只创建屏幕可见的加一个,这个原理类似于电梯原理(可见的阶梯12个,还有12个不可见,阶梯循环利用)这样的话,要是有1亿个view就只加载可见的,解决方法:
if (arg1==null) {//将布局文件在这里实例化
arg1=lf.inflate(R.layout.another6one, null);
//当没有时才加载
vh=new viewholder2();
vh.iv=(TextView)arg1.findViewById(R.id.textView1);
arg1.setTag(vh);
}
2、一个单项布局文件里可能有多个组件,每次为组件赋值就要查找一次,太麻烦了,我们可以先把组件实例化,放到实例化的布局文件里,每次只要取出赋值即可。解决方案:
class viewholder2{//用来存放组件地址,方便以后赋值不用再查找
TextView iv;
}
vh=new viewholder2();
vh.iv=(TextView)arg1.findViewById(R.id.textView1);
arg1.setTag(vh);//将每个组件实例化后以标签(tag)形式放到arg1中
} else {
vh=(viewholder2)arg1.getTag();//从tag中取出封转好的对象
}
vh.iv.setText((String)getdata().get(arg0).get("tit"));//将数据传给实例化的组件