ListView的不同item加载不同Layout

在重写ListView的BaseAdapter时,我们常常在getView()方法中复用convertView,优化ListView以提高性能。convertView在Item为单一的同种类型布局时,能够回收并重用,但是多个Item布局类型不同时,convertView的回收和重用会出现问题。比如有些行为纯文本,有些行则是图文混排,这里纯文本行为一类布局,图文混排的行为第二类布局。单一类型的ListView很简单,下面着重介绍一下ListView包含多种类型视图布局的情形,首先看图效果展示:

点击下载该内容源码


  

在编写代码之前呢,我们需要做这些工作并了解其作用:

  1)重写 getViewTypeCount() – 该方法返回多少个不同的布局

  2)重写 getItemViewType(int) – 根据position返回相应的Item

  3)根据view item的类型,在getView中创建正确的convertView

下面让我们看一下代码怎么实现:

MainActivity.class

/**
 *
 *ListViewDifferentType
 * @author Yuanjunhua
 *
 * 2014-7-28下午6:23:39
 */
public class MainActivity extends Activity {

	private ListView listView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		listView=(ListView) findViewById(R.id.lsitview);
		String[] name1=new String[]{"北京","上海","南京","郑州","轻工业学院","姜寨村"};
		String[] name2=new String[]{"北京","上海","南京","郑州","轻工业学院","姜寨村"};
		Integer[] id2=new Integer[]{
				R.drawable.jx_left_listitem_1,
				R.drawable.jx_left_listitem_2,
				R.drawable.jx_left_listitem_3,
				R.drawable.jx_left_listitem_4,
				R.drawable.jx_left_listitem_5,
				R.drawable.jx_left_listitem_6};

		List<String> list1=new ArrayList<String>();
		fillListMethod(list1,name1);

		List<Map<String,Integer>> list2=new ArrayList<Map<String,Integer>>();
		fillMapMethod(list2,name2,id2);

		Log.d("mapList", "mapList=="+list1);
		Log.d("strList", "strList=="+list2);
		listView.setAdapter(new MyAdapter(this, list1, list2));

	}

	private void fillMapMethod(List<Map<String, Integer>> list,String[] name,Integer[] id) {
		// TODO Auto-generated method stub
		for (int i = 0; i < name.length; i++) {
			Map<String,Integer> map=new HashMap<String, Integer>();
			map.put(name[i], id[i]);
			list.add(map);
		}
	}

	private void fillListMethod(List<String> list,String[] name) {
		// TODO Auto-generated method stub
		for (int i = 0; i < name.length; i++) {
			list.add(name[i]);
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

继承BaseAdapter

/**
 *
 *ListViewDifferentType
 * @author Yuanjunhua
 *
 * 2014-7-28下午6:23:31
 */
public class MyAdapter extends BaseAdapter {

	private LayoutInflater li;
	private List<String> list;
	private List<Map<String,Integer>> map;
	private final int TYPE_ONE=0,TYPE_TWO=1,TYPE_COUNT=2;
	public MyAdapter(Context context,List<String> list,List<Map<String,Integer>> map) {
		// TODO Auto-generated constructor stub
		this.list =list;
		this.map =map;
		li=LayoutInflater.from(context);
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return list.size()+map.size();
	}

	/** 该方法返回多少个不同的布局*/
	@Override
	public int getViewTypeCount() {
		// TODO Auto-generated method stub
		return TYPE_COUNT;
	}
	/** 根据position返回相应的Item*/
	@Override
	public int getItemViewType(int position) {
		// TODO Auto-generated method stub
		int po = position % 2;
		if (po == TYPE_ONE)
			return TYPE_ONE;
		else
			return TYPE_TWO;
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return list.get(position%6);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position%6;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		ViewHolder1 vh1=null;
		ViewHolder2 vh2=null;
		int type=getItemViewType(position);
		if(convertView==null){
			switch (type) {
			case TYPE_ONE:
				vh1=new ViewHolder1();
				convertView=li.inflate(R.layout.item_one, null);
				vh1.tv1=(TextView) convertView.findViewById(R.id.tv1);

				convertView.setTag(vh1);

				break;
			case TYPE_TWO:
				vh2=new ViewHolder2();
				convertView=li.inflate(R.layout.item_two, null);
				vh2.tv2=(TextView) convertView.findViewById(R.id.tv2);
				vh2.img2=(ImageView) convertView.findViewById(R.id.img2);
				convertView.setTag(vh2);
				break;
			}
		}
		else{
			switch (type) {
			case TYPE_ONE:
				vh1=(ViewHolder1) convertView.getTag();
				break;
			case TYPE_TWO:
				vh2=(ViewHolder2) convertView.getTag();
				break;
			}
		}

		switch (type) {
		case TYPE_ONE:
			if(position<5)
			vh1.tv1.setText(list.get((position%6)-(position%6)/2));
			if(position>5)
				vh1.tv1.setText(list.get((position%6)-(position%6)/2+3));
			break;
		case TYPE_TWO:
			int i=0;
			String txt=null;
			Map<String,Integer> mapSI=null;
			if(position<6){
				i=(position%6)-(position%6+1)/2;
				mapSI=map.get(i);
				Iterator<String> it=mapSI.keySet().iterator();
				if(it.hasNext()) txt=it.next();
			}

			if(position>6){
				i=(position%6)-(position%6+1)/2+3;
				mapSI=map.get(i);
				Iterator<String> it=mapSI.keySet().iterator();
				if(it.hasNext()) txt=it.next();
			}
			vh2.tv2.setText(txt);
			vh2.img2.setBackgroundResource(mapSI.get(txt));
			Log.d("txt", "txt=="+txt);
			break;
		}
		return convertView;
	}

	static class ViewHolder1{
		TextView tv1;
	}
	static class ViewHolder2{
		TextView tv2;
		ImageView img2;
	}

}

实现上图的效果就用这么几句代码!!

ListView的不同item加载不同Layout

时间: 2024-10-13 14:41:32

ListView的不同item加载不同Layout的相关文章

cocos2dx ListView 大量 Item 加载方案(转)

[原]cocos2dx ListView 大量 Item 加载方案 2014-11-17阅读599 评论3 问题描述: 在项目中对于常常要在一个ListView中加载大量Item这种需求应该都是比较常见的需求.按一般的做法我们常常会遇到如下瓶颈问题: 1.大量加载导致界面加载需要等待比较长的时间 2.大量加载Item那么Item中的图片资源会消耗太多内存 现在将我的解决方案分享出来(只给出的大致的描述,如果要实现细节代码的可以联系我). 解决方案一: 方案描述: 起初的时候我采用的的方案是分帧去

Android进阶:ListView性能优化异步加载图片 使滑动效果流畅

ListView 是一种可以显示一系列项目并能进行滚动显示的 View,每一行的Item可能包含复杂的结构,可能会从网络上获取icon等的一些图标信息,就现在的网络速度要想保持ListView运行的很好滚动流畅是做不到的 所以这里就需要把这些信息利用多线程实现异步加载 实现这样功能的类 [java] view plaincopy public class AsyncImageLoader { private HashMap<String, SoftReference<Drawable>&

★android开发--ListView+Json+异步网络图片加载+滚动翻页的例子(图片能缓存,图片不错乱)

例子中用于解析Json的Gson请自己Google下载 主Activity: package COM.Example.Main; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import COM.Example.Main.R; import COM.Example.Main.stringG

Android中listView的下拉加载功能实现

今天给大家讲讲android开发中比较常见的listView的下拉加载,其实也可以叫做分页加载.为什么会有这个叫法呢?说说我的理解吧! 从字面上很好理解.当你滑动一个列表到底部的时候,这个时候就会出现正在加载的底部加载布局去加载更多的数据.这里拿微信作为一个例子,如下图所示: 如上图所示红色方框的部分就是底部的加载布局.从一定程度上这样做是必要的,为了优化用户的体验.你可以想想,假如你点开微信的朋友圈的时候,如果没有做分页加载,那么你需要等待很久的时间才能够看到你和朋友发的一些状态.这是因为这个

ListView与GridView异步加载图片

原理很简单,主要是用到了回调方法,下面是异步加载图片的类 <span style="font-size:16px;">package com.xxx.xxx; import java.io.InputStream; import java.lang.ref.SoftReference; import java.net.URL; import java.util.HashMap; import android.graphics.drawable.Drawable; impor

ListView、PullToRefreshListView滑动加载可见item

最近用的了PullToRefreshListView框架,也在listView中加载图片,对于滑动加载可见item,网上找了一些相关文档,但都不太合适,如:http://blog.csdn.net/zhouzme/article/details/19298337?utm_source=tuicool&utm_medium=referral   不过,大体思路总算清晰了,也就是对于listView做滑动事件监听,关键获取到当前可见item的index序号,从first->last,如有不对的,

listview中getview异步加载网络图片

前言:本以为异步加载挺简单,因为网上代码多,但真想要做好,还真不那么简单,从看代码到弄懂再到自己写,实在是有太多的东西需要学了,用了两天的时间,终于弄出来了,因为用到回调函数,所以理解起来可能难度有点大,讲起来也不太好讲,我尽力讲的明白些,其实还是要多看代码,自己摸索摸索,动手写写就什么都理解了.这篇我们只讲怎样实现异步加载,对于滑动时停止加载的事下篇再讲. 实现效果: 1.异步加载图片,在加载图片时,先加载一个默认的图片,然后在后台加载图片,加载完成后显示出来: 2.当用户在滑动时,停止加载图

Android中自定义ListView实现上拉加载更多和下拉刷新

ListView是Android中一个功能强大而且很常用的控件,在很多App中都有ListView的下拉刷新数据和上拉加载更多这个功能.这里我就简单记录一下实现过程. 实现这个功能的方法不止一个,GitHub上有一些开源库可以使用,但是本着学习的精神,我做的是使用自定义ListView实现这个功能. 思路:谷歌提供的ListView是不能提供下拉刷新和下拉加载的,所以我们就需要重写ListView.在ListView的头部和尾部加上我们的布局文件(progressbar). 先说上拉加载更多实现

Android: ListView数据的分批加载 以及 Handle 总结

这是效果图: activity_main.xml 01 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 02     xmlns:tools="http://schemas.android.com/tools" 03     android:layout_width="match_parent" 04     android:layout_he