Android 自定义支持快速搜索筛选的选择控件(一)
Android 自定义支持快速搜索筛选的选择控件
项目中遇到选择控件选项过多,需要快速查找匹配的情况。
做了简单的Demo,效果图如下:
这个控件是由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>
Android 自定义支持快速搜索筛选的选择控件(一)的更多相关文章
- Android自定义View(CustomCalendar-定制日历控件)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/54020386 本文出自:[openXu的博客] 目录: 1分析 2自定义属性 3onMeas ...
- Android自定义View(三、深入解析控件测量onMeasure)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51490283 本文出自:[openXu的博客] 目录: onMeasure什么时候会被调用 ...
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38140505 自从Gallery被谷歌废弃以后,Google推荐使用ViewPa ...
- Android 自定义View 三板斧之二——组合现有控件
通常情况下,Android实现自定义控件无非三种方式. Ⅰ.继承现有控件,对其控件的功能进行拓展. Ⅱ.将现有控件进行组合,实现功能更加强大控件. Ⅲ.重写View实现全新的控件 上文说过了如何继承现 ...
- Android自定义模糊匹配搜索控件(二)
在项目中遇到一个需要通过某个字的值筛选匹配带出其他信息的需求,在这里将实现思路整理出来. 源码地址:https://github.com/whieenz/SearchSelect 先看效果图 上图中的 ...
- Android自定义View(RollWeekView-炫酷的星期日期选择控件)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/53420889 本文出自:[openXu的博客] 目录: 1分析 2定义控件布局 3定义Cus ...
- 用c/c++混合编程方式为ios/android实现一个自绘日期选择控件(一)
本文为原创,如有转载,请注明出处:http://www.cnblogs.com/jackybu 前言 章节: 1.需求描述以及c/c++实现日期和月历的基本操作 2.ios实现自绘日期选择控件 3.a ...
- SNF开发平台WinForm之三-开发-单表选择控件创建-SNF快速开发平台3.3-Spring.Net.Framework
3.1运行效果: 3.2开发实现: 3.2.1 这个开发与第一个开发操作步骤是一致的,不同之处就是在生成完代码之后,留下如下圈红程序,其它删除. 第一个开发地址:开发-单表表格编辑管理页面 http: ...
- 通用数据水平层级选择控件v0.70升级版使其支持jQuery v1.9.1
升级原因:作者原来脚本支持的jquery版本太低了,查找了下资料,使得它能支持最新版本的jquery 备注说明:脚本代码源作者跟源文出处很难找,只能在此特感谢他的分享. 更新部分: 1.新版本不再支持 ...
随机推荐
- Vim 游戏 2048
给大家介绍一款可以在Vim里面玩的游戏 vim2048. 界面如图: 操作非常简单,可以用 hjkl 或者 上下左右方向键移动 项目开源地址为: https://github.com/wsdjeg/v ...
- LeetCode & Q219-Contains Duplicate II
Array Hash Table Description: Given an array of integers and an integer k, find out whether there ar ...
- Jenkins 安装、配置与项目新建及构建
1.Jenkins的安装与配置 1.1 java环境配置 Jenkins基于Java, Linux下安装java只要配置java环境变量即可. 首先,解压java到相应目录,我一般习惯把安装的软件放到 ...
- jQuery兼容浏览器IE8方法
在维护公司网站的时候,发现在IE8下jquery会报对象不支持此属性或方法.缺少对象的错误: 在其他浏览器就可以正常运行,当前使用的jquery版本是3.1.1,查资料发现jquery从2.0开始不 ...
- restful架构风格设计准则(一)以资源为中心、自描述的请求响应、资源状态迁移为粒度
读书笔记,原文链接:http://www.cnblogs.com/loveis715/p/4669091.html,感谢作者! 一.需求描述 当用户在某个电子商务网站购物时,他首先查看要购买的商品分类 ...
- hadoop2.7.3+spark2.1.0+scala2.12.1环境搭建(2)安装hadoop
一.依赖安装 安装JDK 二.文件准备 hadoop-2.7.3.tar.gz 2.2 下载地址 http://hadoop.apache.org/releases.html 三.工具准备 3.1 X ...
- [转]安卓新一代多渠道打包工具Walle 解决渠道包V2签名问题
转自https://www.jianshu.com/p/572b59829a08 为什么要打多个渠道的包? 大家都知道,android应用商店大大小小有几百个,作为一个有志向的app,就需要做到统计各 ...
- 框架学习笔记之Hibernate
一.什么是Hibernate Hibernate框架是当今主流的持久层框架之一,该框架是基于JDBC的主流持久化框架,使用它之后能够大大简化程序DAO层的代码量,提高工作效率,因此受广大开发人员的喜爱 ...
- Linux服务器SSH无法通过DSA证书登录的解决方法
从openssh7.0开始,ssh-dss密钥被默认禁用. 修改服务器端的openssh设置重新开启 # vim /etc/sshd/sshd_config添加以下选项PubkeyAcceptedKe ...
- python2.7-巡风源码阅读
推荐个脚本示例网站:https://www.programcreek.com/python/example/404/thread.start_new_thread,里面可以搜索函数在代码中的写法,只有 ...