Android EditText+ListPopupWindow实现可编辑的下拉列表

Android EditText+ListPopupWindow实现可编辑的下拉列表

📖1. 可编辑的下拉列表

效果图:

✅步骤一:准备视图

EditText视图:

xml 复制代码
 <EditText
                android:id="@+id/edit_text"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="35dp"
                android:layout_marginLeft="0dp"
                android:layout_marginRight="10dp"
                android:background="@drawable/shape_edit2"
                android:inputType="text"
                android:textColor="@color/black"
                android:hint="输入内容"
                android:textSize="16sp" />

shape_edit2形状文件

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 指定了形状内部的填充颜色 -->
    <solid android:color="#ffffff" />
    <!-- 指定了形状轮廓的粗细与颜色 -->
    <stroke
        android:width="1dp"
        android:color="@color/black_gray" />
    <!-- 指定了形状四个圆角的半径 -->
    <corners android:radius="0dp" />
    <!-- 指定了形状四个方向的间距 -->
    <padding
        android:bottom="2dp"
        android:left="2dp"
        android:right="2dp"
        android:top="2dp" />
</shape>

✅步骤二:封装显示方法

java 复制代码
    private ListPopupWindow listPopupWindow;//ListPopupWindow
    private ArrayAdapter<String> adapter;//数组适配
    private List<String> suggestions;//下拉数据列表
    private static final int MAX_VISIBLE_ITEMS = 5;//最大显示数据行

	//显示下拉列表方法
    private void showSuggestions(String query) {
        if (listPopupWindow == null) {
            // 初始化 ListPopupWindow
            listPopupWindow = new ListPopupWindow(getActivity());
            // 初始化适配器
            adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, new ArrayList<>());
            listPopupWindow.setAdapter(adapter);
            listPopupWindow.setAnchorView(edit_text);
            listPopupWindow.setModal(false);
            // 设置下拉列表项点击事件
            listPopupWindow.setOnItemClickListener((parent, view, position, id) -> {
                String selectedItem = adapter.getItem(position);
                if (selectedItem != null) {
                    // 设置编辑框内容为选中项,并将光标移至文本末尾
                    edit_text.setText(selectedItem);
                    edit_text.setSelection(selectedItem.length());
                }
                // 隐藏下拉列表
                listPopupWindow.dismiss();
            });
        }

        // 过滤并设置下拉列表数据
        List<String> filteredSuggestions = new ArrayList<>();
        for (String suggestion : suggestions) {
            if (suggestion.toLowerCase().contains(query.toLowerCase())) {
                filteredSuggestions.add(suggestion);
            }
        }

        // 更新适配器数据
        adapter.clear();
        adapter.addAll(filteredSuggestions);
        
        // 如果过滤后的建议列表不为空,则显示下拉列表
        if (!filteredSuggestions.isEmpty()) {
            // 获取每行的高度
            int itemHeight = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
            // 动态计算ListPopupWindow 的高度,最大高度=MAX_VISIBLE_ITEMS
            int height = Math.min(filteredSuggestions.size(), MAX_VISIBLE_ITEMS) * itemHeight;
            // 设置 ListPopupWindow 的高度
            listPopupWindow.setHeight(height);
            // 显示下拉列表
            listPopupWindow.show();
        } else {
            // 隐藏下拉列表
            listPopupWindow.dismiss();
        }
    }

✅步骤三:获取视图并监听

1.获取输入框

java 复制代码
EditText edit_text = findViewById(R.id.edit_text);//输入框

2.生成下拉数据(这里的数据可换成真实的数据库数据),监听文本变化

java 复制代码
 		//生成数据
		suggestions = new ArrayList<>();
        suggestions.add("item1");
        suggestions.add("item2");
        suggestions.add("item3");
        suggestions.add("item4");
        
        //监听文本变化
        edit_text.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                // No-op
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                showSuggestions(s.toString());//调取显示下拉列表方法
            }

            @Override
            public void afterTextChanged(Editable s) {
                // No-op
            }
        });

至此实现完成。

📖2. 扩展上下箭头

效果图:

✅步骤一:准备上下箭头icon图标

上箭头item_icon_up.xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:width="30dp"
        android:height="30dp"
        android:drawable="@drawable/icon_up_selected" />
</layer-list>

下箭头item_icon_down.xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:width="30dp"
        android:height="30dp"
        android:drawable="@drawable/icon_down_selected" />
</layer-list>

里面的图片可直接再阿里巴巴图标库搜索"上拉"、"下拉"即可

地址:https://www.iconfont.cn/

✅步骤二:drawableRight属性

编辑框添加drawableRight属性,EditText可以添加上下左右图片资源,我们添加右边即可。

xml 复制代码
<EditText
                android:id="@+id/edit_text"
                android:layout_width="0dp"
                android:layout_height="35dp"
                android:layout_marginLeft="0dp"
                android:layout_marginRight="10dp"
                android:layout_weight="1"
                android:background="@drawable/shape_edit2"
                android:drawableRight="@drawable/item_icon_up"
                android:hint="输入停点名/车位号/设备号"
                android:inputType="text"
                android:textColor="@color/black"
                android:textSize="16sp" />

✅步骤三:监听图标点击

java 复制代码
       //监听图标点击
        editText.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                final int DRAWABLE_RIGHT = 2; // 右侧图标的位置

                // 检查触摸事件是否为抬起事件
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    // 检查触摸位置是否在右侧图标范围内
                    if (event.getX() >= (editText.getWidth() - editText.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
                        // 切换图标并处理对应逻辑
                        if (isIconDown) {
                            // 当前图标是 item_icon_down,切换为 item_icon_up
                            editText.setCompoundDrawablesWithIntrinsicBounds(null, null, getResources().getDrawable(R.drawable.item_icon_up), null);
                            // 处理 item_icon_up 的逻辑
                            showSuggestions(editText.getText().toString());
                            if (listPopupWindow != null) listPopupWindow.show();

                        } else {
                            // 当前图标是 item_icon_up,切换为 item_icon_down
                            editText.setCompoundDrawablesWithIntrinsicBounds(null, null, getResources().getDrawable(R.drawable.item_icon_down), null);
                            // 处理 item_icon_down 的逻辑
                            showSuggestions(editText.getText().toString());
                            if (listPopupWindow != null) listPopupWindow.dismiss();
                        }
                        // 切换图标状态
                        isIconDown = !isIconDown;
                        return true;
                    }
                }
                return false;
            }
        });

setCompoundDrawablesWithIntrinsicBounds方法的参数分别是设置左、上、右、下位置。

java 复制代码
setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);

另外定义图标位置的常量如下:

java 复制代码
      // 定义图标位置的常量,分别为左、上、右、下
        final int DRAWABLE_LEFT = 0;
        final int DRAWABLE_TOP = 1;
        final int DRAWABLE_RIGHT = 2;
        final int DRAWABLE_BOTTOM = 3;
相关推荐
秋月霜风1 小时前
mariadb主从配置步骤
android·adb·mariadb
Python私教2 小时前
Python ORM 框架 SQLModel 快速入门教程
android·java·python
编程乐学3 小时前
基于Android Studio 蜜雪冰城(奶茶饮品点餐)—原创
android·gitee·android studio·大作业·安卓课设·奶茶点餐
problc4 小时前
Android中的引用类型:Weak Reference, Soft Reference, Phantom Reference 和 WeakHashMap
android
IH_LZH4 小时前
Broadcast:Android中实现组件及进程间通信
android·java·android studio·broadcast
去看全世界的云4 小时前
【Android】Handler用法及原理解析
android·java
机器之心4 小时前
o1 带火的 CoT 到底行不行?新论文引发了论战
android·人工智能
机器之心5 小时前
从架构、工艺到能效表现,全面了解 LLM 硬件加速,这篇综述就够了
android·人工智能
AntDreamer5 小时前
在实际开发中,如何根据项目需求调整 RecyclerView 的缓存策略?
android·java·缓存·面试·性能优化·kotlin
运维Z叔6 小时前
云安全 | AWS S3存储桶安全设计缺陷分析
android·网络·网络协议·tcp/ip·安全·云计算·aws