ListView是最經典的控件之一,雖然現(xiàn)在其江山地位不穩(wěn),將要被recyclerview取代,但設計理念是很經典的,而且很多程序員還是習慣了ListView,因此這里還需對ListView好好學習,ListView內容非常多,你要有足夠的耐心進行學習,每一個功能點都有可能應用到項目中。 ListView經常被用在列表顯示上,每一個列表項都具有相同的布局,一個ListView通常都有三個要素組成:
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="這里寫圖片描述" />
下面分別講解一下相關方法和屬性的使用及三種適配器的使用,首先看一下如何使用ArrayAdapter是如何進行數據包裝的。
布局文件:
<?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>
設置了divider屬性,子項之間的分隔欄,并設置了dividerHeight屬性決定了分隔欄的高度,將scrollbars屬性的值設成了none表示沒有滑動條。
MainActivity.java代碼如下:
public class MainActivity extends Activity {
private ListView listView;
private String datas[]={ "Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday" };//準備數據源
ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//隱藏標題欄
setContentView(R.layout.activity_main);
listView=(ListView)findViewById(R.id.lv);
//實例化ArrayAdapter
adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,datas);
listView.setAdapter(adapter);//設置適配器
}
}
這里實例化ArrayAdapter對象傳入了三個參數,第一個參數是上下文對象,第二個參數是子項布局,這里調用了系統(tǒng)內容的布局,第三個參數是數據集,這里傳入的是字符串數組。最后調用setAdapter方法設置適配器。 運行實例如下:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/12-3.png" alt="這里寫圖片描述" />
ArrayAdapter適用于顯示信息比較單一的場景,若顯示項中包含多種形式的數據,就不太適用了,下面我們介紹一下可以適配多種數據類型的適配器類SimpleAdapter的使用方法。當存在多種數據類型時首先要考慮布局問題,因此首先要設置子項目布局文件:
<?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負責圖片的顯示,TextView對圖片信息進行說明,采用線性布局的水平布局模式。 主布局文件如下:
<?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>
主布局文件中僅配置了一個ListView控件,設置其寬高都是占據整個布局(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();//初始化數據集
//實例化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);//設置配置器
}
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的構造函數如下: SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) 實例化SimpleAdapter時要傳入幾個參數:
從上面的例子可以看出,ArrayAdapter一般適用于數據源數據種類比較單一的情形,若數據類型比較復雜,需要個性化定制布局,則可以采用BaseAdapter適配器進行數據適配。若要問BaseAdapter和SimpleAdapter有什么不同,通過API文檔可以獲悉,SimpleAdapter是BaseAdapter的子類,BaseAdapter較SimpleAdapter來講更為靈活,在開發(fā)中也更為常用。 下面通過一個實例,來說明在開發(fā)中是如何使用BaseAdapter適配數據源的。
首先對復雜的數據源進行數據封裝:
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;
}
}
然后定義單個子項的布局:
<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;
//構造函數需要傳入兩個必要的參數:上下文對象和數據源
public AnimalAdapter(Context context,List<Animal> datas) {
this.context=context;
this.datas=datas;
}
//返回子項的個數
@Override
public int getCount() {
return datas.size();
}
//返回子項對應的對象
@Override
public Object getItem(int position) {
return datas.get(position);
}
//返回子項的下標
@Override
public long getItemId(int position) {
return position;
}
//返回子項視圖
@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類,必須需要覆寫四個方法,每個方法的具體含義已經在代碼中做了注釋。此外,為了提高加載效率,這里創(chuàng)建了內部類ViewHolder,可以避免每次調用getView方法時都要通過findViewById方法去實例化控件,大大提高運行效率,推薦以后開發(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);//隱藏標題欄
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("大國寶", R.drawable.panda);
datas.add(animal0);
datas.add(animal1);
datas.add(animal2);
datas.add(animal3);
datas.add(animal4);
datas.add(animal5);
}
}
這里調用了setOnItemClickListener方法實現(xiàn)了單項監(jiān)聽,覆寫了onItemClick方法,由參數positon通過List的getPosition方法獲取對象,再通過對象封裝的getAnimal方法可以獲得對應的動物名,由Toast通知輸出。
運行項目實例如下:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/12-4.png" alt="這里寫圖片描述" />