手機(jī)屏幕空間有限携兵,能顯示的內(nèi)容不多蕾哟。可以借助ListView來顯示更多的內(nèi)容共缕。
ListView允許用戶通過上下滑動來將屏幕外的數(shù)據(jù)滾動到屏幕內(nèi)洗出,同時屏幕內(nèi)原有的數(shù)據(jù)滾動出屏幕,從而顯示更多的數(shù)據(jù)內(nèi)容图谷。
ListView的簡單用法
修改activity_main.xml
<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"
android:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listview"></ListView>
</LinearLayout>
android:layout_width
和android:layout_height
設(shè)置為match_parent
可以把ListView占滿整個布局的空間翩活。
修改MainActivity.java
public class MainActivity extends AppCompatActivity {
private String [] data = {"Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","Cherry",
"Mango","Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","Cherry",
"Mango"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//ArraryAdapter適配器,通過泛型來指定要適配的數(shù)據(jù)類型便贵,然后在構(gòu)造函數(shù)中把要適配的數(shù)據(jù)傳入菠镇。
ArrayAdapter<String> arrayAdapter= new ArrayAdapter<String> (
MainActivity.this, android.R.layout.simple_list_item_1,data);
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(arrayAdapter);
}
}
例子中以數(shù)組的方式來傳遞數(shù)據(jù),里面包含很多水果的名字承璃。
數(shù)組中的數(shù)據(jù)無法直接傳遞給ListView,這時需要借助適配器(Adapter)來完成利耍。
Android中提供了很多適配器,這里使用的是ArrayAdapter,它可以通過泛型來指定要適配的數(shù)據(jù)類型,然后在構(gòu)造函數(shù)中把要適配的數(shù)據(jù)傳入盔粹。
因?yàn)閿?shù)據(jù)都是字符串隘梨,所以ArrayAdapter的泛型指定為String。
ArrayAdapter的構(gòu)造函數(shù)傳入3個數(shù)據(jù):
- 1是Context 傳入當(dāng)前的上下文
- 2是ListView子項(xiàng)布局的ID
- 3是要適配的數(shù)據(jù)
android.R.layout.simple_list_item_1
作為ListView子項(xiàng)布局的ID舷嗡,這時安卓內(nèi)置的布局文件轴猎。里面只有一個TextView,可用于顯示一段文本进萄。
最后調(diào)用ListView的setAdapter()方法將構(gòu)建好的適配器對象傳遞進(jìn)去捻脖。
運(yùn)行效果:
定制ListView界面
對ListView界面進(jìn)行定制锐峭,讓其可以顯示更豐富的內(nèi)容。
為每個水果加上圖片
新建fruit.java
定義一個實(shí)體類可婶,作為ListView適配器的適配類型沿癞。
public class Fruit {
private String name;
private int imageId;
public Fruit (String name,int imageId){
this.name = name;
this.imageId = imageId;
}
public String getName() {
return name;
}
public int getImageId() {
return imageId;
}
}
新建布局文件 fruit_item.xml
創(chuàng)建ImageView來顯示水果圖片,TextView來顯示水果名字扰肌。并讓TextView在垂直方向上居中顯示抛寝。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<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:id="@+id/fruitname"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"/>
</LinearLayout>
新建 FruitAdapter.java
public class FruitAdapter extends ArrayAdapter<Fruit> {
private int resourceId;
public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects){
super(context,textViewResourceId,objects);
resourceId = textViewResourceId;
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
Fruit fruit = getItem(position); //獲取當(dāng)前項(xiàng)的Fruit實(shí)例
View view= LayoutInflater.from(getContext()).inflate(resourseId,parent,false);
ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
TextView fruitName =(TextView) view.findViewById(R.id.fruitname);
fruitImage.setImageResource(fruit.getImageId());
fruitName.setText(fruit.getName());
return view;
}
}
FruitAdapter 重寫了父類的構(gòu)造函數(shù),用于將上下文曙旭,ListView子項(xiàng)布局的ID和要適配的數(shù)據(jù)傳遞進(jìn)去。
重寫getView()方法晶府,這個方法在每個子項(xiàng)被滾動到屏幕內(nèi)的時候會被調(diào)用桂躏。
首先通過getItem()得到當(dāng)前的項(xiàng)的Fruit實(shí)例,然后使用LayoutInflater來為這個子項(xiàng)加載我們傳入的布局川陆。
LayoutInflater.from(getContext()).inflate(resourseId,parent,false);
inflate接受三個參數(shù)
- 一個是加載的布局文件id
- 另一個是給加載好的布局再添加一個父布局
-
false
表示只讓我們在父布局中聲明的layout屬性生效剂习,但不會為這個view添加父布局。
修改 MainActivity.java
public class MainActivity extends AppCompatActivity {
private List<Fruit> fruitList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits();// 初始化水果數(shù)據(jù)
FruitAdapter arrayAdapter = new FruitAdapter(MainActivity.this,R.layout.fruit_item,fruitList);
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(arrayAdapter);
}
private void initFruits(){
for( int i =0; i<2;i++){
Fruit apple = new Fruit("Apple",R.drawable.apple_pic);
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);
}
}
}
添加initFruit()方法來初始化所有的水果數(shù)據(jù)较沪。
運(yùn)行結(jié)果:
提升ListView的運(yùn)行效率
上面的代碼中鳞绕,F(xiàn)ruitAdapter的getView()每次都將布局重新加載了一遍,當(dāng)ListView快速滾動時尸曼,就會成為性能的瓶頸们何。
為了解決這問題,需要對ListView進(jìn)行優(yōu)化控轿。
修改FruitAdapter.java
@Override
public View getView(int position, View convertView, ViewGroup parent){
Fruit fruit = getItem(position); //獲取當(dāng)前項(xiàng)的Fruit實(shí)例
View view;
ViewHolder viewHolder;
if (convertView == null){
view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
viewHolder = new ViewHolder();
viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
viewHolder.fruitName =(TextView) view.findViewById(R.id.fruitname);
view.setTag(viewHolder);// 將ViewHolder存儲在View中冤竹。
}else
{
view = convertView;
viewHolder=(ViewHolder)view.getTag(); //重新獲取ViewHolder
}
viewHolder.fruitImage.setImageResource(fruit.getImageId());
viewHolder.fruitName.setText(fruit.getName());
return view;
}
class ViewHolder{
ImageView fruitImage;
TextView fruitName;
}
getView中的convertView參數(shù),用于將之前加載好的布局進(jìn)行緩存茬射,以便以后可以進(jìn)行重用鹦蠕。
- convertView為null時,使用LayoutInflater去加載布局在抛。
- 如果不是Null,則直接對convertView進(jìn)行重用钟病。
內(nèi)部類ViewHolder用于對控件的實(shí)例進(jìn)行緩存。
- 當(dāng)convertView為null時
創(chuàng)建ViewHolder對象刚梭,并將控件的實(shí)例都存到ViewHolder去肠阱,然后調(diào)用View的setTag()方法,將ViewHolder對象存儲于View中望浩。 - 當(dāng)convertView不為null時
調(diào)用View的setTag()方法辖所,把ViewHolder重新取出。
LiewView的點(diǎn)擊事件
修改MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits();// 初始化水果數(shù)據(jù)
FruitAdapter arrayAdapter = new FruitAdapter(MainActivity.this,R.layout.fruit_item,fruitList);
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(arrayAdapter);
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_SHORT).show();
}
});
使用setOnItemClickListener()為ListView注冊了一個監(jiān)聽器磨德。
通過position參數(shù)判斷出用戶點(diǎn)擊的是哪一個子項(xiàng)缘回。