Android 自定义弹窗 附带搜索过滤功能

news2024/11/23 7:31:28

项目场景:

前两天要求在项目中添加个小功能,今天正好有时间随手写了一个小demo,过程分享给大家。以后如果有此类需求可直接移植使用。
需求是因为在下拉列表中选择一个项作为数据显示在界面上,但是所有的选项很多,下翻找很麻烦所有需要用个搜索框解决一下这个问题,下面是Demo的效果,可以先看一下。Demo做的比较简单,但是扩展性很大,需要的小伙伴可以自行改造使用,源码放在了文章的最后。

在这里插入图片描述


问题描述

开发前有个问题就是想用现成已有的东西放进去直接就能用了,也没有做自定义列表的东西,后面发现ListView的过滤功能不是很友好,它的过滤方式智能对数据的第一个字符进行过滤,如果是中间出现的字符它就会过滤不出来,所以又重写了适配器并且重写了它的过滤方法,最后满足了功能要求。

public Cursor swapCursor(Cursor newCursor) {
        if (newCursor == mCursor) {
            return null;
        }
        Cursor oldCursor = mCursor;
        if (oldCursor != null) {
            if (mChangeObserver != null) oldCursor.unregisterContentObserver(mChangeObserver);
            if (mDataSetObserver != null) oldCursor.unregisterDataSetObserver(mDataSetObserver);
        }
        mCursor = newCursor;
        if (newCursor != null) {
            if (mChangeObserver != null) newCursor.registerContentObserver(mChangeObserver);
            if (mDataSetObserver != null) newCursor.registerDataSetObserver(mDataSetObserver);
            mRowIDColumn = newCursor.getColumnIndexOrThrow("_id");
            mDataValid = true;
            // notify the observers about the new cursor
            notifyDataSetChanged();
        } else {
            mRowIDColumn = -1;
            mDataValid = false;
            // notify the observers about the lack of a data set
            notifyDataSetInvalidated();
        }
        return oldCursor;
    }

源码里面的内容就是只能对列表中数据的第一个字进行过滤,这样并不能完全起到过滤的作用,下面看一下解决方式。


解决方案:

1、先创建要自定义的内容,弹窗自定义内容dialog_searchview.xml、列表自定义内容fragment_recomend_item.xml(列表自定义也可以放其他东西,如图片等)。

dialog_searchview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical">
    <androidx.appcompat.widget.SearchView
        android:id="@+id/sv_search"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        ></androidx.appcompat.widget.SearchView>

    <ListView
        android:id="@+id/lv_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>

</LinearLayout>

fragment_recomend_item.xml

<?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="match_parent">
    <TextView
        android:id="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp"
        android:layout_marginLeft="15dp"
        android:textSize="15sp"
        android:text="123456"
        android:textColor="@color/black"
        android:gravity="center_vertical"></TextView>

</LinearLayout>

2、创建数据Been,并且绑定到适配器。
Recomend.java

package com.example.testdemosearchview;

/**
 * Create by HHCH on 2023/5/23
 */
public class Recomend {
    private String title;

    public Recomend(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

RecomendAdapter.java

public class RecomendAdapter extends BaseAdapter implements Filterable {
    Context context;
    List<Recomend> data; //过滤数据
    List<Recomend> backData;//用来备份原始数据
    MyFilter mFilter ;

    public RecomendAdapter(Context context, List<Recomend> data) {
        this.context = context;
        this.data = data;
        backData = data;
    }

    @Override
    public int getCount() {
        return data.size();
    }

    //获取当前数据
    @Override
    public Object getItem(int i) {
        return data.get(i).getTitle();
    }

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

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        if (view ==null){
            view = LayoutInflater.from(context).inflate(R.layout.fragment_recomend_item,null);
        }
        TextView tv_title = view.findViewById(R.id.tv_title);
        tv_title.setText(data.get(i).getTitle());
        return view;
    }


    //执行setFilterText()方法时  自动执行
    @Override
    public Filter getFilter() {
        if (mFilter ==null){
            mFilter = new MyFilter();
        }
        return mFilter;
    }

    //我们需要定义一个过滤器的类来定义过滤规则
    class MyFilter extends Filter{
        //我们在performFiltering(CharSequence charSequence)这个方法中定义过滤规则
        @Override
        protected FilterResults performFiltering(CharSequence charSequence) {
            FilterResults result = new FilterResults();
            List<Recomend> list ;
            if (TextUtils.isEmpty(charSequence)){//当过滤的关键字为空的时候,我们则显示所有的数据
                list  = backData;
            }else {//否则把符合条件的数据对象添加到集合中
                list = new ArrayList<>();
                for (Recomend recomend:backData){
                    if (recomend.getTitle().contains(charSequence)){
                        Log.d("","performFiltering:"+recomend.toString());
                        list.add(recomend);
                    }

                }
            }
            result.values = list; //将得到的集合保存到FilterResults的value变量中
            result.count = list.size();//将集合的大小保存到FilterResults的count变量中

            return result;
        }
        //在publishResults方法中告诉适配器更新界面
        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
            data = (List<Recomend>)filterResults.values;
            Log.d("","publishResults:"+filterResults.count);
            if (filterResults.count>0){
                notifyDataSetChanged();//通知数据发生了改变
                Log.d("","publishResults:notifyDataSetChanged");
            }else {
                notifyDataSetInvalidated();//通知数据失效
                Log.d("","publishResults:notifyDataSetInvalidated");
            }
        }
    }
}

代码中有注释,大家可以看注释理解。
3、使用弹窗显示内容。
MainActivity.java

public class MainActivity extends AppCompatActivity {

    private String[] dic = new String[]{"框架平房", "框架楼房", "砖混平房", "砖混楼房", "砖混厦房", "砖混安架房", "砖混起脊房", "砖木房", "砖木厦房",
            "砖木安架房", "土木房", "土木厦房", "土木安架房", "混合房", "混合安架房", "土窑洞", "石窑洞", "砖窑洞", "混合窑洞",
            "砖墙彩钢瓦房", "彩钢瓦活动板房", "砖(石)木简易房", "土木简易房", "其他简易房"};
    private List<Recomend> list = new ArrayList<>();
    private RecomendAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        Button btn_open = findViewById(R.id.bt_open);
        //填充数据源
        for (int i = 0; i < dic.length;i++){
            list.add(new Recomend(dic[i]));
        }

        btn_open.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                View customView  = View.inflate(MainActivity.this,R.layout.dialog_searchview,null);
                SearchView searchView = customView.findViewById(R.id.sv_search);
                ListView listView = customView.findViewById(R.id.lv_list);
                listView.setTextFilterEnabled(true);
                searchView.setIconifiedByDefault(false);
                //        设置该SearchView显示搜索图标
                searchView.setSubmitButtonEnabled(true);
                //        设置该SearchView内默认显示的搜索文字
                searchView.setQueryHint("查找");
                builder.setView(customView);
                adapter = new RecomendAdapter(MainActivity.this,list);
                listView.setAdapter(adapter);
                //searchView输入监听
                searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                    @Override
                    public boolean onQueryTextSubmit(String query) {
                        return false;
                    }
                    //输入内容发送改变时执行下面的方法
                    @Override
                    public boolean onQueryTextChange(String newText) {
                        if (TextUtils.isEmpty(newText)){
                            //清除ListView的过滤
                            listView.clearTextFilter();
                        }else {
                            //使用用户输入的内容对ListView的列表项进行过滤
                            listView.setFilterText(newText);
                        }
                        return true;
                    }
                });
                AlertDialog dialog = builder.create();
                listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                        dialog.dismiss();
                        Toast.makeText(MainActivity.this,adapter.getItem(i).toString(),Toast.LENGTH_SHORT).show();
                    }
                });
                dialog.show();
                dialog.setCanceledOnTouchOutside(true);// dialog弹出后,点击界面其他部分dialog消失
            }
        });
    }
}

整体的流程就这样,需要注意的是在使用SearchView的时候,要将数据过滤写在输入内容发生变化的方法onQueryTextChange()下。

附地址:Git地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/559288.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件著作权容易搞吗?

