Andriod 自定义ListView的列表项
发布日期:2021-05-07 23:05:21 浏览次数:24 分类:原创文章

本文共 9870 字,大约阅读时间需要 32 分钟。

文章目录

1 自定义ListView列表项

  • LIstView支持自定义列表项,此时需要自定义布局文件
  • 在自定义布局文件需要使用类型数据的时候,此时需要自定义适配器

1.1 自定义布局文件

  1. 新建layout.xml文件
  2. 新建的layout布局是列表项的布局,相当于在列表项中进行自定义布局
<?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:layout_width="100dp"        android:layout_height="80dp"        android:id="@+id/fruit_image"        android:src="@drawable/apple"        />    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/fruit_name"        android:text="name"        android:textSize="30sp"        android:textColor="#000000"        android:layout_gravity="center_vertical"        android:layout_marginLeft="20dp"        />        <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/fruit_price"        android:text="name"        android:textSize="30sp"        android:textColor="#ff0000"        android:layout_gravity="center_vertical"        android:layout_marginLeft="40dp"        /></LinearLayout>

1.2 自定义Adapter加载自定义布局

  • 自定义Adapter需要继承一个父类适配器,例如:ArrayAdapter, 并覆盖其中的构造方法与**getView()**方法
  1. 自定义构造方法:必须是有参构造方法
  • 参数一:上下文环境,例如MainActivity.this
  • 参数二:布局文件的ID,为R.layout.layout
  • 参数三:为列表类型的数据源
// 参数1 为上下文, 参数2 为layout布局的id, 参数3 为数据源    public FruitAdapter(@NonNull Context context, int resource, @NonNull List<Fruit> objects) {           super(context, resource, objects);    }
  1. getView方法,填充自定义布局

使用步骤:

  1. 获取传入数组的数据项,数组或者列表在构造方法中传入
  2. 将自定义布局转化为View类型,使用 **inflate()**方法进行填充 LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout, parent, false);
  3. 在view中获取其中的控件,填充其中的信息
  4. 最后返回布局view
// 屏幕滑动的时候,调用子项@NonNull@Overridepublic View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {       //1. 得到当前fruit实例, 可见 fruit在适配器中    Fruit fruit = getItem(position);    // 2. 为子项加载布局, 传入到ViewGroup中    View view = LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout, parent, false);    // 3. 获取View中的控件,并为控件赋值    ImageView fruitImage = view.findViewById(R.id.fruit_image);    TextView fruitName = view.findViewById(R.id.fruit_name);    TextView fruitPrice = view.findViewById(R.id.fruit_price);    // 4. 设置图片以及文件资源    fruitImage.setImageResource(fruit.getImageID());    fruitName.setText(fruit.getName());    fruitPrice.setText("$" + fruit.getPrice() / 100 + "/KG");    // 5. 返回设置好的布局    return view;}

2 进行ListView进行适配

2.1 自定义JavaBean

package com.hlq.sz_ch_listviewdemo02;public class Fruit {       private int imageID;    private String name;    private long price;    public void setImageID(int imageID) {           this.imageID = imageID;    }    public void setName(String name) {           this.name = name;    }    public void setPrice(long price) {           this.price = price;    }    public int getImageID() {           return imageID;    }    public String getName() {           return name;    }    public long getPrice() {           return price;    }    public Fruit(int imageID, String name, long price) {           this.imageID = imageID;        this.name = name;        this.price = price;    }    public Fruit() {       }}

2.2 自定义布局与ListIView绑定

2.2.1 主布局文件

<?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"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity">    <ListView        android:id="@+id/list_view"        android:layout_width="match_parent"        android:layout_height="match_parent"        /></LinearLayout>

2.2.2 获取自定义布局文件,填充主布局文件

  • 在内存中新建自定义列表适配器new FruitAdapterEnhance(MainActivity.this, R.layout.fruit_layout, fruits);
  • 绑定适配器listView.setAdapter(fruitAdapter);
