Android控件:ListView与Adapter

    ListView几乎随处可见,就是展示一个可滚动的垂直列表,它的数据来源于ListAdapter。Adapter起到嫁接数据与视图的桥梁作用,所以实现简单的ListView并不复杂。


实例一:使用ArrayAdapter实现最简单的ListView

public class MainActivity extends ActionBarActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ListView listView = (ListView) findViewById(R.id.listview);

		final String[] data = { "Jan.", "Feb.", "Mar.", "Apr.", "May", "June",
				"July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec." };
		// 构建一个ArrayAdapter,第二个参数是布局这里使用系统自带的,
		// 最后一个参数其实常常使用的是ArrayList而非数组,固定长度时使用数组
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1, data);
		// 设置适配器,简单两步即可实现显示最简单的ListView
		listView.setAdapter(adapter);

		// 可以为ListView注册一个监听器
		listView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
				// TODO Auto-generated method stub
				Toast.makeText(MainActivity.this, data[arg2], Toast.LENGTH_LONG)
						.show();
			}
		});
	}
}



实例二:使用SimpleAdapter实现自定义布局的ListView

①首先要自定义一个布局文件

<?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="50dp" >

    <ImageView
        android:id="@+id/imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dp" />

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="60dp"
        android:layout_centerVertical="true"
        android:textColor="#1874CD"
        android:textSize="18sp" />

</RelativeLayout>
②Activity

public class MainActivity extends ActionBarActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ListView listView = (ListView) findViewById(R.id.listview);
		// 图片数据
		int[] image = { R.drawable.a7, R.drawable.a1, R.drawable.a2,
				R.drawable.a3, R.drawable.a4, R.drawable.a5, R.drawable.a6 };
		// 文字数据
		String[] data = { "Sunday", "Monday", "Tuesday", "Wednesday",
				"Thursday", "Friday", "Saturday" };
		// List里面套Map
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

		for (int i = 0; i < data.length; i++) {
			// 每个Map套的就是一行数据
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("image", image[i]);
			map.put("data", data[i]);
			// 将这行数据添加到List
			list.add(map);
		}
		
		SimpleAdapter adapter = new SimpleAdapter(this, list,
				R.layout.listview, new String[] { "image", "data" }, new int[] {
						R.id.imageview, R.id.textview });

		listView.setAdapter(adapter);
	}
}

看一下SimpleAdapter的构造器:

public SimpleAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
最后两个参数代表的是:

String[] from:添加到Map里面的列名

int[] to:展示列的视图

上面的例子,new String[] { "image", "data" }, new int[] {R.id.imageview, R.id.textview两个参数则代表,展示的两列列名分别为"image"和"data",对应的视图是布局文件中的imageview和textview。注意与添加数据即构建每一个HashMap时,列名要对应,即

map.put("image", image[i]);map.put("data", data[i]);两者的Key对应的就是from[]里面的列名。



实例三:使用BaseAdapter实现自定义布局的ListView

上面的两个示例都是用一些现成已实现的Apdater,其实最基本的还是BaseAdapter。

public class MainActivity extends ActionBarActivity {

	private ListView listView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		listView = (ListView) findViewById(R.id.listview);
		List<String> list = new ArrayList<String>();
		for (int i = 0; i < 20; i++) {
			list.add("data" + i);
		}
		listView.setAdapter(new MyAdapter(list));
	}

	private class MyAdapter extends BaseAdapter {

		private List<String> list;

		public MyAdapter(List<String> list) {
			this.list = list;
		}

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

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

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

		@Override
		public int getItemViewType(int position) {
			// TODO Auto-generated method stub
			if (position == 5 || position == 10) {
				return 88;
			}
			return super.getItemViewType(position);
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			// TODO Auto-generated method stub
			View view = null;
			ViewHolder holder;
			if (getItemViewType(position) != 88) {
				if (convertView == null) {
					view = LayoutInflater.from(parent.getContext()).inflate(
							R.layout.item, parent, false);
					holder = new ViewHolder(view);
					view.setTag(holder);
				} else {
					view = convertView;
					holder = (ViewHolder) view.getTag();
				}
				holder.textView.setText(list.get(position));
			} else {
				if (convertView == null) {
					view = LayoutInflater.from(parent.getContext()).inflate(
							R.layout.divider, parent, false);
				} else {
					view = convertView;
				}
			}
			return view;
		}

		public class ViewHolder {
			public TextView textView;

			public ViewHolder(View itemView) {
				textView = (TextView) itemView.findViewById(R.id.textview);
			}
		}
	}
}


这里加载的view有两种,一种是textview,一种是一个黑色的条,通过控制view type来实现加载选择:

public abstract int getItemViewType (int position)


ConvertView主题:
实际上一个ListView中使用的控件只有一屏最多能容下的数量,以复用view来达到内存控制,例如:假如一屏最多能容下10个item,则第11个item滑入屏幕时,第1个item滑出屏幕,此时第11个item复用第0个item的控件,以此类推。事实上第11个item滑入屏幕后,显示的内容完全就是复用的第一个item的内容,不过由于getView是同步处理数据处理得很快,所以我们看到的是同步的数据;如果此时ListView是异步加载数据,则第11个item显示的就是第1个item的内容,直至第11个item异步加载完毕。所以,异步加载时需要注意这项内容。


发布了87 篇原创文章 · 获赞 10 · 访问量 12万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览