本代码使用的Android版本:android-studio-2024.2.1.11-windows
本篇文章先介绍自定适配器的如何定义,如何使用,如果赶时间,请直接点击下述目录中项目完整代码部分,可直接跳转:
目录
本文章仅在基础适配器那一篇博客的基础上,更改了适配器为自定适配器的写法,基础适配器那一片文章博客链接如下:
实现效果图
一、自定义适配器应该如何定义?
自定义适配器需要实现一个适配器接口,即BaseAdapter接口,重写其中的getCount()、getItem(int position)、getItemId(int position)、getView(int position,View convertView,ViewGroup parent)方法
重写方法 | |
getCount() | 返回适配器中数据的总数 |
getItem(int position) | 根据指定的位置(索引)获取适配器中的数据项。 |
getItemId(int position) | 返回指定位置数据项的ID。 |
getView(int position,View convertView,ViewGroup parent) | 返回已经填充好数据的视图 |
下面为示例自定义适配部分的代码:
package com.example.test03.AllAdapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.test03.R;
import java.util.List;
import java.util.Map;
public class ProductAdapter extends BaseAdapter {
private Context context;
private List<Map<String, Object>> productData;
private LayoutInflater inflater;
//初始化
public ProductAdapter(Context context, List<Map<String, Object>> productData) {
this.context = context;
this.productData = productData;
this.inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
//获取数量
return productData.size();
}
@Override
public Object getItem(int position) {
//获取对象
return productData.get(position);
}
@Override
public long getItemId(int position) {
//获取Item模板
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//position是选中的ViewList中list的列中的索引
//convertView是用于展示在页面中空白item,最后需要返回一个已填充的convertView返回
//定义一个ViewHolder类
ViewHolder holder;
if (convertView == null) {
//根据获取的item创建一个视图
convertView = inflater.inflate(R.layout.item_commodity, parent, false);
//绑定item中的控件到ViewHolder身上
holder = new ViewHolder();
holder.productName = convertView.findViewById(R.id.productName);
holder.productDescription = convertView.findViewById(R.id.productDescription);
holder.productImage = convertView.findViewById(R.id.productImage);
convertView.setTag(holder);
} else {
//如果已经存在视图
holder = (ViewHolder) convertView.getTag();
}
//根据点击获取的list索引寻找对应的Map
Map<String, Object> product = productData.get(position);
//根据Map中的信息,以键找值的形式一一赋值給每一个控件,以做到对控件的数据的填充
holder.productName.setText((String) product.get("name"));
holder.productDescription.setText((String) product.get("description"));
int imageResId = (int) product.get("image"); // 图片资源ID是以整型存储的
holder.productImage.setImageResource(imageResId);
return convertView;
}
//定义ViewHolder,将item中所有的控件都列一个变量
private static class ViewHolder {
TextView productName;
TextView productDescription;
ImageView productImage;
}
}
二、定义ViewHolder的作用以及用处:
下面详细介绍以下关于定义ViewHolder的作用以及目的:
在列表的每一项(item)中,通常会有多个视图元素(如
TextView
、ImageView
等)。如果不使用 ViewHolder,每次滚动到新的列表项时,系统都需要重新通过findViewById
方法来查找这些视图元素。这是一个非常耗时的操作,特别是在列表项很多或视图元素复杂的情况下。使用 ViewHolder 后,每个列表项都会有一个对应的 ViewHolder 对象,该对象在列表项首次被创建时初始化,并缓存了所有视图元素的引用。这样,在滚动到该列表项时,就可以直接通过 ViewHolder 获取视图元素的引用,而无需再次调用
findViewById
。
1.setTag(Object tag)方法
setTag(Object tag)
方法允许你为视图设置一个标签(Tag),这个标签可以是任何类型的对象。标签通常用于存储与视图相关的额外信息,这些信息在视图的生命周期内可能需要被访问或修改。例如,你可能会在列表项的视图中使用setTag
存储与该列表项相关的数据对象,以便在后续的点击事件处理中能够轻松访问这些数据。
2.getTag()方法
getTag()
方法用于检索之前通过setTag(Object tag)
方法设置的标签。如果之前没有为视图设置标签,则getTag()
方法将返回null
。
三、项目完整代码:
1.Store主页面:
页面代码:
<?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"
android:fitsSystemWindows="true"
tools:context=".Store">
<ListView
android:id="@+id/listView"
android:layout_width="409dp"
android:layout_height="729dp"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
Java代码:
package com.example.test03;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import com.example.test03.AllAdapter.ProductAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Store extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_store);
//获取数据
List<Map<String, Object>> productData = GetDate();
// //装配适配器
// SimpleAdapter adapter = new SimpleAdapter(
// this, // 上下文
// productData, // 数据源
// R.layout.item_commodity, // 自定义布局资源 item
// new String[]{"name", "description", "image"}, // 数据源中的键数组
// new int[]{R.id.productName, R.id.productDescription, R.id.productImage} // 布局文件中的视图 ID 数组
// );
ProductAdapter productAdapter = new ProductAdapter(this,productData);
ListView listView = findViewById(R.id.listView);
listView.setAdapter(productAdapter);
//如果想要得到效果图中的功能的话,需要为他设置一个监听器,如下
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// 获取被点击项目的数据
Map<String, Object> clickedItem = (Map<String, Object>) parent.getItemAtPosition(position);
String productName = (String) clickedItem.get("name");
String productDescription = (String) clickedItem.get("description");
// 在这里处理点击事件,比如显示一个 Toast 消息
Toast.makeText(Store.this, "你点击了 " + productName + "\n" + productDescription, Toast.LENGTH_LONG).show();
}
});
}
private List<Map<String, Object>> GetDate() {
List<Map<String, Object>> productData = new ArrayList<>();
//根据数据源中的键数组来填充数据
//new String[]{"name", "description", "image"},
// 创建巧克力商品数据
Map<String, Object> chocolate = new HashMap<>();
chocolate.put("name", "巧克力");
chocolate.put("description", "好吃的巧克力");
chocolate.put("image", R.drawable.chocolate);
productData.add(chocolate);
// 创建薯片商品数据
Map<String, Object> chips = new HashMap<>();
chips.put("name", "薯片");
chips.put("description", "薯片真好吃");
chips.put("image", R.drawable.chips);
productData.add(chips);
// 创建饼干商品数据
Map<String, Object> cookies = new HashMap<>();
cookies.put("name", "曲奇");
cookies.put("description", "哪里有曲奇");
cookies.put("image", R.drawable.cookies);
productData.add(cookies);
// 可以继续添加更多商品数据...
return productData;
}
}
2. ProductAdapter适配器代码:
package com.example.test03.AllAdapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.test03.R;
import java.util.List;
import java.util.Map;
public class ProductAdapter extends BaseAdapter {
private Context context;
private List<Map<String, Object>> productData;
private LayoutInflater inflater;
//初始化
public ProductAdapter(Context context, List<Map<String, Object>> productData) {
this.context = context;
this.productData = productData;
this.inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
//获取数量
return productData.size();
}
@Override
public Object getItem(int position) {
//获取对象
return productData.get(position);
}
@Override
public long getItemId(int position) {
//获取Item模板
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//position是选中的ViewList中list的列中的索引
//convertView是用于展示在页面中空白item,最后需要返回一个已填充的convertView返回
//定义一个ViewHolder类
ViewHolder holder;
if (convertView == null) {
//根据获取的item创建一个视图
convertView = inflater.inflate(R.layout.item_commodity, parent, false);
//绑定item中的控件到ViewHolder身上
holder = new ViewHolder();
holder.productName = convertView.findViewById(R.id.productName);
holder.productDescription = convertView.findViewById(R.id.productDescription);
holder.productImage = convertView.findViewById(R.id.productImage);
convertView.setTag(holder);
} else {
//如果已经存在视图
holder = (ViewHolder) convertView.getTag();
}
//根据点击获取的list索引寻找对应的Map
Map<String, Object> product = productData.get(position);
//根据Map中的信息,以键找值的形式一一赋值給每一个控件,以做到对控件的数据的填充
holder.productName.setText((String) product.get("name"));
holder.productDescription.setText((String) product.get("description"));
int imageResId = (int) product.get("image"); // 图片资源ID是以整型存储的
holder.productImage.setImageResource(imageResId);
return convertView;
}
//定义ViewHolder,将item中所有的控件都列一个变量
private static class ViewHolder {
TextView productName;
TextView productDescription;
ImageView productImage;
}
}
3.item_commodity模板界面:
<?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"
android:orientation="horizontal"
android:padding="10dp">
<ImageView
android:id="@+id/productImage"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@drawable/ic_launcher_foreground" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:gravity="center_vertical">
<TextView
android:id="@+id/productName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="商品名"
android:textSize="18sp"
android:textColor="@android:color/black" />
<TextView
android:id="@+id/productDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="描述"
android:textSize="14sp"
android:textColor="@android:color/darker_gray" />
</LinearLayout>
</LinearLayout>
四、结语
本账号共为介绍适配器写了4篇文章(包括本文在内),相信你看完这几篇文章,你基本学会了适配器90%的使用了。其余三篇文章链接如下:
Android基础的ListView适配器SimpleAdapter的使用方法,附带可修改模板https://blog.youkuaiyun.com/rawmeat/article/details/144249899?sharetype=blogdetail&sharerId=144249899&sharerefer=PC&sharesource=rawmeat&spm=1011.2480.3001.8118Android中在自定义适配器中使用多个item展示在ListView中,附带代码实现、框架模板
https://blog.youkuaiyun.com/rawmeat/article/details/144284315?spm=1001.2014.3001.5501Android中在适配器中item部分进行监听,并且时时刷新,商品购买为案例
https://blog.youkuaiyun.com/rawmeat/article/details/144305330?spm=1001.2014.3001.5501
本篇文章的分享就到这里了,制作不易,觉得实用的就点个收藏吧!