首先在activity_main中加入ListView控件。

而后修改MainActivity中的代码
public class MainActivity extends AppCompatActivity { String[] data = {"apple","banana","orange","watermelon","banana","orange","watermelon","banana","orange","watermelon","banana","orange","watermelon","banana","orange","watermelon","banana","orange","watermelon","banana","orange","watermelon","banana","orange","watermelon"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); ArrayAdapter adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1,data); ListView listView = (ListView) findViewById(R.id.list_view); listView.setAdapter(adapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView> parent, View view, int position, long id) { String fruit = data[position]; Toast.makeText(MainActivity.this,fruit,Toast.LENGTH_SHORT).show(); } }); } } ArrayAdapter
ArrayAdapter对象,它是Android中用于将数据绑定到ListView、GridView等组件的适配器之一。表示这个适配器是用来处理字符串(String)类型的数据。new ArrayAdapter<>(... 表示实例化一个ArrayAdapter对象。MainActivity.this是当前MainActivity的上下文(Context),这通常用于获取系统服务或启动其他组件。android.R.layout.simple_list_item_1是一个系统提供的布局资源,用于定义列表项的样式。这里指定了列表项的布局,该布局显示单个文本项。data是一个字符串数组,它包含了要显示在列表中的所有数据。ListView listView = (ListView) findViewById(R.id.list_view);
findViewById方法来获取布局文件中定义的ListView组件的实例。R.id.list_view是ListView组件在布局文件中的ID。ListView是Android中的一个组件,用于显示垂直滚动的列表项。listView.setAdapter(adapter);
adapter设置为listView的适配器。setAdapter是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; } } 而后为ListView的子项指定一个自定义的布局,在layout目录下新建一个fruit_item.xml
接着我们需要创建一个自定义的适配器,这个适配器继承自ArrayAdapter,并将泛型是定位Fruit类
public class FruitAdapter extends ArrayAdapter { private int resourceId; public FruitAdapter(@NonNull Context context, int textViewResourceId, List 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()).inflate(resourceId, parent, false); ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image); TextView fruitName = (TextView) view.findViewById(R.id.fruit_name); fruitImage.setImageResource(fruit.getImageId()); fruitName.setText(fruit.getName()); return view; } } public class FruitAdapter extends ArrayAdapter { FruitAdapter的公共类,它继承自ArrayAdapter类,并且指定了泛型参数Fruit,这意味着这个适配器是专门为处理Fruit类型对象的列表而设计的。private int resourceId;resourceId,用于存储列表项的布局资源ID。public FruitAdapter(@NonNull Context context, int textViewResourceId, List objects) { FruitAdapter的构造函数,它接受三个参数: @NonNull Context context:上下文对象,用于访问系统服务和资源。int textViewResourceId:列表项的布局资源ID。List objects :一个包含Fruit对象的列表,这些对象将被显示在列表中。super(context, textViewResourceId, objects);ArrayAdapter的构造函数,传递上下文、资源ID和对象列表。public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {ArrayAdapter中的getView方法,它是适配器的核心,用于为列表中的每个项提供视图。int position:当前项在列表中的位置。@Nullable View convertView:可重用的视图,用于提高列表滚动的性能。@NonNull ViewGroup parent:列表视图的父容器。Fruit fruit = getItem(position);ArrayAdapter的getItem方法,获取列表中当前位置的Fruit对象。View view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);LayoutInflater从getContext()获取的上下文中实例化一个视图,使用resourceId指定的布局资源,并且parent是列表视图的父容器,false表示不要为parent添加这个视图。
LayoutInflater.from(getContext())
LayoutInflater是一个用于将XML布局文件转换成实际视图对象的系统服务。from(context)是一个静态方法,它返回一个LayoutInflater的实例,并且已经配置了给定的上下文(context)。getContext()
- 这是
ArrayAdapter类的一个方法,返回当前适配器的上下文(Context)。上下文是Android中非常重要的概念,它提供了对系统服务的访问以及对资源的引用。inflate(resourceId, parent, attachToRoot)
inflate是LayoutInflater类的一个方法,用于将指定资源ID的XML布局文件实例化为视图对象。resourceId:是一个整型值,指定了要实例化的布局资源的ID。parent:是一个ViewGroup对象,表示新创建的视图将要被添加到的父容器。在这个上下文中,parent参数通常是用来确保新视图的布局参数正确设置的。attachToRoot:是一个布尔值,指定是否将新创建的视图附加到parent。在这个例子中,false表示不附加到parent,而是返回一个独立的视图对象,稍后可以手动添加到parent。综合来看,
LayoutInflater.from(getContext()).inflate(resourceId, parent, false);这行代码的作用是:
- 从当前适配器的上下文中获取
LayoutInflater实例。- 使用
inflate方法将指定的布局资源ID(resourceId)转换成实际的视图对象。- 将这个新创建的视图作为子视图,但不立即附加到提供的父容器(
parent)上。- 返回这个新创建的视图对象,以便可以在适配器的
getView方法中进一步设置和返回。
ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);findViewById获取布局中的ImageView组件,用于显示水果的图片。TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);findViewById获取布局中的TextView组件,用于显示水果的名称。fruitImage.setImageResource(fruit.getImageId());ImageView的图片资源,getImageId()是Fruit类的一个方法,返回图片资源的ID。fruitName.setText(fruit.getName());TextView的文本,getName()是Fruit类的一个方法,返回水果的名称。return view;FruitAdapter类通过重写getView方法,为每个列表项提供了自定义的视图布局,包括水果的图片和名称。这使得列表项不仅显示文本,还可以显示图像,从而提供更丰富的用户界面。
这一步骤只需要替换上一阶段中的适配器对象即可,此处略过。
将FruitAdapter中的代码进行优化。
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { Fruit fruit = getItem(position); View view; if(convertView == null){ view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false); }else{ view = convertView; } ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image); TextView fruitName = (TextView) view.findViewById(R.id.fruit_name); fruitImage.setImageResource(fruit.getImageId()); fruitName.setText(fruit.getName()); return view; } convertView,减少了布局的创建和视图的初始化次数。这对于长列表来说尤其重要,因为它可以显著减少内存使用和提高滚动性能。public class FruitAdapter extends ArrayAdapter { private int resourceId; public FruitAdapter(@NonNull Context context, int textViewResourceId, List 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; ViewHolder viewHolder; if(convertView == null){ view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false); viewHolder = new ViewHolder(); viewHolder.fruitImage = view.findViewById(R.id.fruit_image); viewHolder.fruitName = view.findViewById(R.id.fruit_name); view.setTag(viewHolder); }else{ view = convertView; viewHolder = (ViewHolder) view.getTag(); } viewHolder.fruitImage.setImageResource(fruit.getImageId()); viewHolder.fruitName.setText(fruit.getName()); return view; } class ViewHolder { ImageView fruitImage; TextView fruitName; } } 此控件早在远古时代的16年就被淘汰。

由于该组件不是内置在系统SDK中,所以需要把完整的包路径写出来。
public class FruitAdapter extends RecyclerView.Adapter { private List mFruitList; static class ViewHolder extends RecyclerView.ViewHolder{ ImageView fruitImage; TextView fruitName; public ViewHolder(View itemView) { super(itemView); fruitImage = (ImageView) itemView.findViewById(R.id.fruit_image); fruitName = (TextView) itemView.findViewById(R.id.fruit_name); } } public FruitAdapter(List mFruitList) { this.mFruitList = mFruitList; } @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent,false); ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { Fruit fruit = mFruitList.get(position); holder.fruitImage.setImageResource(fruit.getImageId()); holder.fruitName.setText(fruit.getName()); } @Override public int getItemCount() { return mFruitList.size(); } } 这段代码定义了一个名为FruitAdapter的类,它扩展了RecyclerView.Adapter,用于在RecyclerView中显示水果列表。
public FruitAdapter(List mFruitList) Fruit对象的列表。static class ViewHolder extends RecyclerView.ViewHolderViewHolder,用于缓存视图组件的引用,减少重复调用findViewById。@Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)ViewHolder实例。这个方法负责为每个列表项提供视图。@Override public void onBindViewHolder(@NonNull ViewHolder holder, int position)ViewHolder上。这个方法负责将每个列表项的数据填充到视图中。@Override public int getItemCount()RecyclerView用来确定显示多少项的方法。Fruit对象的列表,并将其存储在适配器中。ViewHolder的构造函数中,通过调用itemView.findViewById获取视图中的组件(如ImageView和TextView),并将它们存储在ViewHolder实例中。LayoutInflater从parent.getContext()获取的上下文中加载布局资源(R.layout.fruit_item),并将其实例化为视图。ViewHolder实例,并将新创建的视图传递给ViewHolder的构造函数。ViewHolder实例。position参数获取列表中对应位置的Fruit对象。ViewHolder中的组件引用(fruitImage和fruitName)来设置视图的图片资源和文本。Fruit对象列表的大小,即列表项的总数。private List fruitList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); initFruits(); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); FruitAdapter adapter = new FruitAdapter(fruitList); recyclerView.setAdapter(adapter); } initFruits(); initFruits的方法,这个方法可能是用来初始化一个包含Fruit对象的列表,这些对象将被用于填充RecyclerView。RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); findViewById方法,获取布局文件中定义的RecyclerView组件的实例,并将其转换为RecyclerView类型。LinearLayoutManager layoutManager = new LinearLayoutManager(this); LinearLayoutManager对象,用于管理RecyclerView中的项如何布局。this关键字指的是当前的上下文(可能是一个Activity或Fragment)。recyclerView.setLayoutManager(layoutManager); LinearLayoutManager设置为RecyclerView的布局管理器,这样RecyclerView就知道如何对其子项进行布局。FruitAdapter adapter = new FruitAdapter(fruitList); FruitAdapter对象,并将之前初始化的fruitList(包含Fruit对象的列表)传递给它。这个适配器将用于将数据绑定到RecyclerView。recyclerView.setAdapter(adapter); FruitAdapter设置为RecyclerView的适配器。这样RecyclerView就有了数据源,并且知道如何显示这些数据。
RecyclerView 是 Android 中一个灵活的组件,用于展示大量数据集,它可以配合不同的布局管理器(LayoutManager)来实现横向滚动、瀑布流布局和网格布局。以下是实现这些布局的基本步骤:
横向滚动通常使用 LinearLayoutManager 并设置其方向为横向。
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); recyclerView.setLayoutManager(layoutManager); 瀑布流布局是一种不规则的网格布局,可以实现不同高度和宽度的项。
StaggeredGridLayoutManager 实例:StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(spanCount, StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager); 网格布局使用 GridLayoutManager 来实现。
GridLayoutManager 实例:GridLayoutManager layoutManager = new GridLayoutManager(this, spanCount); recyclerView.setLayoutManager(layoutManager); RecyclerView 的布局管理器:recyclerView.setLayoutManager(layoutManager); @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent,false); ViewHolder holder = new ViewHolder(view); //注册文字监听事件 holder.fruitName.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int position = holder.getAdapterPosition(); Fruit fruit = mFruitList.get(position); Toast.makeText(view.getContext(),"外层", Toast.LENGTH_SHORT).show(); } }); //注册图片按钮监听事件 holder.fruitImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int position = holder.getAdapterPosition(); Fruit fruit = mFruitList.get(position); Toast.makeText(view.getContext(),"图片", Toast.LENGTH_SHORT).show(); } }); return holder; } 
