ListView是最經(jīng)典的控件之一,雖然現(xiàn)在其江山地位不穩(wěn),將要被recyclerview取代,但設(shè)計(jì)理念是很經(jīng)典的,而且很多程序員還是習(xí)慣了ListView,因此這里還需對(duì)ListView好好學(xué)習(xí),ListView內(nèi)容非常多,你要有足夠的耐心進(jìn)行學(xué)習(xí),每一個(gè)功能點(diǎn)都有可能應(yīng)用到項(xiàng)目中。 ListView經(jīng)常被用在列表顯示上,每一個(gè)列表項(xiàng)都具有相同的布局,一個(gè)ListView通常都有三個(gè)要素組成:
ListView的常用屬性有:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/12-1.png" alt="這里寫圖片描述" />
ListView常用方法有:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/12-2.png" alt="這里寫圖片描述" />
下面分別講解一下相關(guān)方法和屬性的使用及三種適配器的使用,首先看一下如何使用ArrayAdapter是如何進(jìn)行數(shù)據(jù)包裝的。
布局文件:
<?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">
<ListView
android:id="@+id/lv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="@android:color/holo_red_dark"
android:dividerHeight="3dp"
android:scrollbars="none"/>
</RelativeLayout>
設(shè)置了divider屬性,子項(xiàng)之間的分隔欄,并設(shè)置了dividerHeight屬性決定了分隔欄的高度,將scrollbars屬性的值設(shè)成了none表示沒(méi)有滑動(dòng)條。
MainActivity.java代碼如下:
public class MainActivity extends Activity {
private ListView listView;
private String datas[]={ "Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday" };//準(zhǔn)備數(shù)據(jù)源
ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//隱藏標(biāo)題欄
setContentView(R.layout.activity_main);
listView=(ListView)findViewById(R.id.lv);
//實(shí)例化ArrayAdapter
adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,datas);
listView.setAdapter(adapter);//設(shè)置適配器
}
}
這里實(shí)例化ArrayAdapter對(duì)象傳入了三個(gè)參數(shù),第一個(gè)參數(shù)是上下文對(duì)象,第二個(gè)參數(shù)是子項(xiàng)布局,這里調(diào)用了系統(tǒng)內(nèi)容的布局,第三個(gè)參數(shù)是數(shù)據(jù)集,這里傳入的是字符串?dāng)?shù)組。最后調(diào)用setAdapter方法設(shè)置適配器。 運(yùn)行實(shí)例如下:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/12-3.png" alt="這里寫圖片描述" />
ArrayAdapter適用于顯示信息比較單一的場(chǎng)景,若顯示項(xiàng)中包含多種形式的數(shù)據(jù),就不太適用了,下面我們介紹一下可以適配多種數(shù)據(jù)類型的適配器類SimpleAdapter的使用方法。當(dāng)存在多種數(shù)據(jù)類型時(shí)首先要考慮布局問(wèn)題,因此首先要設(shè)置子項(xiàng)目布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="match_parent">
<ImageView
android:id="@+id/img"
android:src="@mipmap/ic_launcher"
android:layout_width="50dp"
android:layout_height="50dp" />
<TextView
android:id="@+id/tv"
android:text="hello"
android:gravity="center"
android:layout_marginLeft="50dp"
android:textSize="28sp"
android:layout_width="wrap_content"
android:layout_height="50dp" />
</LinearLayout>
包括兩種控件,ImgeView和TextView,ImageView負(fù)責(zé)圖片的顯示,TextView對(duì)圖片信息進(jìn)行說(shuō)明,采用線性布局的水平布局模式。 主布局文件如下:
<?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">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
主布局文件中僅配置了一個(gè)ListView控件,設(shè)置其寬高都是占據(jù)整個(gè)布局(match_parent)。 MainActivity.java:
public class MainActivity extends Activity {
private ListView listView;
private SimpleAdapter simpleAdapter;
private List<Map<String, Object>> datas=new ArrayList<Map<String, Object>>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView=(ListView)findViewById(R.id.listview);
initDatas();//初始化數(shù)據(jù)集
//實(shí)例化SimpleAdapter
simpleAdapter=new SimpleAdapter(this,datas,R.layout.animal_layout,new String[]{"img","name"},new int[]{R.id.img,R.id.tv}); listView.setAdapter(simpleAdapter);//設(shè)置配置器
}
private void initDatas() {
Map map1=new HashMap();
map1.put("img",R.drawable.fish);
map1.put("name","小金魚");
Map map2=new HashMap();
map2.put("img",R.drawable.horse);
map2.put("name","千里馬");
Map map3=new HashMap();
map3.put("img",R.drawable.mouse);
map3.put("name","米老鼠");
datas.add(map1);
datas.add(map2);
datas.add(map3);
}
}
SimpleAdapter的構(gòu)造函數(shù)如下: SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) 實(shí)例化SimpleAdapter時(shí)要傳入幾個(gè)參數(shù):
從上面的例子可以看出,ArrayAdapter一般適用于數(shù)據(jù)源數(shù)據(jù)種類比較單一的情形,若數(shù)據(jù)類型比較復(fù)雜,需要個(gè)性化定制布局,則可以采用BaseAdapter適配器進(jìn)行數(shù)據(jù)適配。若要問(wèn)BaseAdapter和SimpleAdapter有什么不同,通過(guò)API文檔可以獲悉,SimpleAdapter是BaseAdapter的子類,BaseAdapter較SimpleAdapter來(lái)講更為靈活,在開(kāi)發(fā)中也更為常用。 下面通過(guò)一個(gè)實(shí)例,來(lái)說(shuō)明在開(kāi)發(fā)中是如何使用BaseAdapter適配數(shù)據(jù)源的。
首先對(duì)復(fù)雜的數(shù)據(jù)源進(jìn)行數(shù)據(jù)封裝:
public class Animal {
public Animal(String animal, int imgId) {
this.animal = animal;
this.imgId = imgId;
}
private String animal;
private int imgId;
public String getAnimal() {
return animal;
}
public void setAnimal(String animal) {
this.animal = animal;
}
public int getImgId() {
return imgId;
}
public void setImgId(int imgId) {
this.imgId = imgId;
}
}
然后定義單個(gè)子項(xiàng)的布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="match_parent">
<ImageView
android:id="@+id/img"
android:src="@mipmap/ic_launcher"
android:layout_width="50dp"
android:layout_height="50dp" />
<TextView
android:id="@+id/tv"
android:text="hello"
android:gravity="center"
android:layout_marginLeft="50dp"
android:textSize="28sp"
android:layout_width="wrap_content"
android:layout_height="50dp" />
</LinearLayout>
主布局文件和ArrayAdapter的主布局文件一樣,就不再貼出代碼,下面看一下自定義的適配器類,繼承自BaseAdapter,如下:
public class AnimalAdapter extends BaseAdapter {
private Context context;
private List<Animal> datas;
//構(gòu)造函數(shù)需要傳入兩個(gè)必要的參數(shù):上下文對(duì)象和數(shù)據(jù)源
public AnimalAdapter(Context context,List<Animal> datas) {
this.context=context;
this.datas=datas;
}
//返回子項(xiàng)的個(gè)數(shù)
@Override
public int getCount() {
return datas.size();
}
//返回子項(xiàng)對(duì)應(yīng)的對(duì)象
@Override
public Object getItem(int position) {
return datas.get(position);
}
//返回子項(xiàng)的下標(biāo)
@Override
public long getItemId(int position) {
return position;
}
//返回子項(xiàng)視圖
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Animal animal= (Animal) getItem(position);
View view;
ViewHolder viewHolder;
if(convertView==null){
view = LayoutInflater.from(context).inflate(R.layout.animal_layout,null);
viewHolder=new ViewHolder();
viewHolder.animalImage=(ImageView)view.findViewById(R.id.img);
viewHolder.animalName=(TextView)view.findViewById(R.id.tv);
view.setTag(viewHolder);
}else{
view=convertView;
viewHolder= (ViewHolder) view.getTag();
}
viewHolder.animalName.setText(animal.getAnimal());
viewHolder.animalImage.setImageResource(animal.getImgId());
return view;
}
//創(chuàng)建ViewHolder類
class ViewHolder{
ImageView animalImage;
TextView animalName;
}
}
繼承自BaseAdapter類,必須需要覆寫四個(gè)方法,每個(gè)方法的具體含義已經(jīng)在代碼中做了注釋。此外,為了提高加載效率,這里創(chuàng)建了內(nèi)部類ViewHolder,可以避免每次調(diào)用getView方法時(shí)都要通過(guò)findViewById方法去實(shí)例化控件,大大提高運(yùn)行效率,推薦以后開(kāi)發(fā)中這么使用。 MainActivity.java代碼如下:
public class MainActivity extends Activity {
private ListView listView;
private List<Animal> datas = new ArrayList<Animal>();
private AnimalAdapter animalAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//隱藏標(biāo)題欄
setContentView(R.layout.activity_main);
initDatas();
listView = (ListView) findViewById(R.id.lv);
animalAdapter = new AnimalAdapter(this, datas);
listView.setAdapter(animalAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this, "您單擊了" + datas.get(position).getAnimal(), Toast.LENGTH_SHORT).show();
}
});
}
private void initDatas() {
Animal animal0 = new Animal("兔八哥", R.drawable.rabbit);
Animal animal1 = new Animal("眼鏡蛇", R.drawable.snack);
Animal animal2 = new Animal("小金魚", R.drawable.fish);
Animal animal3 = new Animal("千里馬", R.drawable.horse);
Animal animal4 = new Animal("米老鼠", R.drawable.mouse);
Animal animal5 = new Animal("大國(guó)寶", R.drawable.panda);
datas.add(animal0);
datas.add(animal1);
datas.add(animal2);
datas.add(animal3);
datas.add(animal4);
datas.add(animal5);
}
}
這里調(diào)用了setOnItemClickListener方法實(shí)現(xiàn)了單項(xiàng)監(jiān)聽(tīng),覆寫了onItemClick方法,由參數(shù)positon通過(guò)List的getPosition方法獲取對(duì)象,再通過(guò)對(duì)象封裝的getAnimal方法可以獲得對(duì)應(yīng)的動(dòng)物名,由Toast通知輸出。
運(yùn)行項(xiàng)目實(shí)例如下:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/12-4.png" alt="這里寫圖片描述" />