為什么使用ListView: 由于手機屏幕空間都比較有限,能夠一次性在屏幕上顯示的內容并不多,程序中有大量的數據需要展示的時候,就可以借助ListView來實現。
ListView的特性: 通過手指上下滑動的方式將屏幕外的數據滾動到屏幕內,同時屏幕上原有的數據則會滾動出屏幕
1. 簡單用法
- 布局文件中增加 ListView
- 源碼中準備數據
- 源碼中構造適配器 Adapter
- 通過 id 找到 ListView 的實例
- ListView 設置適配器
tip:使用android框架提供的子項布局
首先新建項目 LearnListView,修改布局文件activity_main,線性布局嵌套一個 ListView:
<LinearLayout ...>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/list_view">
</ListView>
</LinearLayout>
準備數據,在MainActivity類內部聲明變量data,并初始化:
private String[] data = {"Apple",
"Banana","Orange","Watermelon",
"Pear","Grape","Pineapple",
"Strawberry","Cherry","Mango"};
在MianActivity類的onCreate函數內部構造適配器,其三個參數分別是上下文Context,ListView子項目布局的ID,這里使用Android提供的布局,最后一個參數就是前面準備的數據:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
MainActivity.this, // Context上下文
android.R.layout.simple_list_item_1, // 子項布局id
data); // 數據
接著在MainActivity類的onCreate函數內部找到 ListView 這個實例并為這個實例設置適配器:
listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
運行效果如下:
2. 定制 ListView 的界面
準備一組水果圖片,拖入res/drawable目錄
多出的事情:
1.布局文件中增加 ListView
2.源碼中準備數據 ,準備圖片資源
3.源碼中構造適配器 Adapter ,準備子項布局
4.通過id找到ListView的實例 ,準備數據結構
5.ListView設置適配器,派生ArrayAdapter
新建一個布局文件fruit_item.xml,作為ListView子項目的布局,一個ImageView用于顯示水果的圖片,一個TexitView用于現實水果的名稱:
<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>
定義一個實體類,作為ListView適配器的適配類型。新建類Fruit:
public class Fruit {
// 水果的名稱
private String name;
// 水果對應圖片的資源id,在drawble里邊
private int imageId;
// 構造函數
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;
}
}
自定義一個適配器,新建類FruitAdapter,從ArrayAdapter派生,并將泛型指定為Fruit類。
在其中重寫父類的構造函數,用于將上下文、ListView子項布局的id和數據都傳遞進來。
在其中重寫getView函數,
首先通過getItem()方法得到當前項的Fruit實例,
然后使用LayoutInflater來為這個子項加載我們傳入的布局,
接著調用View的findViewById()方法分別獲取到ImageView和TextView的實例,并分別調用它們的setImageResource()和setText()方法來設置顯示的圖片和文字,最后布局返回。
public class FruitAdapter extends ArrayAdapter<Fruit> {
// 子項布局的id
private int resourceId;
// 構造函數
public FruitAdapter(Context context, // context上下文
int textViewResourceId, // 子項布局的id
List<Fruit> objects){ // 數據鏈表
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
// 重寫getView
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 獲取當前項的Fruit實例
Fruit fruit = getItem(position);
View view;
ViewHolder viewHolder;
if (convertView == null){
// inflate出子項布局,實例化其中的圖片控件和文本控件
view = LayoutInflater.from(getContext()).inflate(resourceId, null);
viewHolder = new ViewHolder();
// 通過id得到圖片控件實例
viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
// 通過id得到文本空間實例
viewHolder.fruitName = (TextView) view.findViewById(R.id.fruit_name);
// 緩存圖片控件和文本控件的實例
view.setTag(viewHolder);
}else{
view = convertView;
// 取出緩存
viewHolder = (ViewHolder) view.getTag();
}
// 直接使用緩存中的圖片控件和文本控件的實例
// 圖片控件設置圖片資源
viewHolder.fruitImage.setImageResource(fruit.getImageId());
// 文本控件設置文本內容
viewHolder.fruitName.setText(fruit.getName());
return view;
}
// 內部類
class ViewHolder{
ImageView fruitImage;
TextView fruitName;
}
}
修改MainActivity代碼
聲明一個成員變量:
private List<Fruit> fruitList = new ArrayList<Fruit>();
添加一個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函數調用初始化函數,修改適配器的初始化:
initFruits();
FruitAdapter adapter = new FruitAdapter(MainActivity.this,
R.layout.fruit_item, fruitList);
listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
運行效果如下:
ListView的點擊事件,在其中Toast出水果的名字,和設置Button的點擊監聽類似:
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();
}
});
運行效果如下: