AutoCompleteTextView,很多人都用过,有些情况下使用Google提供的ArrayAdapter作为适配器就可以完成需求,但是在实际开发中,我们经常需要开发自定义适配器来完成开发工作。


今天就来看看怎么自定义这样一个AutoCompleteTextView。

假设我们有一个Book类,Book有四个属性,id,name,author,price,pinyin,我希望在AutoCompleteTextView中无论输入什么字符,都和这五个属性进行匹配,只要有一个匹配上就将该项数据显示出来。要实现的效果如下图:


要实现这样一个功能的重点在于重写Adapter,我们自定义一个Adapter继承自BaseAdapter,同时实现过滤器Filterable。

继承BaseAdapter很好写,我们经常在ListView中使用,这里还是一样的。

继承BaseAdapter主要实现下面四个方法,books是从构造方法中传进来的数据源。

@Override
public int getCount() {
return books.size();
} @Override
public Object getItem(int position) {
return books.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
// convertView = LayoutInflater.from(context).inflate(
// R.layout.act_item, null);
convertView = View.inflate(context, R.layout.act_item, null);
viewHolder.id = (TextView) convertView.findViewById(R.id.id_book);
viewHolder.name = (TextView) convertView
.findViewById(R.id.name_book);
viewHolder.author = (TextView) convertView
.findViewById(R.id.author_book);
viewHolder.price = (TextView) convertView
.findViewById(R.id.price_book);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
Book book = books.get(position);
viewHolder.id.setText(book.getId() + "");
viewHolder.name.setText(book.getName());
viewHolder.author.setText(book.getAuthor());
viewHolder.price.setText(book.getPrice()+"");
return convertView;
} class ViewHolder {
TextView id, name, author, price;
}

act_item布局文件是这样的:

<?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="horizontal" > <TextView
android:id="@+id/id_book"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:gravity="center"
android:text="id" /> <TextView
android:id="@+id/name_book"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:gravity="center"
android:text="name" /> <TextView
android:id="@+id/author_book"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:gravity="center"
android:text="author" /> <TextView
android:id="@+id/price_book"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:gravity="center"
android:text="price" /> </LinearLayout>

同时,由于我们实现了Filterable接口,所以还要实现该接口里边的一个方法:

    @Override
public Filter getFilter() {
if(mArrayFilter==null){
mArrayFilter = new ArrayFilter();
}
return mArrayFilter;
}
ArrayFilter是我们实现数据过滤的一个关键类,该类继承自Filter,实现其中的两个方法,第一方法时数据的过滤逻辑,第二个方法是把过滤结果赋值给数据源。
    private class ArrayFilter extends Filter {

        @Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (mFilterBooks == null) {
mFilterBooks = new ArrayList<Book>(books);
}
//如果没有过滤条件则不过滤
if (constraint == null || constraint.length() == 0) {
results.values = mFilterBooks;
results.count = mFilterBooks.size();
} else {
List<Book> retList = new ArrayList<Book>();
//过滤条件
String str = constraint.toString().toLowerCase();
//循环变量数据源,如果有属性满足过滤条件,则添加到result中
for (Book book : mFilterBooks) {
if (book.getAuthor().contains(str)
|| book.getName().contains(str)
|| (book.getId() + "").contains(str)
|| (book.getPrice() + "").contains(str)||book.getPinyin().contains(str)) {
retList.add(book);
}
}
results.values = retList;
results.count = retList.size();
}
return results;
} //在这里返回过滤结果
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
// notifyDataSetInvalidated(),会重绘控件(还原到初始状态)
// notifyDataSetChanged(),重绘当前可见区域
books = (List<Book>) results.values;
if(results.count>0){
notifyDataSetChanged();
}else{
notifyDataSetInvalidated();
}
} }

最重要的Adapter已经做好了,下来看看在MainActivity中怎么调用吧:

public class MainActivity extends Activity {

    private List<Book> books = new ArrayList<Book>();
private AutoCompleteTextView act; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
} private void initView() {
act = (AutoCompleteTextView) this.findViewById(R.id.myact);
MyActAdapter adapter = new MyActAdapter(books, this);
act.setAdapter(adapter);
act.setThreshold(0);
} private void initData() {
Book b1 = new Book(1, "三国演义", "罗贯中", 38, "sanguoyanyi");
Book b2 = new Book(2, "红楼梦", "曹雪芹", 25, "hongloumeng");
Book b3 = new Book(3, "西游记", "吴承恩", 43, "xiyouji");
Book b4 = new Book(4, "水浒传", "施耐庵", 72, "shuihuzhuan");
Book b5 = new Book(5, "随园诗话", "袁枚", 32, "suiyuanshihua");
Book b6 = new Book(6, "说文解字", "许慎", 14, "shuowenjiezi");
Book b7 = new Book(7, "文心雕龙", "刘勰", 18, "wenxindiaolong");
books.add(b1);
books.add(b2);
books.add(b3);
books.add(b4);
books.add(b5);
books.add(b6);
books.add(b7);
}
}

布局文件:

public class MainActivity extends Activity {

    private List<Book> books = new ArrayList<Book>();
private AutoCompleteTextView act; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
} private void initView() {
act = (AutoCompleteTextView) this.findViewById(R.id.myact);
MyActAdapter adapter = new MyActAdapter(books, this);
act.setAdapter(adapter);
act.setThreshold(0);
} private void initData() {
Book b1 = new Book(1, "三国演义", "罗贯中", 38, "sanguoyanyi");
Book b2 = new Book(2, "红楼梦", "曹雪芹", 25, "hongloumeng");
Book b3 = new Book(3, "西游记", "吴承恩", 43, "xiyouji");
Book b4 = new Book(4, "水浒传", "施耐庵", 72, "shuihuzhuan");
Book b5 = new Book(5, "随园诗话", "袁枚", 32, "suiyuanshihua");
Book b6 = new Book(6, "说文解字", "许慎", 14, "shuowenjiezi");
Book b7 = new Book(7, "文心雕龙", "刘勰", 18, "wenxindiaolong");
books.add(b1);
books.add(b2);
books.add(b3);
books.add(b4);
books.add(b5);
books.add(b6);
books.add(b7);
}
}

好了,就是这么简单,不过这里有一个最大的缺憾就是我们的数据源中本身带有一个pinyin属性,在实际的开发中肯定不能这样,那么我们怎么实现通过汉字首字母来搜索呢?比如输入sg,就会提示“三国演义”。我会在下篇文章中介绍怎么通过Java类来实现这么一个功能。


版权声明:本文为博主原创文章,未经博主允许不得转载。若有错误地方,还望批评指正,不胜感激。

android开发之自定义AutoCompleteTextView的更多相关文章

  1. android开发之自定义组件

    android开发之自定义组件 一:自定义组件: 我认为,自定义组件就是android给我们提供的的一个空白的可以编辑的图片,它帮助我们实现的我们想要的界面,也就是通过自定义组件我们可以把我们要登入的 ...

  2. Android开发之自定义的ListView(UITableViewController)

    Android开发中的ListView, 顾名方法思义,就是表视图.表示图在iOS开发中就是TableView.两者虽然名称不一样,但是其使用方法,使用场景以及该控件的功能都极为相似,都是用来展示大量 ...

  3. Android开发之自定义组件和接口回调

    说到自定义控件不得不提的就是接口回调,在Android开发中接口回调用的还是蛮多的.在这篇博客开始的时候呢,我想聊一下iOS的自定义控件.在iOS中自定义控件的思路是继承自UIView, 在UIVie ...

  4. Android开发之自定义局部导航菜单

    如今,要实现导航功能方案有很多.比如: 1.用3.0+自带的Toolbar + Fragment导航. 2.用Tabhost实现导航.小弟学浅,就只用过这两种方案实现导航. 但是这两种方案都有一个很明 ...

  5. Android开发进阶——自定义View的使用及其原理探索

    在Android开发中,系统提供给我们的UI控件是有限的,当我们需要使用一些特殊的控件的时候,只靠系统提供的控件,可能无法达到我们想要的效果,这时,就需要我们自定义一些控件,来完成我们想要的效果了.下 ...

  6. Android开发之自定义圆角矩形图片ImageView的实现

    android中的ImageView只能显示矩形的图片,这样一来不能满足我们其他的需求,比如要显示圆角矩形的图片,这个时候,我们就需要自定义ImageView了,其原理就是首先获取到图片的Bitmap ...

  7. Android开发之自定义圆形的ImageView的实现

    android中的ImageView只能显示矩形的图片,这样一来不能满足我们其他的需求,比如要显示圆形的图片,这个时候,我们就需要自定义ImageView了,其原理就是首先获取到图片的Bitmap,然 ...

  8. Android开发之自定义圆角矩形图片ImageView的实现 - Jamy Cai

    android中的ImageView只能显示矩形的图片,这样一来不能满足我们其他的需求,比如要显示圆角矩形的图片,这个时候,我们就需要自定义ImageView了,其原理就是首先获取到图片的Bitmap ...

  9. Android开发之自定义的ProgressDialog

    package com.example.dialog; import android.app.ProgressDialog; import android.content.Context; /** * ...

随机推荐

  1. IntelliJ IDEA Subversion的使用方式

    接着一直点下一步基本上就可以了

  2. SectionIndexer中的getSectionForPosition()与getPositionForSection()

    大家在做字母索引的时候常常会用到SectionIndexer这个类,里面有2个重要的方法 1.   getSectionForPosition()通过该项的位置,获得所在分类组的索引号 2. getP ...

  3. 用JAVA 查询 Active Directory(AD)

    Required Details LDAP address (For e.g.: myjeeva.com or IP of the Domain Controller/Global Catalog[G ...

  4. Cursor的moveToFirst和moveToNext

    参考: http://blog.csdn.net/kerlw/article/details/6126448 总结: 查询得到的cursor是指向第一条记录之前的,因此查询得到cursor后第一次调用 ...

  5. BZOJ_1015_星球大战_[JSOI2008]_(并查集)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1015 n 个点,被 m 条边相连.进行k次删点操作,问第一次操作前和每次操作后的集合数(直接或 ...

  6. Java 编程下 Eclipse 如何设置单行代码显示的最大宽度

    Eclipse 下一行代码的默认宽度是 80 , 稍长一点的一行代码就会自动换行,代码可读性较差,我们可以自己在 Eclipse 对代码宽度进行设置. 设置路径为:[Window]→[Preferen ...

  7. SharePoint 2010中使用SPListItemCollectionPosition更快的结果

    转:http://www.16kan.com/article/detail/318657.html Introduction介绍 In this article we will explore the ...

  8. DHU-1241 Oil Deposits

    Oil Deposits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  9. 哈希(1) hash的基本知识回顾

    好久没看数据结构了,现在也打不起精神来,翻了一下书,严蔚敏那本书.,以下是书的第9章,发现自己很多时候对知识的认识无法结构化和系统化,都是零散的,模糊的混乱的记忆,以后要有体系, 第9章 查找     ...

  10. Hadoop 配置好hive,第一次在conf能进入,第二次就不行了,怎么办?

    问题描述: 在 Hadoop 配置好 hive 数据仓库,在conf目录下通过hive命令进入hive数据仓库,非常顺利.  但关闭终端,第二次按这种方式却显示,无次命令. 怎么办? 解决办法: 在h ...