You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android双Spinner联动实现:基于Assets本地JSON数据

嘿,作为Android开发新手能想到用本地JSON来存联动数据,这个思路真的不错!我来帮你一步步搞定这个双向联动的Spinner功能,从JSON文件准备到代码实现全给你捋明白~

第一步:准备Assets中的JSON数据

首先咱们得确定JSON的结构,因为要实现双向联动,推荐用键值对关联的结构,比如一个Spinner是分类、另一个是对应子项,示例JSON如下(你可以根据自己的需求修改):

{
  "fruits": ["Apple", "Banana", "Orange"],
  "vegetables": ["Carrot", "Potato", "Tomato"],
  "grains": ["Rice", "Wheat", "Corn"]
}

把这个文件命名为spinner_data.json,放到项目的src/main/assets文件夹里(如果没有这个文件夹,右键main目录 → New → Folder → Assets Folder 创建即可)。

第二步:读取并解析Assets里的JSON

接下来咱们要写代码从Assets中读取JSON文件,然后解析成能被Spinner使用的数据结构。在你的Activity里添加以下代码:

首先是读取Assets文件的工具方法:

private String loadJSONFromAsset() {
    String json = null;
    try {
        InputStream is = getAssets().open("spinner_data.json");
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        json = new String(buffer, StandardCharsets.UTF_8);
    } catch (IOException ex) {
        ex.printStackTrace();
        return null;
    }
    return json;
}

然后在onCreate方法里解析JSON,存储联动数据:

// 定义全局变量存储联动映射和父选项列表
private Map<String, List<String>> spinnerMap;
private List<String> parentOptions;
// 用于反向联动的子项到父项的映射
private Map<String, String> childToParentMap;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main); // 替换成你的布局文件名

    // 加载并解析JSON数据
    String jsonStr = loadJSONFromAsset();
    if (jsonStr != null) {
        try {
            JSONObject jsonObject = new JSONObject(jsonStr);
            spinnerMap = new HashMap<>();
            parentOptions = new ArrayList<>();
            childToParentMap = new HashMap<>();

            // 遍历JSON的键,作为父Spinner的选项
            Iterator<String> keys = jsonObject.keys();
            while (keys.hasNext()) {
                String parentKey = keys.next();
                parentOptions.add(parentKey);
                
                // 解析对应子项列表
                JSONArray childArray = jsonObject.getJSONArray(parentKey);
                List<String> childList = new ArrayList<>();
                for (int i = 0; i < childArray.length(); i++) {
                    String childItem = childArray.getString(i);
                    childList.add(childItem);
                    // 同时建立子项到父项的映射,用于反向联动
                    childToParentMap.put(childItem, parentKey);
                }
                spinnerMap.put(parentKey, childList);
            }
        } catch (JSONException e) {
            e.printStackTrace();
            Toast.makeText(this, "JSON解析失败", Toast.LENGTH_SHORT).show();
        }
    } else {
        Toast.makeText(this, "加载JSON文件失败", Toast.LENGTH_SHORT).show();
    }

    // 初始化Spinner并设置联动逻辑
    initSpinners();
}
第三步:布局文件准备

在你的布局XML里添加两个Spinner控件(比如activity_main.xml):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <Spinner
        android:id="@+id/spinner_first"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:hint="请选择第一个选项"/>

    <Spinner
        android:id="@+id/spinner_second"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请选择第二个选项"/>

</LinearLayout>
第四步:实现Spinner双向联动逻辑

添加initSpinners()方法,完成Spinner的初始化和联动监听:

private void initSpinners() {
    Spinner spinnerFirst = findViewById(R.id.spinner_first);
    Spinner spinnerSecond = findViewById(R.id.spinner_second);

    // 初始化第一个Spinner的适配器
    ArrayAdapter<String> firstAdapter = new ArrayAdapter<>(this,
            android.R.layout.simple_spinner_item, parentOptions);
    firstAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinnerFirst.setAdapter(firstAdapter);

    // 第一个Spinner选中事件:联动第二个Spinner
    spinnerFirst.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            String selectedParent = parentOptions.get(position);
            List<String> childOptions = spinnerMap.get(selectedParent);
            
            // 更新第二个Spinner的适配器
            ArrayAdapter<String> secondAdapter = new ArrayAdapter<>(MainActivity.this,
                    android.R.layout.simple_spinner_item, childOptions);
            secondAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spinnerSecond.setAdapter(secondAdapter);
        }

        @Override
        public void onNothingSelected(AdapterView<?> parentView) {
            // 可选:未选中时的处理逻辑
        }
    });

    // 第二个Spinner选中事件:反向联动第一个Spinner
    spinnerSecond.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            if (spinnerSecond.getAdapter() != null) {
                String selectedChild = spinnerSecond.getSelectedItem().toString();
                String parentItem = childToParentMap.get(selectedChild);
                // 找到第一个Spinner中对应父项的位置并选中
                int parentPosition = parentOptions.indexOf(parentItem);
                spinnerFirst.setSelection(parentPosition);
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parentView) {
            // 可选:未选中时的处理逻辑
        }
    });

    // 默认选中第一个父项,初始化第二个Spinner
    if (!parentOptions.isEmpty()) {
        spinnerFirst.setSelection(0);
    }
}
一些关键注意事项
  • JSON格式校验:一定要确保你的JSON文件语法正确,比如引号、逗号没有遗漏,否则会解析失败,可以用在线JSON校验工具检查。
  • 空值处理:代码里已经加了JSON加载失败、解析失败的Toast提示,避免出现空指针异常。
  • 适配自定义布局:如果你不想用系统默认的Spinner样式,可以自定义simple_spinner_item的布局文件替换进去。

内容的提问来源于stack exchange,提问作者Vibhanshu Tyagi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:05:22