没有代码、材料&#xff0c;只有一个软件名字就能拿证&#xff0c;你说容易不… 当然这是对我们软著一级代理来说&#xff0c;每年申请下证几千个软著。下面说说下证要点给大家避坑。人群覆盖高新企业、大学生、大学老师、互联网公司。 软件著作权想要轻松下证&#xff0c;必…

《微服务实战》 第十六章 Spring cloud stream应用

前言 https://github.com/spring-cloud/spring-cloud-stream-binder-rabbit 官方定义Spring Cloud Stream是一个构建消息驱动微服务的框架。应用程序通过inputs或者outputs来与Spring Cloud Stream中binder对象交互。通过我们配置来binding(绑定),而Spring Cloud Stream的bin…

lwIP更新记06:申请 TCP 控制块(tcp_alloc)

从 lwIP-2.0.0 开始&#xff0c;申请 tcp_pcb 控制块的逻辑发生了变化。 每个 tcp 连接都必须有一个 PCB 控制块 &#xff0c;使用函数 tcp_new() 申请 PCB 控制块。tcp_new 函数代码如下所示&#xff1a; /*** Creates a new TCP protocol control block but doesnt place it…

进阶篇丨链路追踪(Tracing)很简单:常见问题排查

作者&#xff1a;涯海 经过前面多篇内容的学习&#xff0c;想必大部分同学都已经熟练掌握分布式链路追踪的基础用法&#xff0c;比如回溯链路请求轨迹&#xff0c;定位耗时瓶颈点&#xff1b;配置核心接口黄金三指标告警&#xff0c;第一时间发现流量异常&#xff1b;大促前梳…

公司刚来的测试,00后真卷,上班还没2年,跳到我们公司起薪20k....

都说00后躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。 这不&#xff0c;前段时间我们公司来了个00后&#xff0c;工作都没两年&#xff0c;跳槽到我们公司起薪18K&#xff0c;都快接近我了。后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了…

neo4j图形数据库

目录 1. neo4j简介1.1 什么是图形数据库1.2 什么是neo4j1.3 neo4j的特性1.4neo4j的优点1.5 neo4j的构建元素 2. 安装部署2.1 环境说明2.2 下载安装包2.3 解压安装包2.4 配置安装jdk环境2.5 配置neoj4全局变量2.6 修改neo4j配置文件2.7 服务基本操作2.8 测试访问 3. 使用DBeaver…

上门洗车小程序软件开发所需要的功能有哪些呢?

相信很多企业及投资者都想开发一款属于自己的小程序系统。那么一款专业好用的上门洗车小程序软件开发所需要的功能有哪些呢&#xff1f; 1. 用户注册与登录。 用户可以通过手机号码或微信账号进行注册和登录。注册后可以查看历史订单、评价技师、参加活动等。 …

浅析EasyCVR视频能力在自然灾害风险预警场景中的应用意义

一、方案背景 我国是自然灾害多发的国家&#xff0c;夏季也是灾害多发季节&#xff0c;山洪、泥石流、洪涝、冰雹、飓风、地震等自然灾害每年都给国家经济带来巨大的损失。建设自然灾害风险预警视频监控系统&#xff0c;实现对自然灾害的可视化预警监测和监管&#xff0c;并提…

分布式事务的21种武器 - 2

在分布式系统中&#xff0c;事务的处理分布在不同组件、服务中&#xff0c;因此分布式事务的ACID保障面临着一些特殊难点。本系列文章介绍了21种分布式事务设计模式&#xff0c;并分析其实现原理和优缺点&#xff0c;在面对具体分布式事务问题时&#xff0c;可以选择合适的模式…

【业务架构】业务驱动的推荐系统相关技术总结

什么是推荐系统 推荐系统是一种基于用户历史行为和属性信息为用户推荐个性化内容的技术。而业务驱动的推荐系统&#xff0c;是指根据业务需求&#xff0c;将推荐系统集成进业务流程中&#xff0c;通过推荐系统提高业务效率、提升用户体验等目的。以下是一些相关实现技术。 用户…

Vue--》Vue3打造可扩展的项目管理系统后台的完整指南(一)

今天开始使用 vue3 ts 搭建一个项目管理的后台&#xff0c;因为文章会将项目的每一个地方代码的书写都会讲解到&#xff0c;所以本项目会分成好几篇文章进行讲解&#xff0c;我会在最后一篇文章中会将项目代码开源到我的GithHub上&#xff0c;大家可以自行去进行下载运行&…

C语言隐藏自己源码成lib静态库的和使用lib静态库的方法

首先从头开始创建一个新项目&#xff1a; 这个sub.c内的文件内容很简单&#xff0c;就写一个减法函数 // 定义一个减法函数&#xff0c;传入两个整数&#xff0c;返回差 int sub(int x, int y) { return x - y; } // 定义一个减法函数&#xff0c;传入两个整数&#xff0…

7. 数据库MySQL

本文介绍了数据库mysql的安装配置过程&#xff0c;以及通过VsCode调用数据库实现一些功能 一、安装 如果之前安装过&#xff0c;或者安装失败。清除MySQL缓存并重新安装&#xff1a;运行以下命令以清除所有MySQL缓存文件&#xff0c;并重新安装它们 sudo apt-get remove --pu…

JAVA基础(各种类)

Object类 1、Object类中有许多方法是用native修饰的&#xff0c;这些方法是本地方法&#xff0c;用C语言实现。 2、Object类的一些方法&#xff1a; clone()方法&#xff1a;需要继承Clonable接口&#xff0c;并覆写clone()&#xff0c;修改为public权限&#xff0c;原来为p…

Halcon中从两组点的对应关系生成仿射矩阵,及思考原理和代码实现

有几个算子有点类似&#xff0c;看了下区别 1.vector_to_rigid( : : Px, Py, Qx, Qy : HomMat2D) 2.vector_to_similarity( : : Px, Py, Qx, Qy : HomMat2D) 3.vector_to_aniso( : : Px, Py, Qx, Qy : HomMat2D) vector_to_rigid 这个是刚性变换&#xff0c; 只有旋转和平移…

参考企业微信日程 通过vue+elementUi编写一个按月统计会议的日程计划组件

这个组件的话 需要三个第三方依赖 npm install --save chinese-lunar-calendar sass sass-loader element-uisass因为我这里 还是习惯写sass样式 毕竟真的方便啊 chinese-lunar-calendar 是一款将日期转为农历的工具 element-ui主要是表格真的方便 在 项目src下的main.js入口…

如何学好人工智能?

“在主流的视频直播教学之外&#xff0c;直接与老师在课件上互动能够更快地让我进入学习状态。” 大家的时间都很宝贵&#xff0c;当我们好不容易下定决心要学习一门新知识时&#xff0c;各种影响学习的噪声会在本不富裕的耐心上大打折扣&#xff0c;万事开头难变成了真理。特别…

[技术分享]Android平台实时音视频录像模块设计之道

实现背景 录像有什么难的&#xff1f;无非就是数据过来&#xff0c;编码保存mp4而已&#xff0c;这可能是好多开发者在做录像模块的时候的思考输出。是的&#xff0c;确实不难&#xff0c;但是做好&#xff0c;或者和其他模块有非常好的逻辑配合&#xff0c;确实不容易。 好多…

考研复试第十六天:合并果子 【哈佛曼树】

前置知识 哈佛曼树&#xff1a;我们先来复习一下啥叫做哈佛曼树 1.背景 我们有下面这样一个字符串需要编码&#xff0c;就是将下面的字符转为二进制。我们采用的方法是前缀编码&#xff0c;用一颗树的叶节点来放字符。 2.前缀编码 编码是咋样的呢&#xff1f;看下面这个例子…

BurpSuite—Project options模块(项目选择)

本文主要BurpSuite—Project options模块(项目选择)介绍的相关内容 关于BurpSuite的安装可以看一下之前这篇文章&#xff1a; http://t.csdn.cn/cavWt 一、简介 Project options主要用来对Project的一些设置。 二、模块说明 Project options主要由五个模块组成: 1.Connect…