Android studio 之 适配器

  • ListView仅作为容器(列表),用于装载 & 显示数据(即 列表项Item
  • 而容器内的具体数据(列表项Item)则是由 适配器(Adapter)提供

适配器(Adapter):作为View 和 数据之间的桥梁 & 中介,将数据映射到要展示的View

  • 当需显示数据时,ListView会向Adapter取出数据,从而加载显示,具体如下图

数组适配器 ArrayAdapter

适用于列表项只含有文本信息的情况

将数组适配器绑定在对话框上

1.创建一个按钮,并添加点击事件,打开添加了适配器的对话框

复制代码
<Button
    android:id="@+id/adpter_btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"
    android:onClick="popAlert"
    android:text="数组适配器 ArrayAdapter" />

2.创建数组适配器

创建数据源

复制代码
final String[] items= {"java","c++","android","flutter","dart"};

创建适配器中的每一项数据的样式布局

复制代码
<!-- 适配器中每一项数据的样式布局 -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="center_vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:src="@mipmap/star"/>
    <TextView
        android:id="@+id/arry_tx"
        android:text="测试"
        android:layout_marginLeft="15dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

实例化一个数组适配器

  • 参数1 Context:环境上下文

  • 参数2 resource:布局资源索引

  • 参数3 int textViewResourceId:指定数据中文本需要放在布局中的文本控件的id

  • 参数4 objects:数据源

    ArrayAdapter arrayAdapter = new ArrayAdapter(this, R.layout.array_item_layout,R.id.arry_tx,items);

3.在对话框里添加适配器 .setAdapter()

  • 参数1 - ListAdapter 适配器对象(对数据显示样式的规则制定器):The ListAdapter to supply the list of items

  • 参数2 - OnClickListener 监听器 (可给可不给,不给则设为null)

    // 实例化对话框
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    ArrayAdapter arrayAdapter = new ArrayAdapter(this, R.layout.array_item_layout,R.id.arry_tx,items);
    builder.setTitle("请选择")
    /* .setAdapter() 设置适配器
    * 参数1 - ListAdapter 适配器对象(对数据显示样式的规则制定器):The ListAdapter to supply the list of items
    * 参数2 - OnClickListener 监听器 (可给可不给,不给则设为null)*/
    .setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
    @Override
    /int which 当前点击的item索引/
    public void onClick(DialogInterface dialog, int which) {
    Toast.makeText(ButtonActivity.this,items[which],Toast.LENGTH_SHORT).show();
    }
    })
    .show();

简单适配器 SimpleAdapter

即可以处理列表项全是文本的情况,又可以处理列表项包含其他控件(如图片、文本、按钮等)情况

使用步骤

准备数据源

复制代码
private void initData() {
    Map<String,Object> data1 = new HashMap<>();
    data1.put("icon",R.mipmap.star);
    data1.put("name","沈成林");
    data1.put("age",23);

    Map<String,Object> data2 = new HashMap<>();
    data2.put("icon",R.mipmap.star);
    data2.put("name","杨滨溶");
    data2.put("age",23);

    Map<String,Object> data3 = new HashMap<>();
    data3.put("icon",R.mipmap.star);
    data3.put("name","朱一龙");
    data3.put("age",23);

    data.add(data1);
    data.add(data2);
    data.add(data3);
    }

准备布局(适配器每一项数据的显示样式布局)

R.layout.simpleadapeter_item:

复制代码
<?xml version="1.0" encoding="utf-8"?>
<!-- SimpleAdapter 的item样式-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/headIcon"
        android:layout_width="50dp"
        android:layout_height="65dp"
        android:background="@mipmap/study" />

    <TextView
        android:id="@+id/itemName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="28dp"
        android:layout_toEndOf="@+id/headIcon"
        android:text="name"
        android:textSize="26sp" />

    <TextView
        android:id="@+id/itemAge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/itemName"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="13dp"
        android:layout_toRightOf="@id/headIcon"
        android:text="TextView"
        android:textColor="#F44336"
        android:textStyle="bold" />

</RelativeLayout>

实例化一个简单适配器

复制代码
public SimpleAdapter(Context context, List<? extends Map<String, ?>> data, @LayoutRes int resource, String[] from, @IdRes int[] to)
复制代码
参数1:环境上下文
参数2:数据源
参数3:每一项布局(列表项布局)  R.layout.simpleadapeter_item
参数4:数据来源的key数组,一个String数据,对应到Map上的每个<key,value>的key值
参数5:是一个int数组,对应resource列表项布局文件里面每个控件的id,需要与上面String[] from的from相对应
key所指代的数据会在to数组中id所代表的控件上显示出来
复制代码
String[] from = {"icon","name","age"}; // 参数4
int[] to = {R.id.headIcon,R.id.itemName,R.id.itemAge}; // 参数5
SimpleAdapter simpleAdapter = new SimpleAdapter(this,data,R.layout.simpleadapeter_item,from,to);

