Android.GridView实现宫式布局
??
?????? 从上面的官方范例可以看出,基本的布局已经实现了。但是这并不是我们所需要的,因为要做宫式布局的话,就必须要在每一个宫,也就是一个格中,放入一个图片,并在图片下面显示文字。可能这个时候,会有人说了,那就把文字写到图片里面啊。是的,这是一种解决办法。但是是最愚蠢和最不可取的方法。因为这样将会导致系统无法实现国际化,而且文字要是有修改的话,就得修改图片,所以这是不可取的。
?????? 有基础的朋友,应该会说,那在格子中加入一个ImageView和TextView啊。对,想法是对的。可是例子中的代码是这样的:
?
?public class AppsAdapter extends BaseAdapter {
??????? public AppsAdapter() {
??????? }
??????? public View getView(int position, View convertView, ViewGroup parent) {
??????????? ImageView i;
??????????? if (convertView == null) {
??????????????? i = new ImageView(Grid1.this);
??????????????? i.setScaleType(ImageView.ScaleType.FIT_CENTER);
??????????????? i.setLayoutParams(new GridView.LayoutParams(50, 50));
??????????? } else {
??????????????? i = (ImageView) convertView;
??????????? }
??????????? ResolveInfo info = mApps.get(position);
??????????? i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager()));
??????????? return i;
??????? }
??????? public final int getCount() {
??????????? return mApps.size();
??????? }
??????? public final Object getItem(int position) {
??????????? return mApps.get(position);
??????? }
??????? public final long getItemId(int position) {
??????????? return position;
??????? }
??? }
?mGrid = (GridView) findViewById(R.id.myGrid);
??????? mGrid.setAdapter(new AppsAdapter());
?
??????????上面是主要代码,就是自定义一个Adapter来填充GridView。从getView()方法中可以看出,这个适配器只能填充一个View。我尝试加入一个LinearLayout来封装ImageView和TextView,然后在getView()方法返回。但是报错。没有执行成功!
??????????无奈之下,网上找了一下资料。发现可以使用SimpleAdapter来实现。废话少说,上代码:
?
?public class MainActivity extends Activity implements OnItemClickListener {
?private String texts[] = null;
?private Integer images[] = null;
?
?@Override
?public void onCreate(Bundle savedInstanceState) {
??super.onCreate(savedInstanceState);
??setContentView(R.layout.main);
??// 初始化图片数组和文本数组
??images = new Integer[]{ R.drawable.shoppingcart,
????R.drawable.shoppingcart, R.drawable.shoppingcart,
????R.drawable.shoppingcart, R.drawable.shoppingcart,
????R.drawable.shoppingcart, R.drawable.shoppingcart };
??
??texts = new String[]{ "宫式布局1", "宫式布局2", "宫式布局3", "宫式布局4", "宫式布局5", "宫式布局6",
??"宫式布局7" };
??// 填充GridView
??GridView gridView = (GridView) findViewById(R.id.homeGrid);
??
??SimpleAdapter simpleAdapter = new SimpleAdapter(this, fillMap(),
????R.layout.griditem, new String[] { "imageView", "imageTitle" },
????new int[] { R.id.imageView, R.id.imageTitle });
??gridView.setAdapter(simpleAdapter);
??// 监听onItemClick事件
??gridView.setOnItemClickListener(this);
?}
?public List<Map<String, Object>> fillMap() {
??List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
??for (int i = 0, j = texts.length; i < j; i++) {
???Map<String, Object> map = new HashMap<String, Object>();
???map.put("imageView", images[i]);
???map.put("imageTitle", texts[i]);
???list.add(map);
??}
??return list;
?}?
?@Override
?public void onItemClick(AdapterView<?> arg0, View arg1, int idx, long arg3) {
??// TODO Auto-generated method stub
??switch (idx) {
??case 0:
???startActivity(new Intent(this, ChoiceCarActivity.class));
???this.finish();
???break;
??default:
???break;
??}
?}
?
???????? 不急,我先来解释一下代码。代码关键在于SimpleAdapter这个类。
?????
?SimpleAdapter simpleAdapter = new SimpleAdapter(this,
?????????????????????????????????????????????????????????????????????????????????????????? ?fillMap(),
?????????????????????????????????????????????????????????????????????????????????????????? ?R.layout.griditem,
????????????????????????????????????????????????????????????????????????????????????????????new String[] { "imageView", "imageTitle" },
??????????????????????????????????????????????????????????????????????????????????????? ????new int[] { R.id.imageView, R.id.imageTitle });
?
???????? 第一个参数是Context,也就是上下文。在这里就是MainActivity这个类本身。
?????????第二个参数是List<Map<String,Object>>,也就是List里面放着一堆Maps,Map里面放着一对Key和Value,Key是String类型,Value是Object类型。这个有什么用呢?其实这里面的List放的Maps,每一个Map对应的就是一个格子,Map里面的对象就是格子里面要放的东西。GridView会从这个List中循环取出每一个Map,然后将Map中的对象一个一个取出来,填到一个格子中。
??????? 第三个参数是R.layout.griditem,这个是一个模板,也就是说GridView的每一个格子都按照这个模板来布局。后面会给出griditem的xml代码。
??????? 第四个参数是new String[]{"imageView","imageTitle"},这个参数是一个String数组,对应着Map的Key,也就是说,Map的key是什么,这里就是什么。GridView会根据这里给的数组的值来从Map中获取对应的Value。
????????第五个参数是new int[] {R.id.imageView,R.id.imageTitle},这个参数是一个int数组,对应着第三个参数的模板的控件ID。
?????? 说到这里,估计大家还是不太理解,这个SimpleAdapter是怎么工作的。我现在就详细得说一下,它的工作机制:首先GridView会先从List中循环获取Map,每一次循环List,都会从String数组(第四个参数)中循环取出String数组的值,然后作为Map的key,从而获取到该Map的对应该Key的Value。同时从int数组(第五个参数)中循环取出id值,从R.layout.griditem模板中根据这些id值获取到这些控件。这样,每一次循环List,都将会产生一些控件,和一些Value,按照顺序将Value的值填充到控件中。比如说,控件是TextView,那么这个Value就会赋值到TextView的text属性中,如果是ImageView,那么Value就会赋值到ImageView的src属性中。这样,每循环一次List,该格子就产生了两个控件,一个是ImageView,另一个是TextView,这两个控件都在模板中提前定义了。
????? 如果大家还不理解的话,我尝试写一些伪代码来帮助大家理解。
List<Map<String,Object>> list;? //第二个参数
String[]????str;//第四个参数
int []? ids;//第五个参数
int k =0;
?for(int i=0,j=list.size();i<j;i++){
??????????? Map<String,Object>? map = (Map<String,Object>)list.get(i);
????????????Object? image = map.get(str[k]);//第一个Value
????????????Object?? text = map.get(str[k+1]);//第二个Value
?
?????????????// 获取控件
???????????ImageView imageView =? (ImageView )findViewById(ids[k]);
???????????TextView textView =? (TextView )findViewById(ids[k+1]);
?
????????? //将Value赋值到控件中
?????????? imageView.setSrc(image);
????????? textView.setText(text);
?
????????? // 将控件加入到GridView的格子中
}
???????????上面是伪代码,用来描述GridView解析SimpleAdapter的过程。以上纯粹个人理解,不代表实际是这样操作的。如有错误之处,敬请原谅,并请悉心指教。
??????????? 下面附上模板XML和GridView的XML:
???????????? 1、GridView的main.xml,此为主界面。
?
?<?xml version="1.0" encoding="utf-8"?>?
????????? 2、模板griditem.xml,模板必须和main.xml分开为两个XML文件。相互独立。
?<?xml version="1.0" encoding="utf-8"?>?
?
??????????? 宫式布局已经完成。下一篇文章将会介绍如何获取用户点击的是哪一宫,哪一个格子。敬请期待。谢谢!
转载请注明文章出处:暗夜星辰 http://kandy0619.blog.163.com/