為什么使用ListView: 由于手機(jī)屏幕空間都比較有限枉氮,能夠一次性在屏幕上顯示的內(nèi)容并不多,程序中有大量的數(shù)據(jù)需要展示的時(shí)候涎拉,就可以借助ListView來(lái)實(shí)現(xiàn)晾咪。
ListView的特性: 通過(guò)手指上下滑動(dòng)的方式將屏幕外的數(shù)據(jù)滾動(dòng)到屏幕內(nèi),同時(shí)屏幕上原有的數(shù)據(jù)則會(huì)滾動(dòng)出屏幕
1. 簡(jiǎn)單用法
- 布局文件中增加 ListView
- 源碼中準(zhǔn)備數(shù)據(jù)
- 源碼中構(gòu)造適配器 Adapter
- 通過(guò) id 找到 ListView 的實(shí)例
- ListView 設(shè)置適配器
tip:使用android框架提供的子項(xiàng)布局
首先新建項(xiàng)目 LearnListView鞋既,修改布局文件activity_main力九,線性布局嵌套一個(gè) ListView:
<LinearLayout ...>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/list_view">
</ListView>
</LinearLayout>
準(zhǔn)備數(shù)據(jù),在MainActivity類內(nèi)部聲明變量data邑闺,并初始化:
private String[] data = {"Apple",
"Banana","Orange","Watermelon",
"Pear","Grape","Pineapple",
"Strawberry","Cherry","Mango"};
在MianActivity類的onCreate函數(shù)內(nèi)部構(gòu)造適配器跌前,其三個(gè)參數(shù)分別是上下文Context,ListView子項(xiàng)目布局的ID陡舅,這里使用Android提供的布局舒萎,最后一個(gè)參數(shù)就是前面準(zhǔn)備的數(shù)據(jù):
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
MainActivity.this, // Context上下文
android.R.layout.simple_list_item_1, // 子項(xiàng)布局id
data); // 數(shù)據(jù)
接著在MainActivity類的onCreate函數(shù)內(nèi)部找到 ListView 這個(gè)實(shí)例并為這個(gè)實(shí)例設(shè)置適配器:
listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
運(yùn)行效果如下:
2. 定制 ListView 的界面
準(zhǔn)備一組水果圖片,拖入res/drawable目錄
多出的事情:
1.布局文件中增加 ListView
2.源碼中準(zhǔn)備數(shù)據(jù) ,準(zhǔn)備圖片資源
3.源碼中構(gòu)造適配器 Adapter 臂寝,準(zhǔn)備子項(xiàng)布局
4.通過(guò)id找到ListView的實(shí)例 章鲤,準(zhǔn)備數(shù)據(jù)結(jié)構(gòu)
5.ListView設(shè)置適配器,派生ArrayAdapter
新建一個(gè)布局文件fruit_item.xml咆贬,作為L(zhǎng)istView子項(xiàng)目的布局败徊,一個(gè)ImageView用于顯示水果的圖片,一個(gè)TexitView用于現(xiàn)實(shí)水果的名稱:
<LinearLayout ...>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fruit_image"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="10dip"
android:id="@+id/fruit_name"/>
</LinearLayout>
定義一個(gè)實(shí)體類掏缎,作為L(zhǎng)istView適配器的適配類型皱蹦。新建類Fruit:
public class Fruit {
// 水果的名稱
private String name;
// 水果對(duì)應(yīng)圖片的資源id,在drawble里邊
private int imageId;
// 構(gòu)造函數(shù)
public Fruit(String name, int imageId){
this.name = name;
this.imageId = imageId;
}
// get名字
public String getName() {
return name;
}
// get圖片id
public int getImageId() {
return imageId;
}
}
自定義一個(gè)適配器眷蜈,新建類FruitAdapter沪哺,從ArrayAdapter派生,并將泛型指定為Fruit類酌儒。
在其中重寫父類的構(gòu)造函數(shù)辜妓,用于將上下文、ListView子項(xiàng)布局的id和數(shù)據(jù)都傳遞進(jìn)來(lái)忌怎。
在其中重寫getView函數(shù)籍滴,
首先通過(guò)getItem()方法得到當(dāng)前項(xiàng)的Fruit實(shí)例,
然后使用LayoutInflater來(lái)為這個(gè)子項(xiàng)加載我們傳入的布局榴啸,
接著調(diào)用View的findViewById()方法分別獲取到ImageView和TextView的實(shí)例孽惰,并分別調(diào)用它們的setImageResource()和setText()方法來(lái)設(shè)置顯示的圖片和文字,最后布局返回鸥印。
public class FruitAdapter extends ArrayAdapter<Fruit> {
// 子項(xiàng)布局的id
private int resourceId;
// 構(gòu)造函數(shù)
public FruitAdapter(Context context, // context上下文
int textViewResourceId, // 子項(xiàng)布局的id
List<Fruit> objects){ // 數(shù)據(jù)鏈表
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
// 重寫getView
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 獲取當(dāng)前項(xiàng)的Fruit實(shí)例
Fruit fruit = getItem(position);
View view;
ViewHolder viewHolder;
if (convertView == null){
// inflate出子項(xiàng)布局勋功,實(shí)例化其中的圖片控件和文本控件
view = LayoutInflater.from(getContext()).inflate(resourceId, null);
viewHolder = new ViewHolder();
// 通過(guò)id得到圖片控件實(shí)例
viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
// 通過(guò)id得到文本空間實(shí)例
viewHolder.fruitName = (TextView) view.findViewById(R.id.fruit_name);
// 緩存圖片控件和文本控件的實(shí)例
view.setTag(viewHolder);
}else{
view = convertView;
// 取出緩存
viewHolder = (ViewHolder) view.getTag();
}
// 直接使用緩存中的圖片控件和文本控件的實(shí)例
// 圖片控件設(shè)置圖片資源
viewHolder.fruitImage.setImageResource(fruit.getImageId());
// 文本控件設(shè)置文本內(nèi)容
viewHolder.fruitName.setText(fruit.getName());
return view;
}
// 內(nèi)部類
class ViewHolder{
ImageView fruitImage;
TextView fruitName;
}
}
修改MainActivity代碼
聲明一個(gè)成員變量:
private List<Fruit> fruitList = new ArrayList<Fruit>();
添加一個(gè)initFruit()方法:
private void initFruits(){
//蘋果
Fruit apple = new Fruit("Apple", // 名字
R.drawable.apple_pic); // 圖片id
fruitList.add(apple); // 蘋果增加到鏈表
Fruit banana = new Fruit("Banana", R.drawable.banana_pic);
fruitList.add(banana);
Fruit orange = new Fruit("Orange", R.drawable.orange_pic);
fruitList.add(orange);
Fruit watermelon = new Fruit("Watermelon", R.drawable.watermelon_pic);
fruitList.add(watermelon);
Fruit pear = new Fruit("Pear", R.drawable.pear_pic);
fruitList.add(pear);
Fruit grape = new Fruit("Grape", R.drawable.grape_pic);
fruitList.add(grape);
Fruit pineapple = new Fruit("Pineapple", R.drawable.pineapple_pic);
fruitList.add(pineapple);
Fruit strawberry = new Fruit("Strawberry", R.drawable.strawberry_pic);
fruitList.add(strawberry);
Fruit cherry = new Fruit("Cherry", R.drawable.cherry_pic);
fruitList.add(cherry);
Fruit mango = new Fruit("Mango", R.drawable.mango_pic);
fruitList.add(mango);
}
接著在onCreate函數(shù)調(diào)用初始化函數(shù),修改適配器的初始化:
initFruits();
FruitAdapter adapter = new FruitAdapter(MainActivity.this,
R.layout.fruit_item, fruitList);
listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
運(yùn)行效果如下:
ListView的點(diǎn)擊事件库说,在其中Toast出水果的名字酝润,和設(shè)置Button的點(diǎn)擊監(jiān)聽(tīng)類似:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fruit fruit = fruitList.get(position);
Toast.makeText(MainActivity.this, fruit.getName(),Toast.LENGTH_LONG).show();
}
});
運(yùn)行效果如下: