可支持快速搜索筛选的Android自定义选择控件
程序员文章站
2023-08-25 13:11:16
android 自定义支持快速搜索筛选的选择控件使用方法,具体如下
项目中遇到选择控件选项过多,需要快速查找匹配的情况。
做了简单的demo,效果图如下:
源码地址...
android 自定义支持快速搜索筛选的选择控件使用方法,具体如下
项目中遇到选择控件选项过多,需要快速查找匹配的情况。
做了简单的demo,效果图如下:
源码地址:https://github.com/whieenz/searchselect
这个控件是由dialog+searchview+listview实现的。dialog用来承载选择控件,searchview实现输入,listview展示结果。设计概要图如下:
一、自定义dialog
dialog布局文件
<?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" android:orientation="vertical"> <linearlayout android:layout_width="wrap_content" android:layout_weight="1" android:background="@drawable/dialog_bg" android:layout_height="match_parent" android:orientation="vertical" > <relativelayout android:layout_width="match_parent" android:layout_height="50dp"> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="20dp" android:layout_centervertical="true" android:textsize="18sp" android:textcolor="#000000" android:id="@+id/tv_dialog_select_title"/> <imagebutton android:layout_width="50dp" android:layout_height="match_parent" android:padding="8dp" android:layout_marginright="10dp" android:layout_centervertical="true" android:layout_alignparentright="true" android:scaletype="centerinside" android:background="@color/transparent" android:src="@drawable/im_search_back" android:id="@+id/btn_dialog_select_search"/> </relativelayout> <com.whieenz.searchselect.dialogsearchview android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/searchview" android:visibility="gone"/> <listview android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical" android:id="@+id/listview" android:layout_gravity="center_horizontal" /> </linearlayout> <linearlayout android:layout_width="match_parent" android:layout_height="80dp" android:gravity="center" android:background="@color/transparent"> <imagebutton android:layout_width="40dp" android:layout_height="40dp" android:id="@+id/imb_dialog_select_close" android:scaletype="centerinside" android:src="@drawable/dialog_close" android:background="@color/transparent"/> </linearlayout> </linearlayout>
dialog java文件
package com.whieenz.searchselect; import android.app.activity; import android.app.dialog; import android.content.context; import android.content.dialoginterface; import android.util.displaymetrics; import android.view.gravity; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.view.window; import android.view.windowmanager; import android.widget.adapterview; import android.widget.imagebutton; import android.widget.listview; import android.widget.textview; import java.util.arraylist; import java.util.list; /** * created by whieenz on 2017/7/18. */ public class serachselectdialog extends dialog { public serachselectdialog(context context, int themeresid) { super(context, themeresid); } /** * 设置 dialog的大小 * @param x 宽比例 * @param y 高比例 */ public void setdialogwindowattr(double x, double y, activity activity){ if (x<0||x>1||y<0||y>1){ return; } window window = this.getwindow(); windowmanager.layoutparams lp = window.getattributes(); windowmanager manager = activity.getwindowmanager(); displaymetrics outmetrics = new displaymetrics(); manager.getdefaultdisplay().getmetrics(outmetrics); int width = outmetrics.widthpixels; int height = outmetrics.heightpixels; lp.gravity = gravity.center; lp.width = (int) (width * x); lp.height = (int) (height * y); this.getwindow().setattributes(lp); } public static class builder { private string title; private view contentview; private string positivebuttontext; private string negativebuttontext; private string singlebuttontext; private list<string> listdata; private view.onclicklistener positivebuttonclicklistener; private view.onclicklistener negativebuttonclicklistener; private view.onclicklistener singlebuttonclicklistener; private view layout; private context context; private serachselectdialog dialog; private onselectedlistiner selectedlistiner; listview listview; //searchview searchview ; dialogsearchview searchview; imagebutton searchbtn; imagebutton closebtn; textview titleview; private boolean state = false; public builder(context context) { //这里传入自定义的style,直接影响此dialog的显示效果。style具体实现见style.xml this.context = context; dialog = new serachselectdialog(context,r.style.selectdialog); layoutinflater inflater = (layoutinflater) context.getsystemservice(context.layout_inflater_service); layout = inflater.inflate(r.layout.dialog_select_search, null); listview = (listview)layout.findviewbyid(r.id.listview); //searchview = (searchview) layout.findviewbyid(r.id.searchview); searchview = (dialogsearchview) layout.findviewbyid(r.id.searchview); searchbtn = (imagebutton) layout.findviewbyid(r.id.btn_dialog_select_search); closebtn = (imagebutton) layout.findviewbyid(r.id.imb_dialog_select_close); titleview = (textview) layout.findviewbyid(r.id.tv_dialog_select_title); dialog.addcontentview(layout, new viewgroup.layoutparams(viewgroup.layoutparams.match_parent, viewgroup.layoutparams.wrap_content)); } public builder settitle(string title) { this.title = title; return this; } public builder setcontentview(view v) { this.contentview = v; return this; } public void setlistdata(list<string> listdata) { this.listdata = listdata; } public builder setpositivebutton(string positivebuttontext, view.onclicklistener listener) { this.positivebuttontext = positivebuttontext; this.positivebuttonclicklistener = listener; return this; } public builder setnegativebutton(string negativebuttontext, view.onclicklistener listener) { this.negativebuttontext = negativebuttontext; this.negativebuttonclicklistener = listener; return this; } /** * 单按钮对话框和双按钮对话框的公共部分在这里设置 */ private serachselectdialog create() { titleview.settext(title); final searchselectadapter sa = new searchselectadapter(context,listdata); listview.setadapter(sa); listview.invalidate(); searchbtn.setonclicklistener(new view.onclicklistener() { @override public void onclick(view view) { if (!state){ searchview.setvisibility(view.visible); state = true; }else { searchview.setvisibility(view.gone); state = false; } } }); searchview.setdialogsearchviewlistener(new dialogsearchview.dialogsearchviewlistener() { @override public boolean onquerytextchange(string text) { updatelayout(searchitem(text)); return false; } }); closebtn.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { dialog.dismiss(); } }); dialog.setondismisslistener(new dialoginterface.ondismisslistener() { @override public void ondismiss(dialoginterface dialog) { } }); listview.setonitemclicklistener(new adapterview.onitemclicklistener() { @override public void onitemclick(adapterview<?> parent, view view, int position, long id) { selectedlistiner.onselected(sa.getitem(position)); dialog.dismiss(); } }); dialog.setcontentview(layout); //用户可以点击手机back键取消对话框显示 dialog.setcancelable(true); //用户不能通过点击对话框之外的地方取消对话框显示 dialog.setcanceledontouchoutside(false); return dialog; } public list<string> searchitem(string name) { arraylist<string> msearchlist = new arraylist<string>(); for (int i = 0; i < listdata.size(); i++) { int index = listdata.get(i).indexof(name); // 存在匹配的数据 if (index != -1) { msearchlist.add(listdata.get(i)); } } return msearchlist; } public void updatelayout(list<string> newlist) { final searchselectadapter sa = new searchselectadapter(context,newlist); listview.setadapter(sa); listview.setonitemclicklistener(new adapterview.onitemclicklistener() { @override public void onitemclick(adapterview<?> parent, view view, int position, long id) { selectedlistiner.onselected(sa.getitem(position)); dialog.dismiss(); } }); } public void setselectedlistiner(serachselectdialog.builder.onselectedlistiner selectedlistiner) { this.selectedlistiner = selectedlistiner; } public static abstract class onselectedlistiner{ public abstract void onselected(string string); } public serachselectdialog show() { create(); dialog.show(); return dialog; } } }
二、自定义searchview
searchview 布局文件
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:gravity="center" android:background="#ffffff" android:layout_height="50dp"> <linearlayout android:layout_width="match_parent" android:layout_height="35dp" android:orientation="horizontal" android:gravity="center_vertical" android:layout_marginleft="15dp" android:layout_marginright="15dp" android:background="@drawable/search_layout_bg"> <imagebutton android:layout_width="20dp" android:layout_height="20dp" android:id="@+id/imb_search_search" android:layout_marginleft="15dp" android:scaletype="centerinside" android:src="@drawable/im_search_gray" android:background="#f0f0f0" /> <edittext android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="10dp" android:layout_marginright="15dp" android:id="@+id/et_search_text" android:layout_weight="1" android:lines="1" android:textsize="14sp" android:background="@null" android:hint="请输入搜索内容"/> <imagebutton android:layout_width="35dp" android:layout_height="35dp" android:padding="12.5dp" android:id="@+id/imb_search_clear" android:layout_marginright="20dp" android:src="@drawable/im_x" android:visibility="gone" android:scaletype="centerinside" android:background="#f0f0f0" /> </linearlayout> </linearlayout>
searchview java代码
package com.whieenz.searchselect; import android.content.context; import android.text.editable; import android.text.textwatcher; import android.util.attributeset; import android.view.layoutinflater; import android.view.view; import android.widget.edittext; import android.widget.imageview; import android.widget.linearlayout; /** * created by whieenz on 2017/7/19. */ public class dialogsearchview extends linearlayout implements view.onclicklistener { /** * 输入框 */ private edittext etinput; /** * 删除键 */ private imageview ivdelete; /** * 上下文对象 */ private context mcontext; /** * 搜索回调接口 */ private dialogsearchviewlistener mlistener; /** * 设置搜索回调接口 * * @param listener 监听者 */ public void setdialogsearchviewlistener(dialogsearchviewlistener listener) { mlistener = listener; } public dialogsearchview(context context, attributeset attrs) { super(context, attrs); mcontext = context; layoutinflater.from(context).inflate(r.layout.view_search_layout, this); initviews(); } private void initviews() { etinput = (edittext) findviewbyid(r.id.et_search_text); ivdelete = (imageview) findviewbyid(r.id.imb_search_clear); ivdelete.setonclicklistener(this); etinput.addtextchangedlistener(new editchangedlistener()); etinput.setonclicklistener(this); } private class editchangedlistener implements textwatcher { @override public void beforetextchanged(charsequence charsequence, int i, int i2, int i3) { } @override public void ontextchanged(charsequence charsequence, int i, int i2, int i3) { if (!"".equals(charsequence.tostring())) { ivdelete.setvisibility(visible); //更新autocomplete数据 if (mlistener != null) { mlistener.onquerytextchange(charsequence + ""); } } else { ivdelete.setvisibility(gone); } } @override public void aftertextchanged(editable editable) { } } @override public void onclick(view view) { switch (view.getid()) { case r.id.imb_search_clear: etinput.settext(""); if (mlistener != null) { mlistener.onquerytextchange(""); } ivdelete.setvisibility(gone); break; } } /** * search view回调方法 */ public interface dialogsearchviewlistener { boolean onquerytextchange(string text); } }
自定义listview adapter
listitem 布局文件
<?xml version="1.0" encoding="utf-8"?> <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="50dp" android:paddingleft="10dp" android:paddingtop="15dp" android:paddingbottom="15dp" android:orientation="horizontal"> <textview android:id="@+id/tv_select_info" android:layout_width="match_parent" android:layout_height="match_parent" android:textsize="20sp" android:layout_centerinparent="true" android:gravity="center" android:lines="1"/> </relativelayout>
adapter 文件
package com.whieenz.searchselect; import android.content.context; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.widget.baseadapter; import android.widget.textview; import java.util.list; public class searchselectadapter extends baseadapter { private list<string> datas; private context context; private layoutinflater inflater; public searchselectadapter(context ctx, list<string> datas){ this.context = ctx; this.datas = datas; this.inflater = layoutinflater.from(ctx); } @override public int getcount() { return datas.size(); } @override public string getitem(int i) { return datas.get(i); } @override public long getitemid(int i) { return i; } @override public view getview(int i, view view, viewgroup viewgroup) { viewholder holder = null; if (view == null ) { view = inflater.inflate(r.layout.list_cell_select_single, null); holder = new viewholder(view); view.settag(holder); } else { holder = (viewholder) view.gettag(); } holder.info.settext(datas.get(i)); return view; } static class viewholder { textview info; public viewholder(view view) { info = view.findviewbyid(r.id.tv_select_info); } } }
mainactivity 实现
布局文件
<?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:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp" tools:context="com.whieenz.searchselect.mainactivity"> <linearlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="150dp" android:orientation="horizontal"> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textsize="20sp" android:gravity="left" android:text="选择结果:" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textsize="20sp" android:textcolor="#ff5c5c" android:id="@+id/tv_result" /> </linearlayout> <button android:layout_width="match_parent" android:layout_height="40dp" android:layout_margintop="20dp" android:gravity="center" android:textsize="20sp" android:textcolor="#ffffff" android:background="@drawable/btn_bg" android:text="打开选择器" android:onclick="doselect"/> </linearlayout>
java文件
package com.whieenz.searchselect; import android.support.v7.app.appcompatactivity; import android.os.bundle; import android.view.view; import android.widget.textview; import java.util.arraylist; import java.util.list; public class mainactivity extends appcompatactivity { private list<string> mdatas; private textview textview; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); textview = (textview) findviewbyid(r.id.tv_result); initdata(); } public void doselect(view view){ serachselectdialog.builder alert = new serachselectdialog.builder(this); alert.setlistdata(mdatas); alert.settitle("请选择城市"); alert.setselectedlistiner(new serachselectdialog.builder.onselectedlistiner() { @override public void onselected(string info) { textview.settext(info); } }); serachselectdialog mdialog = alert.show(); //设置dialog 尺寸 mdialog.setdialogwindowattr(0.9,0.9,this); } /** * 初始化数据 */ private void initdata(){ mdatas = new arraylist<>(); string [] citys = {"武汉","北京","上海","深圳","兰州","成都","天津"}; for (int i = 0; i < 10; i++) { for (int j = 0; j < citys.length; j++) { mdatas.add(citys[j]+i); } } } }
其他配置
dialog style(样式)
<style name="selectdialog" parent="@android:style/theme.dialog"> <item name="android:windownotitle">true</item>//无标题 <item name="android:windowbackground">@color/transparent</item> </style>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 微软在线服务中断 云计算产品全中招