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;
相关推荐
雨白5 分钟前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹2 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空3 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭4 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日5 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安5 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑5 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟9 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡10 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0010 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体