通过ListView来展示

1.添加ListView控件,xml文件

复制代码
 <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4">
        <ListView
            android:id="@+id/list1"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

2.将ListView控件绑定在 SimpleAdapter 上

复制代码
ListView listView = findViewById(R.id.list1);
listView.setAdapter(simpleAdapter);

3.为listView设置item点击事件

复制代码
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    /*数据源data是一个List<Map<String,Object>>的列表,
     *onItemClick方法,返回的position就是当前点击的 item 的位序,通过它可以拿到item的数据源
     *view 就是点击的item的视图*/
     Map<String,Object> data1 = data.get(position);
     Toast.makeText(ListViewActivity.this,"姓名"+data1.get("name")+",年龄:"+data1.get("age"),Toast.LENGTH_SHORT).show();
                }
            });

基本适配器 BaseAdapter

根据xml文件中定义的样式进行列表项的填充,完全自定义数据适配方式,适用性最强

准备列表项布局 R.layout.baseadapter_item

复制代码
<?xml version="1.0" encoding="utf-8"?>
<!-- 1. BaseAdapter item的样式设计-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <ImageView
        android:id="@+id/base_icon"
        android:src="@mipmap/study"
        android:layout_width="80dp"
        android:layout_margin="5dp"
        android:layout_height="80dp"/>

    <TextView
        android:id="@+id/base_name"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="nickName"
        android:layout_toRightOf="@+id/base_icon"
        android:layout_margin="5dp"
        android:textSize="26sp" />

    <TextView
        android:id="@+id/base_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:layout_alignStart="@+id/base_name"
        android:layout_toRightOf="@+id/base_icon"
        android:layout_below="@+id/base_name"
        android:textSize="22sp"
        android:text="2023-12-4" />

    <TextView
        android:id="@+id/base_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/base_icon"
        android:textSize="26sp"
        android:text="这是内容" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/base_content"
        android:layout_marginTop="20dp"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/base_icon1"
            android:layout_width="40dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:src="@mipmap/star" />

        <ImageView
            android:id="@+id/base_icon2"
            android:layout_width="40dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:src="@mipmap/star" />

        <ImageView
            android:id="@+id/base_icon3"
            android:layout_width="40dp"
            android:layout_height="50dp"
            android:layout_weight="1"
            android:src="@mipmap/star" />
    </LinearLayout>

</RelativeLayout>

准备数据源

准备一个数据对象 BaseMsg类

复制代码
package com.example.androidstudiostudy.data;

// 2.1 准备数据源 - BaseAdapter 的数据源类
public class BaseMsg {
    private int icon;
    private String nickName;
    private String content;

    public int getIcon() {
        return icon;
    }

    public void setIcon(int icon) {
        this.icon = icon;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public boolean isLike() {
        return isLike;
    }

    public void setLike(boolean like) {
        isLike = like;
    }

    private boolean isLike;

    public BaseMsg(int icon, String nickName, String content, boolean isLike) {
        this.icon = icon;
        this.nickName = nickName;
        this.content = content;
        this.isLike = isLike;
    }
}

初始化一个 BaseMsg 列表

复制代码
private List<BaseMsg> lists = new ArrayList<>();  // 定义一个 BaseMsg 对象的列表
private int[] touxiang ={R.mipmap.star,R.mipmap.study,R.mipmap.star,R.mipmap.study,R.mipmap.star,R.mipmap.study,R.mipmap.star,R.mipmap.study,}; // 定义一个int类型的数组,里面存放 图标的id

// 初始化 BaseMsg 对象的列表
public void initBaseListData() {
      for (int i = 0; i < 8; i++) {
         BaseMsg baseMsg = new BaseMsg(touxiang[i], "用户" + (i+1), "这是第" + (i+1) + "段代码", false);
         lists.add(baseMsg);
      }
    }

构建 BaseAdapter 适配器

新建一个继承自 BaseAdapter 的类,在这个类中对每一个item的布局进行设计

要求传入 环境上下文、数据源

复制代码
package com.example.androidstudiostudy;

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 android.widget.Toast;

import com.example.androidstudiostudy.data.BaseMsg;
import java.util.List;

// 新建一个继承自 BaseAdapter 的类
// 根据准备好的数据源和子项布局完成 ListView 效果的一一设置
public class MyBaseAdapter extends BaseAdapter {