import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.AdapterView;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {       // 内部对象    private ListView listView;    @Override    protected void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // 1. 绑定控件        listView = (ListView)findViewById(R.id.list_view);        // 2. 准备数据        List<Fruit> fruits = new ArrayList<>();        for (int i = 0; i < 2; ++i) {               Fruit pineApple = new Fruit(R.drawable.pineapple, "菠萝", 1690);            fruits.add(pineApple);            Fruit mango = new Fruit(R.drawable.mango, "芒果", 2990);            fruits.add(mango);            Fruit grape = new Fruit(R.drawable.grape, "葡萄", 1990);            fruits.add(grape);            Fruit pomegranate = new Fruit(R.drawable.pomegranate, "石榴", 1500);            fruits.add(pomegranate);            Fruit apple =  new Fruit(R.drawable.apple, "苹果", 2000);            fruits.add(apple);            Fruit watermelon = new Fruit(R.drawable.watermelon, "西瓜", 2880);            fruits.add(watermelon);            Fruit orange = new Fruit(R.drawable.orange, "橘子", 1880);            fruits.add(orange);        }        // 3. 设置子布局        // 4. 定义适配器, 控件与数据的桥梁        FruitAdapterEnhance fruitAdapter = new FruitAdapterEnhance(MainActivity.this, R.layout.fruit_layout, fruits);        listView.setAdapter(fruitAdapter);        // 5. 设置点击事件        // 4 为列表适配器增加响应事件        listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){               @Override            public void onItemClick(AdapterView<?> parent, View view, int position , long i) {                   // 从View中获取信息, 此时的View为点击的View                TextView textView = view.findViewById(R.id.fruit_name);                String result = textView.getText().toString();                Toast.makeText(MainActivity.this, "选择的选项为: " + result, Toast.LENGTH_SHORT).show();                // 上下文必须指定为MainActivity.this            }        });    }}

3 对自定义布局的加载进行优化

  • 优化思想:在用户进行滑动的时候,每一个列表项都需要重新加载,由于布局要加载到内存,造成ListView的性能下降
  • 为了优化性能,可以将ListView的布局保存,不必重新加载,每一个列表项只是将数据填入到布局中

3.1 对自定义列表适配器进行优化

  1. 自定义内部类,包含列表项中的布局控件,此时为ViewHolder
  2. 第一次加载时,View的引用为null, 将ViewHolder内部类存储view中,使用view.setTag(viewHolder);
  3. 当view的引用不为null的时候,获取view布局,并获取其中的内部类进行布局的填充view = convertView; viewHolder = (ViewHolder)view.getTag();
  4. 每一个项目的加载都需要设置信息,因此在ViewHolder内部类中填充信息。获取View控件,进行资源的设置,例如:
viewHolder.getFruitImage().setImageResource(fruit.getImageID());viewHolder.getFruitName().setText(fruit.getName());

3.2 完整优化代码

import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.ImageView;import android.widget.TextView;import androidx.annotation.NonNull;import androidx.annotation.Nullable;import java.util.List;public class FruitAdapterEnhance extends ArrayAdapter<Fruit> {       // 构造函数    // 参数1 为上下文, 参数2 为layout布局的id, 参数3 为数据源    public FruitAdapterEnhance(@NonNull Context context, int resource, @NonNull List<Fruit> objects) {           super(context, resource, objects);    }    // 屏幕滑动的时候,调用子项    @NonNull    @Override    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {           //1. 得到当前fruit实例, 从适配的位置获取 使得控件与数据项一一对应        Fruit fruit = getItem(position);        // 1. 新增ViewHolder        ViewHolder viewHolder;        View view;        // 2. 是否加载了布局        if (convertView == null) {               // 2.1 没有加载布局的时候,使用子布局            view = LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout, parent, false);            viewHolder = new ViewHolder();            viewHolder.setFruitImage(view.findViewById(R.id.fruit_image));            viewHolder.setFruitName(view.findViewById(R.id.fruit_name));            viewHolder.setFruitPrice(view.findViewById(R.id.fruit_price));            // 2.2 将viewHolder存储与view中            view.setTag(viewHolder);        } else {               // 从新获取viewHolder            view = convertView;            viewHolder = (ViewHolder)view.getTag();        }        // 3. 设置viewGroup中的内容        viewHolder.getFruitImage().setImageResource(fruit.getImageID());        viewHolder.getFruitName().setText(fruit.getName());        viewHolder.getFruitPrice().setText("$" + fruit.getPrice() / 100 + "/Kg");//        // 2. 为子项加载布局, 传入到ViewGroup中//        View view = LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout, parent, false);////        // 3. 获取View中的控件,并为控件赋值//        ImageView fruitImage = view.findViewById(R.id.fruit_image);//        TextView fruitName = view.findViewById(R.id.fruit_name);//        TextView fruitPrice = view.findViewById(R.id.fruit_price);////        // 4. 设置图片以及文件资源//        fruitImage.setImageResource(fruit.getImageID());//        fruitName.setText(fruit.getName());//        fruitPrice.setText("$" + fruit.getPrice() / 100 + "/KG");////        // 5. 返回设置好的布局        return view;    }    // 3设置内部类,加载布局,只需提供数据,加快读取速度    private class ViewHolder{           ImageView fruitImage;        TextView fruitName;        TextView fruitPrice;        public ImageView getFruitImage() {               return fruitImage;        }        public TextView getFruitName() {               return fruitName;        }        public TextView getFruitPrice() {               return fruitPrice;        }        public void setFruitImage(ImageView fruitImage) {               this.fruitImage = fruitImage;        }        public void setFruitName(TextView fruitName) {               this.fruitName = fruitName;        }        public void setFruitPrice(TextView fruitPrice) {               this.fruitPrice = fruitPrice;        }    }}

4 结果

在这里插入图片描述

在这里插入图片描述

上一篇:Andriod RecyclerView 适配器与点击事件
下一篇:Andriod ListView简单数组适配器

发表评论

最新留言

不错!
[***.144.177.141]2025年03月30日 02时58分29秒