android中AutoCompleteTextView的简单用法(实现搜索历史)
网上有不少教程,那个提示框字符集都是事先写好的,例如用一个string[] 数组去包含了这些数据,但是,我们也可以吧用户输入的作为历史记录保存
下面先上我写的代码:
import android.app.activity; import android.content.sharedpreferences; import android.os.bundle; import android.util.log; import android.view.view; import android.view.view.onclicklistener; import android.view.view.onfocuschangelistener; import android.widget.arrayadapter; import android.widget.autocompletetextview; import android.widget.button; public class read_historyactivity extends activity implements onclicklistener { private autocompletetextview autotv; /** called when the activity is first created. */ @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); autotv = (autocompletetextview) findviewbyid(r.id.autocompletetextview1); initautocomplete("history",autotv); button search = (button) findviewbyid(r.id.button1); search.setonclicklistener(this); } @override public void onclick(view v) { // 这里可以设定:当搜索成功时,才执行保存操作 savehistory("history",autotv); } /** * 初始化autocompletetextview,最多显示5项提示,使 * autocompletetextview在一开始获得焦点时自动提示 * @param field 保存在sharedpreference中的字段名 * @param auto 要操作的autocompletetextview */ private void initautocomplete(string field,autocompletetextview auto) { sharedpreferences sp = getsharedpreferences("network_url", 0); string longhistory = sp.getstring("history", "nothing"); string[] hisarrays = longhistory.split(","); arrayadapter<string> adapter = new arrayadapter<string>(this, android.r.layout.simple_dropdown_item_1line, hisarrays); //只保留最近的50条的记录 if(hisarrays.length > 50){ string[] newarrays = new string[50]; system.arraycopy(hisarrays, 0, newarrays, 0, 50); adapter = new arrayadapter<string>(this, android.r.layout.simple_dropdown_item_1line, newarrays); } auto.setadapter(adapter); auto.setdropdownheight(350); auto.setthreshold(1); auto.setcompletionhint("最近的5条记录"); auto.setonfocuschangelistener(new onfocuschangelistener() { @override public void onfocuschange(view v, boolean hasfocus) { autocompletetextview view = (autocompletetextview) v; if (hasfocus) { view.showdropdown(); } } }); } /** * 把指定autocompletetextview中内容保存到sharedpreference中指定的字符段 * @param field 保存在sharedpreference中的字段名 * @param auto 要操作的autocompletetextview */ private void savehistory(string field,autocompletetextview auto) { string text = auto.gettext().tostring(); sharedpreferences sp = getsharedpreferences("network_url", 0); string longhistory = sp.getstring(field, "nothing"); if (!longhistory.contains(text + ",")) { stringbuilder sb = new stringbuilder(longhistory); sb.insert(0, text + ","); sp.edit().putstring("history", sb.tostring()).commit(); } <span style="font-family: monospace; white-space: pre; background-color: rgb(240, 240, 240); "> } }</span>
上面的代码我实现了autocomplettextview的从sharepreference中读取历史记录并显示的功能,当没有任何输入时,提示最新的5项历史记录(这里可以加个条件,当有历史记录时才显示)
补上布局的代码
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <textview android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <linearlayout android:layout_width="0px" android:layout_height="0px" android:focusable="true" android:focusableintouchmode="true"></linearlayout> <autocompletetextview android:hint="请输入文字进行搜索" android:layout_height="wrap_content" android:layout_width="match_parent" android:id="@+id/autocompletetextview1"> </autocompletetextview> <button android:text="搜索" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></button> </linearlayout>
当之有一个edittext或者auto的时候,进入画面时是默认得到焦点的,要想去除焦点,可以在auto之前加一个o像素的layout,并设置他先得到焦点。
效果图如下
下面出现的是源码内容
需要注意的是,我这里用到的autocompletetextview的几个方法
1. setadapter()方法:这里要传递的adapter参数必须是继承listadapter和filterable的,其中arrayadapter和simpleadapter都能满足要求,我们常用arrayadapter,因为他不需要像simpleadapte那样设置他的显示位置和textview组件。
要想掌握它,就必须查看他的源码,我们可以看看arrayadapter是如何实现
凡是继承了filterable的adapter都必须重写getfilter接口方法
public filter getfilter() { if (mfilter == null) { mfilter = new arrayfilter(); } return mfilter; }
这个filter 就是实现过滤方法的对象,同样,我们可以查看他的源码是如何实现的
/** * <p>an array filter constrains the content of the array adapter with * a prefix. each item that does not start with the supplied prefix * is removed from the list.</p> */ private class arrayfilter extends filter { @override protected filterresults performfiltering(charsequence prefix) { filterresults results = new filterresults(); if (moriginalvalues == null) { synchronized (mlock) { moriginalvalues = new arraylist<t>(mobjects); } } if (prefix == null || prefix.length() == 0) { synchronized (mlock) { arraylist<t> list = new arraylist<t>(moriginalvalues); results.values = list; results.count = list.size(); } } else { string prefixstring = prefix.tostring().tolowercase(); final arraylist<t> values = moriginalvalues; final int count = values.size(); final arraylist<t> newvalues = new arraylist<t>(count); for (int i = 0; i < count; i++) { final t value = values.get(i); final string valuetext = value.tostring().tolowercase(); // first match against the whole, non-splitted value if (valuetext.startswith(prefixstring)) { newvalues.add(value); } else { final string[] words = valuetext.split(" "); final int wordcount = words.length; for (int k = 0; k < wordcount; k++) { if (words[k].startswith(prefixstring)) { newvalues.add(value); break; } } } } results.values = newvalues; results.count = newvalues.size(); } return results; }
这是arrayadapter自定义的一个私有内部类,所谓私有,就意味着你不能通过继承去修改这种过滤方法,同样你也不能直接得到他过滤后结果集results。假如你想使用新的过滤方法,你必须重写getfilter()方法,返回的filter对象是你要新建的filter对象(在里面包含performfiltering()方法重新构造你要的过滤方法)
2.setdropdownheight方法 ,用来设置提示下拉框的高度,注意,这只是限制了提示下拉框的高度,提示数据集的个数并没有变化
3.setthreshold方法,设置从输入第几个字符起出现提示
4.setcompletionhint方法,设置提示框最下面显示的文字
5.setonfocuschangelistener方法,里面包含onfocuschangelistener监听器,设置焦点改变事件
6.showdropdown方法,让下拉框弹出来
我没有用到的一些方法列举
1.clearlistselection,去除selector样式,只是暂时的去除,当用户再输入时又重新出现
2.dismissdropdown,关闭下拉提示框
3.enoughtofilter,这是一个是否满足过滤条件的方法,sdk建议我们可以重写这个方法
4. getadapter,得到一个可过滤的列表适配器
5.getdropdownanchor,得到下拉框的锚计的view的id
6.getdropdownbackground,得到下拉框的背景色
7.setdropdownbackgrounddrawable,设置下拉框的背景色
8.setdropdownbackgroundresource,设置下拉框的背景资源
9.setdropdownverticaloffset,设置下拉表垂直偏移量,即是list里包含的数据项数目
10.getdropdownverticaloffset ,得到下拉表垂直偏移量
11..setdropdownhorizontaloffset,设置水平偏移量
12.setdropdownanimationstyle,设置下拉框的弹出动画
13.getthreshold,得到过滤字符个数
14.setonitemclicklistener,设置下拉框点击事件
15.getlistselection,得到下拉框选中为位置
16.getonitemclicklistener。得到单项点击事件
17.getonitemselectedlistener得到单项选中事件
18.getadapter,得到那个设置的适配器
一些隐藏方法和构造我没有列举了,具体可以参考api文档
自定义:
网上找到的都是同arrayadapter一起使用的,有时候需要自定义风格,咋办?follow me!
看上图,实现了清空输入框内容和删除item功能。
其实使用autocompletetextview就得实现过滤器filterable,你得告诉它怎么过滤。由于arrayadapter已经帮我们实现了filterable接口,所以我们很容易忽略这个,以为autocompletetextview用起来很简单。如果你使用的是baseadapter呢?当然,事实上也不难,只要让它也实现filterable接口就可以了。
下面是源码:
实现自定义的adapter
import java.util.arraylist; import java.util.list; import qianlong.qlmobile.tablet.csco.r; import android.content.context; import android.util.log; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.view.view.onclicklistener; import android.widget.baseadapter; import android.widget.filter; import android.widget.filterable; import android.widget.imageview; import android.widget.textview; public class autocompleteadapter extends baseadapter implements filterable{ private context context; private arrayfilter mfilter; private arraylist<string> moriginalvalues;//所有的item private list<string> mobjects;//过滤后的item private final object mlock = new object(); private int maxmatch=10;//最多显示多少个选项,负数表示全部 public autocompleteadapter(context context,arraylist<string> moriginalvalues,int maxmatch){ this.context=context; this.moriginalvalues=moriginalvalues; this.maxmatch=maxmatch; } @override public filter getfilter() { // todo auto-generated method stub if (mfilter == null) { mfilter = new arrayfilter(); } return mfilter; } private class arrayfilter extends filter { @override protected filterresults performfiltering(charsequence prefix) { // todo auto-generated method stub filterresults results = new filterresults(); // if (moriginalvalues == null) { // synchronized (mlock) { // moriginalvalues = new arraylist<string>(mobjects);// // } // } if (prefix == null || prefix.length() == 0) { synchronized (mlock) { log.i("tag", "moriginalvalues.size="+moriginalvalues.size()); arraylist<string> list = new arraylist<string>(moriginalvalues); results.values = list; results.count = list.size(); return results; } } else { string prefixstring = prefix.tostring().tolowercase(); final int count = moriginalvalues.size(); final arraylist<string> newvalues = new arraylist<string>(count); for (int i = 0; i < count; i++) { final string value = moriginalvalues.get(i); final string valuetext = value.tolowercase(); // if(valuetext.contains(prefixstring)){//匹配所有 // // } // first match against the whole, non-splitted value if (valuetext.startswith(prefixstring)) { //源码 ,匹配开头 newvalues.add(value); } // else { // final string[] words = valuetext.split(" ");//分隔符匹配,效率低 // final int wordcount = words.length; // // for (int k = 0; k < wordcount; k++) { // if (words[k].startswith(prefixstring)) { // newvalues.add(value); // break; // } // } // } if(maxmatch>0){//有数量限制 if(newvalues.size()>maxmatch-1){//不要太多 break; } } } results.values = newvalues; results.count = newvalues.size(); } return results; } @override protected void publishresults(charsequence constraint, filterresults results) { // todo auto-generated method stub mobjects = (list<string>) results.values; if (results.count > 0) { notifydatasetchanged(); } else { notifydatasetinvalidated(); } } } @override public int getcount() { // todo auto-generated method stub return mobjects.size(); } @override public object getitem(int position) { // todo auto-generated method stub //此方法有误,尽量不要使用 return mobjects.get(position); } @override public long getitemid(int position) { // todo auto-generated method stub return position; } @override public view getview(final int position, view convertview, viewgroup parent) { // todo auto-generated method stub viewholder holder = null; if(convertview==null){ holder=new viewholder(); layoutinflater inflater = (layoutinflater)context.getsystemservice(context.layout_inflater_service); convertview=inflater.inflate(r.layout.simple_list_item_for_autocomplete, null); holder.tv=(textview)convertview.findviewbyid(r.id.simple_item_0); holder.iv=(imageview)convertview.findviewbyid(r.id.simple_item_1); convertview.settag(holder); }else{ holder = (viewholder) convertview.gettag(); } holder.tv.settext(mobjects.get(position)); holder.iv.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { // todo auto-generated method stub string obj=mobjects.remove(position); moriginalvalues.remove(obj); notifydatasetchanged(); } }); return convertview; } class viewholder { textview tv; imageview iv; } public arraylist<string> getallitems(){ return moriginalvalues; } }
import android.content.context; import android.util.attributeset; import android.view.view; import android.widget.autocompletetextview; import android.widget.imageview; import android.widget.relativelayout; import android.widget.imageview.scaletype; public class advancedautocompletetextview extends relativelayout{ private context context; private autocompletetextview tv; public advancedautocompletetextview(context context) { super(context); // todo auto-generated constructor stub this.context=context; } public advancedautocompletetextview(context context, attributeset attrs) { super(context, attrs); // todo auto-generated constructor stub this.context=context; } @override protected void onfinishinflate() { super.onfinishinflate(); initviews(); } private void initviews() { relativelayout.layoutparams params=new relativelayout.layoutparams(relativelayout.layoutparams.fill_parent,relativelayout.layoutparams.wrap_content); tv=new autocompletetextview(context); tv.setlayoutparams(params); tv.setpadding(10, 0, 40, 0); // tv.setsingleline(true); relativelayout.layoutparams p=new relativelayout.layoutparams(relativelayout.layoutparams.wrap_content,relativelayout.layoutparams.wrap_content); p.addrule(relativelayout.align_parent_right); p.addrule(relativelayout.center_vertical); p.rightmargin=10; imageview iv=new imageview(context); iv.setlayoutparams(p); iv.setscaletype(scaletype.fit_center); iv.setimageresource(r.drawable.delete); iv.setclickable(true); iv.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { // todo auto-generated method stub tv.settext(""); } }); this.addview(tv); this.addview(iv); } public void setadapter(autocompleteadapter adapter){ tv.setadapter(adapter); } public void setthreshold(int threshold){ tv.setthreshold(threshold); } public autocompletetextview getautocompletetextview(){ return tv; } }
simple_list_item_for_autocomplete.xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingtop="5dip" android:paddingbottom="5dip" > <textview android:id="@+id/simple_item_0" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:paddingleft="5dip" android:textcolor="@android:color/black" /> <imageview android:id="@+id/simple_item_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaletype="fitcenter" android:src="@drawable/delete" android:layout_centervertical="true" android:layout_marginright="5dip" /> </linearlayout>
使用,通常情况下都这样:
private advancedautocompletetextview tv; private autocompleteadapter adapter; private arraylist<string> moriginalvalues=new arraylist<string>(); @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); moriginalvalues.add("1234561"); moriginalvalues.add("1234562"); moriginalvalues.add("2234563"); moriginalvalues.add("2234564"); moriginalvalues.add("3234561111"); moriginalvalues.add("32345622222"); moriginalvalues.add("323456333333"); moriginalvalues.add("3234564444"); moriginalvalues.add("3234565555"); moriginalvalues.add("32345666666"); moriginalvalues.add("32345777777"); tv = (advancedautocompletetextview) findviewbyid(r.id.tv); tv.setthreshold(0); adapter = new autocompleteadapter(this, moriginalvalues, 10); tv.setadapter(adapter); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Ejb3持久化实体时的异常 博客分类: Java\Eclipse Plugin\Birt IEHibernate
下一篇: Eclipse Birt的列绑定错误 博客分类: Java\Eclipse Plugin\Birt Eclipse数据结构
推荐阅读
-
android中AutoCompleteTextView的简单用法(实现搜索历史)
-
Android App中实现简单的刮刮卡抽奖效果的实例详解
-
Android中ViewPager组件的基本用法及实现图片切换的示例
-
Android App中实现简单的刮刮卡抽奖效果的实例详解
-
Android中如何实现清空搜索框的文字
-
Android中ViewPager组件的基本用法及实现图片切换的示例
-
Android中如何实现清空搜索框的文字
-
基于Android中的 AutoCompleteTextView实现自动填充
-
Android中使用 AutoCompleteTextView 实现手机号格式化附带清空历史的操作
-
Android实现简单实用的搜索框