ListView由于手机屏幕空间都比较有限,能够一次性在屏幕上显示的内容并不多,当我们的程序中有少量 的数据需要展示的时候,就可以借助ListView来实现。ListView允许用户通过手指上下滑动的方 式将屏幕外的数据滚动到屏幕内,同时屏幕上原有的数据则会滚动出屏幕。相信你其实每都 在使用这个控件,比如查看QQ聊天记录,微信好友列表,翻阅微博最新消息,等等。 作用: 在有限的屏幕展示少量的数据,可以实现滑动显示。
ListView的特别属性:
divider = 设置列表项之间的分割线
dividerHeigth = 设置列表项之间的高度
listSelector = 设置列表项选中时的背景
ListView xml布局
xml布局:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/List_V"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:listSelector="#839ABC"
android:divider="#D82424"
android:dividerHeight="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
自定义ListView
自定义ListView的数据展示list_item.xml布局:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="110dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="160dp"
android:layout_height="100dp"
android:scaleType="fitXY"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/avatars" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="52dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="@+id/imageView"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toTopOf="@+id/imageView"
app:layout_constraintVertical_bias="0.469" />
</androidx.constraintlayout.widget.ConstraintLayout>
ListView数据实体类
定义一个数据实体类,作为ListView适配器的适配类型数据。
public class Fruit {
Integer imageView;
String name;
public Integer getImageView() {
return imageView;
}
public String getName() {
return name;
}
public Fruit(Integer imageView,String name){
this.imageView = imageView;
this.name = name;
}
}
ListView适配器ArrayAdapter<>
ListView适配器ArrayAdapter<Fruit>,目前我们ListView的运行效率是很低的,因为在FruitAdapter 的getView() 方法中,每次都将布局重新加载了一遍,当ListView快速滚动的时候,这就会成为性能的瓶颈。
public class FruitAdapter extends ArrayAdapter<Fruit> {
protected int resourceID;
public FruitAdapter(@NonNull Context context, int resource, @NonNull List objects) {
super(context, resource, objects);
resourceID = resource;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Fruit fruit = (Fruit) getItem(position);
View view = LayoutInflater.from(parent.getContext()).inflate(resourceID, parent, false);
ImageView imageView = view.findViewById(R.id.imageView);
TextView name = view.findViewById(R.id.name);
imageView.setImageResource(fruit.getImageView());
name.setText(fruit.getName());
return view;
}
}
ListView效率优化
提升ListView运行效率,getView() 方法中有一个convertView 参数,这个参数用于将之前加载 好的布局进行缓存,以便之后可以进行重用:public class FruitAdapter extends ArrayAdapter<Fruit> {
protected int resourceID;
public FruitAdapter(@NonNull Context context, int resource, @NonNull List objects) {
super(context, resource, objects);
resourceID = resource;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Fruit fruit = (Fruit) getItem(position);
View view;
if (convertView == null) {
view = LayoutInflater.from(parent.getContext()).inflate(resourceID, parent, false);
} else {
view = convertView;
}
ImageView imageView = view.findViewById(R.id.imageView);
TextView name = view.findViewById(R.id.name);
imageView.setImageResource(fruit.getImageView());
name.setText(fruit.getName());
return view;
}
}
ListView效率深度优化
可以看到,现在我们在getView() 方法中进行了判断,如果convertView 为null ,则使 用LayoutInflater 去加载布局,如果不为null 则直接对convertView 进行重用。这样就 大大提高了ListView的运行效率,在快速滚动的时候也可以表现出更好的性能。 不过,目前我们的这份代码还是可以继续优化的,虽然现在已经不会再重复去加载布局,但是 每次在getView() 方法中还是会调用View 的findViewById() 方法来获取一次控件的实 例。我们可以借助一个ViewHolder 来对这部分性能进行优化,修改FruitAdapter 中的代 码,如下所示public class FruitAdapter extends ArrayAdapter<Fruit> {
protected int resourceID;
public FruitAdapter(@NonNull Context context, int resource, @NonNull List objects) {
super(context, resource, objects);
resourceID = resource;}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Fruit fruit = (Fruit) getItem(position);
View view;
ViewHolder viewHolder;
if (convertView == null) {
view = LayoutInflater.from(parent.getContext()).inflate(resourceID,parent,false);
viewHolder = new ViewHolder();
viewHolder.fruit_imageView = view.findViewById(R.id.imageView);
viewHolder.fruit_name = view.findViewById(R.id.name);
view.setTag(viewHolder);//将viewHolder存储在view中
}
else {
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.fruit_imageView.setImageResource(fruit.getImageView());
viewHolder.fruit_name.setText(fruit.getName());
return view;}
private class ViewHolder{ ImageView fruit_imageView;TextView fruit_name;}
}
我们新增了一个内部类ViewHolder,用于对控件的实例进行缓存。当convertView为null的时候,创建一个ViewHolder对象,并将控件的实例都存放在ViewHolder里,然后调用View的setTag()方法,将ViewHolder对象存储在View 中。当convertView不为null的时候,则调用View的getTag()方法,把ViewHolder重新取出。这样所有控件的实例都缓存在了ViewHolder 里,就没有必要每次都通过findViewById() 方法来获取控件实例了。
List View监听事件
ListView的滚动毕竟只是满足了我们视觉上的效果,可是如果ListView中的子项不能 点击的话,这个控件就没有什么实际的用途了。因此,我们就设置ListView响应用户的点击事件listView.setOnTtemClickListener:listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fruit fruit = list.get(position);
Toast.makeText((Context) MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
MainActivity中调用相应方法函数:
public class MainActivity extends AppCompatActivity {
List<Fruit> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
inF();
ListView listView = findViewById(R.id.List_V);
FruitAdapter adapter= new FruitAdapter(this,R.layout.list_item,list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fruit fruit = list.get(position);
Toast.makeText((Context) MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
}
private void inF() {
for (int i = 0; i < 1000; i++) {
Fruit p1 = new Fruit(R.drawable.pg,"苹果");
Fruit p2 = new Fruit(R.drawable.xj,"香蕉");
list.add(p1);
list.add(p2);
}
}
}
我们使用setOnItemClickListener() 方法为ListView注册了一个监听器,当用
户点击了ListView中的任何一个子项时,就会回调onItemClick() 方法。在这个方法中可以通
过position 参数判断出用户点击的是哪一个子项,然后获取到相应的水果,并通过Toast将水
果的名字显示出来。
最终效果:
标签:总结,fruit,View,超强,imageView,ListView,public,view From: https://blog.csdn.net/m0_74225871/article/details/139355482