0.ListView概述
1.只能做纵向滚动,不能做横向滚动
2.需要做性能优化
1.ListView 简单用法
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView android:id="@+id/m_listView1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
public class MainActivity extends AppCompatActivity {
private List<String> listDatas = Arrays.asList("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);
//ArrayAdapter的构造函数传入3个数据:1是Context 传入当前的上下文,2是ListView子项布局的ID,3是要适配的数据
//android.R.layout.simple_list_item_1,listDatas是内置的ListViewItem
ArrayAdapter<String> dapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,listDatas);
ListView listView = findViewById(R.id.m_listView1);
listView.setAdapter(dapter);
}
}
2.自定义ListViewItem
1-定义布局文件 fruit_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView android:id="@+id/fruit_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_vertical"/>
<TextView android:id="@+id/fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"/>
</LinearLayout>
2-定义Fruit类:
public class Fruit {
public Fruit(int imgId, String name) {
this.imageId = imgId;
this.name = name;
}
private int imageId;
private String name;
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3-定义Adapter: FruitAdapter extends ArrayAdapter
public class FruitAdapter extends ArrayAdapter<Fruit> {
private int resourceId;
public FruitAdapter(@NonNull Context context, int textViewResourceId, List<Fruit> objects) {
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
/**
* 每个子项被滚动到屏幕时调用
* */
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Fruit fruit = getItem(position);
View view = LayoutInflater.from(getContext()) //获得LayoutInflater对象
.inflate(resourceId ,parent ,false); //根据布局id把这个布局加载成一个View并返回
ImageView fruitImage = view.findViewById(R.id.fruit_image);
TextView fruitName = view.findViewById(R.id.fruit_name);
fruitImage.setImageResource(fruit.getImageId());
fruitName.setText(fruit.getName());
return view;
}
}
4-加载数据
public class MainActivity extends AppCompatActivity {
/* private List<String> listDatas = Arrays.asList("Apple", "Banana", "Orange", "Watermelon",
"Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango"
, "Apple", "Banana"
, "Orange", "Watermelon"
, "Pear", "Grape",
"Pineapple"
, "Strawberry", "Cherry", "Mango");*/
private List<Fruit> fruits = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* //ArrayAdapter的构造函数传入3个数据:
// 1是Context 传入当前的上下文
// ,2是ListView子项布局的ID
// ,3是要适配的数据
//android.R.layout.simple_list_item_1,listDatas是内置的
ArrayAdapter<String> dapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,listDatas);
ListView listView = findViewById(R.id.m_listView1);
listView.setAdapter(dapter);*/
InitFruits();
FruitAdapter adapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item, fruits);
ListView listView = findViewById(R.id.m_listView1);
listView.setAdapter(adapter);
}
private void InitFruits(){
for (int i= 0; i < 10 ; i++){
Fruit taozi = new Fruit(R.drawable.taozi, "桃子");
fruits.add(taozi);
Fruit putao = new Fruit(R.drawable.putao, "葡萄");
fruits.add(putao);
Fruit huolongguo = new Fruit(R.drawable.huolongguo, "火龙果");
fruits.add(huolongguo);
Fruit lamei = new Fruit(R.drawable.lanmei, "蓝莓");
fruits.add(lamei);
Fruit xiguang = new Fruit(R.drawable.xigua, "西瓜");
fruits.add(xiguang);
}
}
}
效果:
3.优化ListView性能
1.getView()方法中,每次都将布局重新加载了一遍,当ListView快速滚动的时候,这就会成为性能的瓶颈。
convertView参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以进行重用。
2.调用View 的 findViewById()方法来获取一次控件的实例。借助一个ViewHolder来对这部分性能进行优化
public class FruitAdapter extends ArrayAdapter<Fruit> {
private int resourceId;
public FruitAdapter(@NonNull Context context, int textViewResourceId, List<Fruit> objects) {
super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
/**
* 每个子项被滚动到屏幕时调用
*/
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Fruit fruit = getItem(position);
/* View view = LayoutInflater.from(getContext()) //获得LayoutInflater对象
.inflate(resourceId ,parent ,false); //根据布局id把这个布局加载成一个View并返回*/
/****************************优化ListView运行效率********************************************************
1.getView()方法中,每次都将布局重新加载了一遍,当ListView快速滚动的时候,这就会成为性能的瓶颈。
convertView参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以进行重用。
2.调用View 的 findViewById()方法来获取一次控件的实例。借助一个ViewHolder来对这部分性能进行优化
*********************************************************************************************************/
View view = null;
ViewHolder viewHolder;
if (null == convertView) {
view = LayoutInflater.from(getContext()) //获得LayoutInflater对象
.inflate(resourceId, parent, false); //根据布局id把这个布局加载成一个View并返回
viewHolder = new ViewHolder();
viewHolder.fruitImage = view.findViewById(R.id.fruit_image);
viewHolder.fruitName = view.findViewById(R.id.fruit_name);
view.setTag(viewHolder); //将ViewHolder存储在View中
} else {
view = convertView;
viewHolder = (ViewHolder) view.getTag(); //从View中获取ViewHolder
}
viewHolder.fruitImage.setImageResource(fruit.getImageId());
viewHolder.fruitName.setText(fruit.getName());
return view;
}
class ViewHolder{
ImageView fruitImage;
TextView fruitName;
}
}
4.ListView的点击事件
//ListView 子项点击事件
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fruit fruit = fruits.get(position);
Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_LONG).show();
/* TextView fruitName = view.findViewById(R.id.fruit_name);
Toast.makeText(MainActivity.this, fruitName.getText().toString(), Toast.LENGTH_LONG).show();*/
}
});
在点击事件中获取Fruit
的数据
//ListView 子项点击事件
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Adapter adapter = parent.getAdapter();
Fruit fruit = (Fruit) adapter.getItem(position);
Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show();
}
});