    private List<BaseMsg> baseMsgList;
    private Context context;

    // 构造方法
    public MyBaseAdapter(List<BaseMsg> baseMsgList,Context context) {
        this.baseMsgList = baseMsgList;
        this.context = context;
    }

    // 获取数量(设置listView的长度)
    @Override
    public int getCount() {
        return baseMsgList.size();
    }

    @Override
    // 获取视图(设置 listView 每一项的显示效果)
    /* 参数1:当前Item的下标 --- 和数据源的下标相同,可以由此获取数据源配置item
     * 参数2:当前Item的view
     * 参数3:当前视图的父视图(可调整当前视图的宽高)*/
    public View getView(int position, View convertView, ViewGroup parent) {
        // 完成对view的设置
        // 将设置好的 item 布局资源转换成view
        convertView = LayoutInflater.from(context).inflate(R.layout.baseadapter_item,null); // 此时得到的是最初的item布局,没有添加的数据

        // 获取数据源[position] 的数据,并将他们设置到item视图中的控件中
        BaseMsg m = baseMsgList.get(position); // 获取item的数据列表

        ImageView imageView = convertView.findViewById(R.id.base_icon);
        imageView.setImageResource(m.getIcon());

        TextView tN = convertView.findViewById(R.id.base_name);
        tN.setText(m.getNickName());

        TextView tC = convertView.findViewById(R.id.base_content);
        tC.setText(m.getContent());

        // 可以给item的单个控件设置点击事件
        tN.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              //  System.out.printf("点击了"+tN.getText());
                Toast.makeText(context,"你点击了"+m.getNickName(),Toast.LENGTH_SHORT).show();
            }
        });
        return convertView;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }


}

 // 获取视图(设置 listView 每一项的显示效果)
 /* 参数1:当前Item的下标 --- 和数据源的下标相同,可以由此获取数据源配置item
  * 参数2:当前Item的view
  * 参数3:当前视图的父视图(可调整当前视图的宽高)*/
public View getView(int position, View convertView, ViewGroup parent)

实例化 BaseAdapter 适配器

复制代码
BaseAdapter baseAdapter = new MyBaseAdapter(lists,this);

通过ListView展示

复制代码
initBaseListData();
listView.setAdapter(baseAdapter);

动态添加

复制代码
// 动态添加 BaseAdapter 数据源中的数据
public void addData(View view) {
    lists.add(new BaseMsg(R.mipmap.ic_launcher,"新name","这是新增的",false));
    // 通知适配器更新
    baseAdapter.notifyDataSetChanged();
    // 设置listView自动显示到最新的数据
    listView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
}

列表自动滑动到底部 :TRANSCRIPT_MODE_ALWAYS_SCROLL

复制代码
    /**
     * The list will automatically scroll to the bottom, no matter what items
     * are currently visible.
     *
     * @see #setTranscriptMode(int)
     */
// 列表自动滑动到底部
    public static final int TRANSCRIPT_MODE_ALWAYS_SCROLL = 2;
相关推荐
fatiaozhang95272 小时前
中兴云电脑W102D_晶晨S905X2_2+16G_mt7661无线_安卓9.0_线刷固件包
android·adb·电视盒子·魔百盒刷机·魔百盒固件
CYRUS_STUDIO3 小时前
Android APP 热修复原理
android·app·hotfix
鸿蒙布道师3 小时前
鸿蒙NEXT开发通知工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
鸿蒙布道师3 小时前
鸿蒙NEXT开发网络相关工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
大耳猫4 小时前
【解决】Android Gradle Sync 报错 Could not read workspace metadata
android·gradle·android studio
ta叫我小白4 小时前
实现 Android 图片信息获取和 EXIF 坐标解析
android·exif·经纬度
dpxiaolong5 小时前
RK3588平台用v4l工具调试USB摄像头实践(亮度,饱和度,对比度,色相等)
android·windows
xrkhy6 小时前
提交到Gitee仓库
gitee
tangweiguo030519876 小时前
Android 混合开发实战:统一 View 与 Compose 的浅色/深色主题方案
android
老狼孩111226 小时前
2025新版懒人精灵零基础及各板块核心系统视频教程-全分辨率免ROOT自动化开发
android·机器人·自动化·lua·脚本开发·懒人精灵·免root开发