可支持快速搜索筛选的Android自定义选择控件

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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-07-29 19:03:14

可支持快速搜索筛选的Android自定义选择控件的相关文章

Android自定义组合控件之自定义下拉刷新和左滑删除实例代码_Android

绪论 最近项目里面用到了下拉刷新和左滑删除,网上找了找并没有可以用的,有比较好的左滑删除,但是并没有和下拉刷新上拉加载结合到一起,要不就是一些比较水的结合,并不能在项目里面使用,小编一着急自己组合了一个,做完了和QQ的对比了一下,并没有太大区别,今天分享给大家,其实并不难,但是不知道为什么网上没有比较好的Demo,当你的项目真的很急的时候,又没有比较好的Demo,那么"那条友谊的小船儿真是说翻就翻啊",好了,下面先来具体看一下实现后的效果吧:   代码已经上传到Github上了,小伙伴

Android 自定义Button控件实现按钮点击变色_Android

效果图如下所示: 一.shape 样式:(在drawable新建-->new-->Drawable resource file 在父级标签selector添加Item ) <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item and

Android自定义View控件实现刷新效果_Android

三种得到LinearInflater的方法 a. LayoutInflater inflater = getLayoutInflater(); b. LayoutInflater localinflater = (LayoutInflater)context.getSystemService (Context.LAYOUT_INFLATER_SERVICE); c. LayoutInflater inflater = LayoutInflater.from(context); onDraw 方法

Android 自定义Button控件实现按钮点击变色

效果图如下所示: 一.shape 样式:(在drawable新建-->new-->Drawable resource file 在父级标签selector添加Item ) <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item and

Android自定义View控件实现刷新效果

三种得到LinearInflater的方法 a. LayoutInflater inflater = getLayoutInflater(); b. LayoutInflater localinflater = (LayoutInflater)context.getSystemService (Context.LAYOUT_INFLATER_SERVICE); c. LayoutInflater inflater = LayoutInflater.from(context); onDraw 方法

Android自定义日历控件实例详解_Android

为什么要自定义控件 有时,原生控件不能满足我们对于外观和功能的需求,这时候可以自定义控件来定制外观或功能:有时,原生控件可以通过复杂的编码实现想要的功能,这时候可以自定义控件来提高代码的可复用性. 如何自定义控件 下面我通过我在github上开源的Android-CalendarView项目为例,来介绍一下自定义控件的方法.该项目中自定义的控件类名是CalendarView.这个自定义控件覆盖了一些自定义控件时常需要重写的一些方法. 构造函数 为了支持本控件既能使用xml布局文件声明,也可在ja

Android自定义表格控件满足人们对视觉的需求_Android

Android平台已经给我们提供了很多标准的组件,如:TextView.EditView.Button.ImageView.Menu等,还有许多布局控件,常见的有:AbsoluteLayout.LinerLayout.RelativeLayout.TableLayout等.但随着人们对视觉的需求,基本组件已无法满足人们求新求异的要求,于是我们常常会自定义组件,用来实现更美观的UI界面. 实现自定义控件通常有两种途径,一种是继承View类,重写其中的重要方法,另一种是继承ViewGroup类,通过

android自定义倒计时控件示例_Android

自定义TextView控件TimeTextView代码: 复制代码 代码如下: import android.content.Context;import android.content.res.TypedArray;import android.graphics.Paint;import android.text.Html;import android.util.AttributeSet;import android.widget.TextView; import com.new0315.R;

Android自定义日历控件实例详解

为什么要自定义控件 有时,原生控件不能满足我们对于外观和功能的需求,这时候可以自定义控件来定制外观或功能:有时,原生控件可以通过复杂的编码实现想要的功能,这时候可以自定义控件来提高代码的可复用性. 如何自定义控件 下面我通过我在github上开源的Android-CalendarView项目为例,来介绍一下自定义控件的方法.该项目中自定义的控件类名是CalendarView.这个自定义控件覆盖了一些自定义控件时常需要重写的一些方法. 构造函数 为了支持本控件既能使用xml布局文件声明,也可在ja