简介
本文主要讲述一下Android UI 中ListView的使用方法,ListView无论是在APP中还是在Android系统中,都有着广泛的应用!基本上所有的应用程序中都能够看到,一般情况下,鉴于手机屏幕的空间有限,一次显示的信息并不是很多,但是当程序需要显示比较多的类似信息的时候就需要用到这个ListView!
Android中API中也对其进行了一些介绍,可以参考http://www.android-doc.com/reference/android/widget/ListView.html, 这个ListView是一个垂直滚动显示不同表项的视窗,这个表项主要是通过ListAdapter(适配器)来关联到View中。
要让一个ListView完全显示出来需要具备3个要素:
1. 要存在一个ListView,一般情况下都是通过在XML文件中配
2.要有显示在ListView的数据,字符串,图片资源等
3.要有一个适配器将数据与view关联起来,当然有些情况下系统的布局无法满足是,需要自己创建一个布局,这个布局是每个item显示的布局!
Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带,在我们使用过程中可以根据自己的需求实现接口或者继承类进行一定的扩展。比较常用的有 Base Adapter,Impleader,Adapter,Counteradaptation等。
- BaseAdapter是一个抽象类,继承它需要实现较多的方法,所以也就具有较高的灵活性;
- ArrayAdapter支持泛型操作,最为简单,只能展示一行字。
- SimpleAdapter有最好的扩充性,可以自定义出各种效果。
- SimpleCursorAdapter可以适用于简单的纯文字型ListView,它需要Cursor的字段和UI的id对应起来。如需要实现更复杂的UI也可以重写其他方法。可以认为是SimpleAdapter对数据库的简单结合,可以方便地把数据库的内容以列表的形式展示出来。
简单ListView
目标:在Item上显示文字 使用的Adapter: ArrayAdapter<T> 这个比较简单,只能够展示一行字!先看下效果
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</LinearLayout>
Java Code
<pre name="code" class="java"><pre style="background-color: rgb(255, 255, 255); font-family: 宋体; font-size: 9pt;"><pre name="code" class="java">public class SampleListViewActivity extends AppCompatActivity {
private String[] name = {"宋江", "吴用", "卢俊义", "公孙胜", "武松", "李逵", "林冲", "鲁智深"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sample_list_view);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(SampleListViewActivity.this,android.R.layout.simple_list_item_1,name);
ListView list = (ListView) findViewById(R.id.list_view);
list.setAdapter(adapter);
}
}
在上面code中,ArrayAdapter的泛型指定为String,绑定数据布局文件是android系统自定义的android.R.layout.simple_list_item_1在这个布局里只有一个TextView,可以看到其属性及配置,实际上就是把String中的文字按照这种布局放到对应的TextView中去..直至到显示完成。
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:minHeight="?android:attr/listPreferredItemHeightSmall" />
带标题的ListView
simpleAdapter的扩展性最好,可以定义各种各样的布局出来,在使用过程中经常会用到带标题的ListView,其实简单来说就是2个TextView,一个作为标题,一个作为Text
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
<ListView
android:id="@+id/title_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</LinearLayout>
JAVA 代码
public class TitleListViewActivity extends AppCompatActivity {
private String[] title = {"宋江", "吴用", "卢俊义", "公孙胜", "武松", "李逵", "林冲", "鲁智深"};
private String[] name = {"及时雨", "智多星", "玉麒麟", "入云龙", "行者", "黑旋风", "豹子头", "花和尚"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_title_list_view);
ListView list = (ListView) findViewById(R.id.title_list_view);
ArrayList<Map<String, Object>> array = new ArrayList<Map<String, Object>>();
int length = title.length;
for (int i = 0; i < length; i++) {
Map<String, Object> map = new HashMap<>();
map.put("title", title[i]);
map.put("text", name[i]);
array.add(map);
}
SimpleAdapter adapter = new SimpleAdapter(this, array, android.R.layout.simple_list_item_2, new String[]{"title", "text"},
new int[]{android.R.id.text1, android.R.id.text2});
list.setAdapter(adapter);
}
}
在这里会使用到HashMap,实际上就是一个键值对,通过Key来寻找对应的资源,比如说这里titile和text都是对应的Key,在这个ArrayList中有好多这样的键值对,通过SimpleAdapter把ArrayList所有的数据,都按照布局simple_list_item_2的形式进行放置,title放到text1中,text放到text2中。
带图片的List
上面带标题的ListView给我们展示了一个梁山好汉名字和绰号的列表,那么如果我想直接显示他们的头像,这样岂不是更好!当然也更复杂了。
这里继续使用SimpleAdapter来实现这个功能,提前准备好图片的资源啦,因为显示头像和名字绰号,这样的布局Android的系统没有内置的布局,只能自己动手丰衣足食了,
先定义个布局文件: 左边显示头像,右边分为上下两个TextView
<?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/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/beam_hero_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="50sp" />
<TextView
android:id="@+id/beam_hero_name_nickname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:gravity="end" />
</LinearLayout>
</LinearLayout>
Java Code:
public class ImageListActivity extends AppCompatActivity {
private String[] title = {"宋江", "吴用", "卢俊义", "公孙胜", "李逵", "林冲", "鲁智深"};
private String[] name = {"及时雨", "智多星", "玉麒麟", "入云龙", "黑旋风", "豹子头", "花和尚"};
private int[] image = {R.drawable.songjiang,R.drawable.wuyong,R.drawable.lujunyi,R.drawable.gongsunsheng,
R.drawable.likui,R.drawable.linchong, R.drawable.luzhishen};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_list);
ListView list = (ListView) findViewById(R.id.image_list_view);
ArrayList<Map<String, Object>> array = new ArrayList<Map<String, Object>>();
int len = title.length;
for(int i = 0; i <len; i++){
Map<String, Object> map = new HashMap<String, Object>();
map.put("image",image[i]);
map.put("title", title[i]);
map.put("text", name[i]);
array.add(map);
}
SimpleAdapter adapter = new SimpleAdapter(this, array, R.layout.beam_hero_layout, new String[]{"image","title", "text"},
new int[]{R.id.image_view, R.id.beam_hero_name,R.id.beam_hero_name_nickname});
list.setAdapter(adapter);
}
}
看图说话,其实SimpleAdapter确实非常强大了,你可以通过定制各种布局来显示了相关的数据了!
如何响应ListVeiw事件,ListView显示是一个方面,可能我们更关注的是点击这个控件的时候如何进行响应
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(ImageListActivity.this,"您选择了英雄:" + title[position] + " 绰号:"+name[position], Toast.LENGTH_LONG).show();
}
});
当点击的时候,Toast就会显示了,这个地方使用setOnItemClickListener注册了一个监听器,当用户点击了任何一个ListView中的子项就会调用onItemClick方法,在这个方法中可以通过position可以知道用户点击的是哪一个子项!
带按钮的listView
在现有的ListView中,只看到了头像,姓名以及绰号等信息,但是如果我想知道比较更详细的信息该怎么办呢?我可以在每个Item里再加一个按钮,点一下按钮可以显示当前英雄的详细信息!这种情况下需要自定义adapter
再次之前简单说下ListView显示的过程:系统要知道我显示ListView要显示多少行, 也就是传入数据的个数,其实这样就得到了ListView的显示行数,系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个ViewGroup),然后再实例
并设置各个组件,并进行显示。绘制完这一行了,那 再绘制下一行,直到绘完为止。
如果我们要自定义适配器,那就要重写getView方法,getView()有三个参数,position表示将显示的是第几 行,covertView是从布局文件中inflate来的布局。我们写一个类来描述布局文件中的各个组件,比如ImageView,TextView 等,然后判断convertView是否为空,如果为空就从inflate中拿到布局,然后把布局中的各个组件都设上对 应的值,这里的Position对应相关数据的位置
Layout文件
<?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/beam_image_view_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/beam_hero_name_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="50sp"
/>
<TextView
android:id="@+id/beam_hero_name_nickname_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
/>
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/beam_hero_button_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="简介"
android:layout_alignParentEnd="true"
/>
</RelativeLayout>
</LinearLayout>
Java Code:
public class ButtonImageActivity extends AppCompatActivity {
private String[] title = {"宋江", "吴用", "卢俊义", "公孙胜", "李逵", "林冲", "鲁智深"};
private String[] name = {"及时雨", "智多星", "玉麒麟", "入云龙", "黑旋风", "豹子头", "花和尚"};
private int[] image = {R.drawable.songjiang, R.drawable.wuyong, R.drawable.lujunyi, R.drawable.gongsunsheng,
R.drawable.likui, R.drawable.linchong, R.drawable.luzhishen};
public int mlen;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button_image);
ListView list =(ListView)findViewById(R.id.image_list_view_2);
mlen = title.length;
list.setAdapter(new BeamHeroAdapter(this));
}
private class BeamHeroAdapter extends BaseAdapter implements View.OnClickListener {
private Context mContext;
private LayoutInflater inflater;
public BeamHeroAdapter(Context mContext) {
this.mContext = mContext;
inflater = LayoutInflater.from(mContext);
}
public int getCount() {
return mlen;
}
public long getItemId(int position) {
return position;
}
public Object getItem(int position) {
return null;
}
public View getView(int position, View convertView, ViewGroup parent) {
View v;
if (convertView == null) {
v = inflater.inflate(R.layout.beam_hero_button_layout, null);
} else {
v = convertView;
}
ImageView img = (ImageView) v.findViewById(R.id.beam_image_view_1);
TextView text1 = (TextView) v.findViewById(R.id.beam_hero_name_1);
TextView text2 = (TextView) v.findViewById(R.id.beam_hero_name_nickname_1);
Button button = (Button) v.findViewById(R.id.beam_hero_button_1);
img.setImageResource(image[position]);
text1.setText(title[position]);
text2.setText(name[position]);
button.setOnClickListener(this);
return v;
}
public void onClick(View v){
}
}
}
OK,这里按钮的响应函数没有写出来,可以自行实现了...看下运行效果
总结
本文主要介绍了ListView的用法,应该说用法可能千变万化,不过只要掌握了最后一种自己实现Adapter的方法,详细再复杂的显示方式也都能够实现,不过在我们手机的应用之中,比这种更复杂的情况还真少见...!重点是要学会原理,这样才能举一反三。
更多参考
[1]
[2]http://www.xuanyusong.com/archives/91
[3]