本篇文章主要讲解最常用的控件之一:ListView的使用。
当我们的程序有大量的数据需要展示的时候,可以借助ListView实现。ListView允许用户上下滑动滚动屏幕,如:查看QQ聊天记录。
一、ListView的简单用法
** 首先新建一个新的活动,csdn7.xml中的代码如下:**
布局中引入ListView控件和前面其他控件用法一致。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
csdn7.java代码如下:
首先准备好一个数据数组用来展示,通过适配器将数据传给ListView,ArrayAdapter的构造函数中依次传入**上下文、ListView子项布局的id,要适配的数据**。注意:这里使用的android.R.layout.simple_list_item_1为Android内置的布局文件,里面只有一个TextView,用于简单显示一段文本。最后调用ListView的setAdapter()方法,将适配器对象传进去,这样ListView和数据之间的关联就建立完成。
public class csdn7 extends AppCompatActivity {
private String[] data = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_csdn7);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
csdn7.this, android.R.layout.simple_list_item_1, data);
ListView listView = findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
}
效果如下:
二、进一步优化ListView界面
只显示一段文本的ListView很单调,下面对ListView界面添加图片进行美观。效果如下:
新建一个Image类,作为ListView适配器的适配类型,代码如下:
name表示每行字母的名字,imageId表示图片id。
public class Image {
private String name;
private int imageId;
public Image(String name,int imageId){
this.name = name;
this.imageId = imageId;
}
public String getName(){
return name;
}
public int getImageId(){
return imageId;
}
}
** 接下来需要为ListView子项指定自定义的布局,在layout目录下新建item.xml,代码如下:**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"/>
</LinearLayout>
接下来创建一个自定义的适配器adapter类,,代码如下:
adapter重写了父类的构造函数,用于将上下文,ListView子项布局的id和数据传递进来。 重写getView()方法,此方法在每个子项被滚动到屏幕内时调用。 在getView()方法中,首先通过getItem方法得到当前项的image实例,然后使用LayoutInflater方法来为这个子项加载传入的布局,LayoutInflater方法的inflate方法接收3个参数,第三个参数指定为false,表示只让在父布局中声明的layout属性生效,接下来获取到两个实例,并分别调用setImageResource和setText方法设置显示的图片和文字,最后将布局返回,这样自定义的适配器就完成了。
public class adapter extends ArrayAdapter<Image> {
private int resourceId;
public adapter(Context context, int textViewResourceId, List<Image> objects){
super(context,textViewResourceId,objects);
resourceId = textViewResourceId;
}
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Image image = getItem(position);
View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
ImageView image2 = view.findViewById(R.id.image);
TextView name = view.findViewById(R.id.name);
image2.setImageResource(image.getImageId());
name.setText(image.getImageId());
return view;
}
}
下面修改主类csdn7.java的代码如下:
首先,自定义一个init()方法初始化list中的元素,然后创建自定义适配器adapter的实例,最后将适配器传递给ListView,这样就完成了。
public class csdn7 extends AppCompatActivity {
private List<Image> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_csdn7);
init();//初始化数据
adapter ad = new adapter(csdn7.this,R.layout.item,list);
ListView listview = findViewById(R.id.list_view);
listview.setAdapter(ad);
}
private void init(){
for(int i = 0; i < 5; i++){
Image a = new Image("A",R.drawable.image1);
list.add(a);
Image b = new Image("B",R.drawable.image1);
list.add(b);
Image c = new Image("C",R.drawable.image1);
list.add(c);
Image d = new Image("D",R.drawable.image1);
list.add(d);
Image e = new Image("E",R.drawable.image1);
list.add(e);
}
}
}
现在只用修改item.xml文件中的内容,就可以做出各种复杂的界面了。
三、提升ListView的效率(优化)
目前,上面的代码还有待优化的地方,如:adapter的getView()方法中,每次都将布局重新加载一遍,当ListView快速滚动的时候,运行效率会降低。再比如:每次在getView()方法中都会调用findViewById()方法获取控件实例。下面就对这两个问题进行优化。
修改adapter中的getView()方法中的代码,如下:
getView()方法有一个convertView参数,这个参数用于将之前加载好的布局进行缓存,如果为null则加载布局,如果不为null则直接重用convertView。这样优化了第一个问题。
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Image image = getItem(position);
View view;
if(convertView == null){
view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
}else{
view = convertView;
}
ImageView image2 = view.findViewById(R.id.image);
TextView name = view.findViewById(R.id.name);
image2.setImageResource(image.getImageId());
name.setText(image.getName());
return view;
}
再次修改getView()方法中的代码,如下:
新增一个内部类ViewHolder,**用于对控件的实例进行缓存**,当convertView为null时,创建一个ViewHolder对象,将控件的实例都存放在ViewHolder里,调用setTag()方法,将ViewHolder对象存放在View中;不为null时,调用getTag,重新取出。这样优化了第二个问题。
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Image image = getItem(position);
View view;
ViewHolder viewHolder;
if(convertView == null){
view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
viewHolder = new ViewHolder();
viewHolder.image = view.findViewById(R.id.image);
viewHolder.name = view.findViewById(R.id.name);
view .setTag(viewHolder);
}else{
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.image.setImageResource(image.getImageId());
viewHolder.name.setText(image.getName());
return view;
}
class ViewHolder{
ImageView image;
TextView name;
}
四、ListView的点击事件
点击事件是不可或缺的,前面的只是满足视觉上的效果,点击事件才是实际用途。
修改csdn7.java的代码,如下:
原理同前面按钮的点击事件一致,创建实例后,调用setOnItemClickListener()方法为ListView注册监听器,通过参数i判断用户点击的子项。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_csdn7);
init();//初始化数据
adapter ad = new adapter(csdn7.this,R.layout.item,list);
ListView listview = findViewById(R.id.list_view);
listview.setAdapter(ad);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Image image = list.get(i);
Toast.makeText(csdn7.this, image.getName(), Toast.LENGTH_SHORT).show();
}
});
}
效果如下:
希望本文章对你有帮助,如果你对Android开发感兴趣,请持续关注本专栏,帮助你从入门到项目实战,你将收获:Android基础开发、各种经典功能实现、项目实战、开发自己的APP、将APP上传应用商店、靠广告赚钱等等,持续更新ing......
版权归原作者 四月天行健 所有, 如有侵权,请联系我们删除。