《Android开发卷——手机联系人T9搜索》

   

自己研究了好几天联系人的T9搜索算法, 先分享出来给大家看看. 欢迎指教.如果有大神有更好的T9搜索算法, 那更好啊,大家一起研究研究,谢谢.

第一部分是比较简单的获取手机联系人.

获取联系人前提要有权限.

<uses-permission android:name="android.permission.READ_CONTACTS" />

因为手机的联系人都存储在数据库里面,所以我们只要把数据库里的信息查询出来即可.

private static final String[] PHONES_PROJECTION = new String[] {

Phone.DISPLAY_NAME, Phone.NUMBER, Photo.SORT_KEY_ALTERNATIVE};

ContentResolver resolver = getBaseContext().getContentResolver();

Cursor phoneCursor = resolver.query(Phone.CONTENT_URI,

PHONES_PROJECTION, null, null, null);

这里我只是简单的说一下而已,后面的遍历phoneCursor 就能把联系人查询出来.(我项目里是开一条线程获取联系人的,以防太多联系人导致页面空白或者卡顿)

第二部分是T9搜索部分

思路是: a只要联系人的号码有包含我输入的数字就add到list进去,

b联系人的姓名拼音有包含我输入的拼音就add到list进去,

c联系人的姓名缩写拼音有包含我输入的拼音就add到list进去

举个例子--联系人姓名:测试,号码:1234567890

情况一:我输入1234567890就能把测试显示出来

情况二:我输入23744(ceshi),因为这个"测试"的拼音,所以也能把测试显示出来

情况三:我输入(27)cs,这是"测试"的拼音缩写,所以也能把测试显示出来

当然我输入23(ce)或者744(shi)什么的,都可以把测试显示出来.

以上是我的思路,下面附上一段代码

public class MainT9 extends Activity{

	private int[] textViewId = new int[]{R.id.main_num_1,R.id.main_num_2,R.id.main_num_3,R.id.main_num_4,
			R.id.main_num_5,R.id.main_num_6,R.id.main_num_7,R.id.main_num_8,R.id.main_num_9,R.id.main_num_left,
			R.id.main_num_0,R.id.main_num_right,R.id.main_num_delete};
	private TextView[] textView = new TextView[textViewId.length];
	private EditText inputEditText;

	private ListView mListView;

	private List<ContractBean> mList;
	private List<ContractBean> list;
	private MyAdapter myAdapter;

	private static final String[] PHONES_PROJECTION = new String[] {
		Phone.DISPLAY_NAME, Phone.NUMBER, Photo.SORT_KEY_ALTERNATIVE};

	long waitTime = 300;
	long touchTime = 0;

	/**
	 * 判断是否人为输入
	 */
	private boolean isWrite = false;
	private boolean isAfresh = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		this.setContentView(R.layout.main_activity);

		mList = new ArrayList<ContractBean>();
		list = new ArrayList<ContractBean>();

		/**
		 * 刚开始启动程序时,开条线程去获取联系人
		 */
		new Thread(getContract).start();

		for(int i = 0;i<textViewId.length;i++){
			textView[i] = (TextView) this.findViewById(textViewId[i]);
			textView[i].setOnClickListener(click);
		}

		inputEditText = (EditText) this.findViewById(R.id.main_num_edit);
//		hideSystemKeyBoard(inputEditText);

		mListView = (ListView) this.findViewById(R.id.main_contract_listview);
		myAdapter = new MyAdapter(this, mList);
		mListView.setAdapter(myAdapter);

		inputEditText.addTextChangedListener(new TextWatcher() {
			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
				// TODO Auto-generated method stub
				if (isWrite) {
					isWrite = false;
					return;
				}
				isWrite = true;
				String inputStr = "";
				String newStr = s.toString();
				newStr = newStr.replace(" ", "");
				int index = 0;
				if (true) {
					if ((index + 3) < newStr.length()) {
						inputStr += (newStr.substring(index, index + 3) + " ");
						index += 3;
					}
				}
				while ((index + 4) < newStr.length()) {
					inputStr += (newStr.substring(index, index + 4) + " ");
					index += 4;
				}
				inputStr += (newStr.substring(index, newStr.length()));
				inputEditText.setText(inputStr);
				inputEditText.setSelection(inputStr.length());

				if(count == 0){
					isAfresh = true;
				}else{
					isAfresh = false;
				}

				long currentTime = System.currentTimeMillis();
				if ((currentTime - touchTime) >= waitTime) {
					touchTime = currentTime;
					searchConstract(isAfresh);
				}
			}
			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				// TODO Auto-generated method stub
			}
			@Override
			public void afterTextChanged(Editable s) {
				// TODO Auto-generated method stub
			}
		});
	}

	private void searchConstract(boolean isAfresh){
		if(isAfresh){
			if(mList!=null){
				myAdapter.updateListView(mList);
			}else{
				new Thread(getContract).start();
			}

		}else{
			String  str1= inputEditText.getText().toString();
			str1 = str1.replace(" ", "");

			SearchContract search = new SearchContract(str1);
			search.start();
		}
	}

	/**
	 * T9搜索线程
	 * @author Chillax_KUN
	 */
	class SearchContract extends Thread{
		String body;
		SearchContract(String body){
			this.body = body;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			Iterator<ContractBean> iterator = mList.iterator();
			list = new ArrayList<ContractBean>();
			list.clear();

			while(iterator.hasNext()){
				ContractBean sortModel = iterator.next();
				String search = sortModel.getSearch();
				String phone = sortModel.getPhone();
				phone = phone.replace(" ", "");
				String zimu = sortModel.getZimu();

				if(phone.contains(body) || search.contains(body)||zimu.contains(body)){
					list.add(sortModel);
				}
			}
			h.sendEmptyMessage(1);
		}

	}

	/**
	 * 开启线程,获取联系人
	 */
	Runnable getContract = new Runnable() {
		@Override
		public void run() {
			// TODO Auto-generated method stub
			mList = getPhoneContacts();
			h.sendEmptyMessage(0);
		}
	};

	private List<ContractBean> getPhoneContacts() {
		ContentResolver resolver = getBaseContext().getContentResolver();
		Cursor phoneCursor = resolver.query(Phone.CONTENT_URI,
				PHONES_PROJECTION, null, null, null);

		List<ContractBean> mList = new ArrayList<ContractBean>();

		if (phoneCursor != null) {
			phoneCursor.moveToFirst();
			while (!phoneCursor.isAfterLast()) {
				ContractBean model = new ContractBean();

				String name = phoneCursor.getString(0);
				String phone = phoneCursor.getString(1);
				String search = phoneCursor.getString(2);

				model.setName(name);
				model.setPhone(phone);
				model.setSearch(getNum(search,false));

				String zimu = "";
				String str[] = search.split(" ");
				if(str.length>0){
					for(int i = 0;i<str.length;i++){
						if(str[i].length()==1){
							zimu = zimu + str[i];
						}
					}
				}

				model.setZimu(getNum(zimu,true));

				mList.add(model);
				phoneCursor.moveToNext();
			}
			if(phoneCursor!=null){
				phoneCursor.close();
			}
			return mList;
		}
		return mList;
	}

	/**
	 * 将联系人的姓名拼音全部转化为数字
	 * @param 联系人姓名拼音
	 * @return 姓名拼音对应数字
	 */
	public String getNum(String search, boolean status){
		String str = "";
		for(int i = 0;i<search.length();i++){
			String c = search.charAt(i)+"";
			if(c.equals("1")){
				str = str + "1";
				if(status){
					i = i + 1;
				}
				continue;
			}else if(c.equals("A")||c.equals("B")||c.equals("C")||c.equals("2")
					||c.equals("a")||c.equals("b")||c.equals("c")){
				str = str + "2";
				if(status){
					i = i + 1;
				}
				continue;
			}else if(c.equals("D")||c.equals("E")||c.equals("F")||c.equals("3")
					||c.equals("d")||c.equals("e")||c.equals("f")){
				str = str + "3";
				if(status){
					i = i + 1;
				}
				continue;
			}else if(c.equals("G")||c.equals("H")||c.equals("I")||c.equals("4")
					||c.equals("g")||c.equals("h")||c.equals("i")){
				str = str + "4";
				if(status){
					i = i + 1;
				}
				continue;
			}else if(c.equals("J")||c.equals("K")||c.equals("L")||c.equals("5")
					||c.equals("j")||c.equals("k")||c.equals("l")){
				str = str + "5";
				if(status){
					i = i + 1;
				}
				continue;
			}else if(c.equals("M")||c.equals("N")||c.equals("O")||c.equals("6")
					||c.equals("m")||c.equals("n")||c.equals("o")){
				str = str + "6";
				if(status){
					i = i + 1;
				}
				continue;
			}else if(c.equals("P")||c.equals("Q")||c.equals("R")||c.equals("S")||c.equals("7")
					||c.equals("p")||c.equals("q")||c.equals("r")||c.equals("s")){
				str = str + "7";
				if(status){
					i = i + 1;
				}
				continue;
			}else if(c.equals("T")||c.equals("U")||c.equals("V")||c.equals("8")
					||c.equals("t")||c.equals("u")||c.equals("v")){
				str = str + "8";
				if(status){
					i = i + 1;
				}
				continue;
			}else if(c.equals("W")||c.equals("X")||c.equals("Y")||c.equals("Z")||c.equals("9")
					||c.equals("w")||c.equals("x")||c.equals("y")||c.equals("z")){
				str = str + "9";
				if(status){
					i = i + 1;
				}
				continue;
			}else if(c.equals("0")){
				str = str + "0";
				if(status){
					i = i + 1;
				}
				continue;
			}
		}
		return str;
	};

	Handler h = new Handler(){
		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			super.handleMessage(msg);
			if(msg.what==0){
				if(mList!=null && myAdapter!=null){
					myAdapter.updateListView(mList);
					myAdapter.notifyDataSetChanged();
				}
			} else if(msg.what==1){
				myAdapter.updateListView(list);
			}

		}
	};

	OnClickListener click = new OnClickListener() {

		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			switch (v.getId()) {
			case R.id.main_num_1:
				inputEditText.setText(inputEditText.getText()+"1");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_2:
				inputEditText.setText(inputEditText.getText()+"2");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_3:
				inputEditText.setText(inputEditText.getText()+"3");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_4:
				inputEditText.setText(inputEditText.getText()+"4");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_5:
				inputEditText.setText(inputEditText.getText()+"5");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_6:
				inputEditText.setText(inputEditText.getText()+"6");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_7:
				inputEditText.setText(inputEditText.getText()+"7");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_8:
				inputEditText.setText(inputEditText.getText()+"8");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_9:
				inputEditText.setText(inputEditText.getText()+"9");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_0:
				inputEditText.setText(inputEditText.getText()+"0");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_left:
				inputEditText.setText(inputEditText.getText()+"*");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_right:
				inputEditText.setText(inputEditText.getText()+"#");
				inputEditText.setSelection(inputEditText.getText().toString().length());
				break;
			case R.id.main_num_delete:
				String string = inputEditText.getText().toString();
				if(!string.equals("")){
					inputEditText.setText(string.subSequence(0, string.length()-1));
					inputEditText.setSelection(inputEditText.getText().toString().length());
				}
				break;
			default:
				break;
			}
		}
	};

	/**
	 * 通过反射调用setShowSoftInputOnFocus(false) 来隐藏键盘。 用 InputType.TYPE_NULL方法,无法显示光标。
	 */
	private void hideSystemKeyBoard(View view) {
		this.getWindow().setSoftInputMode(
				WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
		try {
			Class<EditText> cls = EditText.class;
			Method setSoftInputShownOnFocus;
			// 此方法为隐藏的需用java反射调用
			setSoftInputShownOnFocus = cls.getMethod("setShowSoftInputOnFocus",
					boolean.class);
			setSoftInputShownOnFocus.setAccessible(true);
			setSoftInputShownOnFocus.invoke((EditText) view, false);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

源码地址:http://download.csdn.net/detail/chillax_li/7467553

尊重原创, 转载请注明出处:http://blog.csdn.net/chillax_li/article/details/29380615

《Android开发卷——手机联系人T9搜索》,布布扣,bubuko.com

时间: 2024-10-18 08:30:33

《Android开发卷——手机联系人T9搜索》的相关文章

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

IOS测试框架之:athrun的InstrumentDriver源码阅读笔记

athrun的InstrumentDriver源码阅读笔记 作者:唯一 athrun是淘宝的开源测试项目,InstrumentDriver是ios端的实现,之前在公司项目中用过这个框架,没有深入了解,现在回来记录下. 官方介绍:http://code.taobao.org/p/athrun/wiki/instrumentDriver/ 优点:这个框架是对UIAutomation的java实现,在代码提示.用例维护方面比UIAutomation强多了,借junit4的光,我们可以通过junit4的

Yii源码阅读笔记 - 日志组件

?使用 Yii框架为开发者提供两个静态方法进行日志记录: Yii::log($message, $level, $category);Yii::trace($message, $category); 两者的区别在于后者依赖于应用开启调试模式,即定义常量YII_DEBUG: defined('YII_DEBUG') or define('YII_DEBUG', true); Yii::log方法的调用需要指定message的level和category.category是格式为“xxx.yyy.z

源码阅读笔记 - 1 MSVC2015中的std::sort

大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格式化,去掉或者展开用于条件编译或者debug检查的宏,依重要程度重新排序函数,但是不会改变命名方式(虽然MSVC的STL命名实在是我不能接受的那种),对于代码块的解释会在代码块前(上面)用注释标明. template<class _RanIt, class _Diff, class _Pr> in

CI框架源码阅读笔记5 基准测试 BenchMark.php

上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功能,各模块之间可以相互调用,共同构成了CI的核心骨架. 从本篇开始,将进一步去分析各组件的实现细节,深入CI核心的黑盒内部(研究之后,其实就应该是白盒了,仅仅对于应用来说,它应该算是黑盒),从而更好的去认识.把握这个框架. 按照惯例,在开始之前,我们贴上CI中不完全的核心组件图: 由于BenchMa

CI框架源码阅读笔记2 一切的入口 index.php

上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里这次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中,我们并不会逐行进行解释,而只解释核心的功能和实现. 1.       设置应用程序环境 define('ENVIRONMENT', 'development'); 这里的development可以是任何你喜欢的环境名称(比如dev,再如test),相对应的,你要在下面的switch case代码块中

Apache Storm源码阅读笔记

欢迎转载,转载请注明出处. 楔子 自从建了Spark交流的QQ群之后,热情加入的同学不少,大家不仅对Spark很热衷对于Storm也是充满好奇.大家都提到一个问题就是有关storm内部实现机理的资料比较少,理解起来非常费劲. 尽管自己也陆续对storm的源码走读发表了一些博文,当时写的时候比较匆忙,有时候衔接的不是太好,此番做了一些整理,主要是针对TridentTopology部分,修改过的内容采用pdf格式发布,方便打印. 文章中有些内容的理解得益于徐明明和fxjwind两位的指点,非常感谢.

CI框架源码阅读笔记4 引导文件CodeIgniter.php

到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.com/usr/reg 经过引导文件,实际上会交给Application中的UsrController控制器的reg方法去处理. 这之中,CodeIgniter.php做了哪些工作?我们一步步来看. 1.    导入预定义常量.框架环境初始化 之前的一篇博客(CI框架源码阅读笔记2 一切的入

jdk源码阅读笔记之java集合框架(二)(ArrayList)

关于ArrayList的分析,会从且仅从其添加(add)与删除(remove)方法入手. ArrayList类定义: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco } span.s1 { color: #931a68 } public class ArrayList<E> extends AbstractList<E> implements List<E> ArrayList基本属性: /** *

dubbo源码阅读笔记--服务调用时序

上接dubbo源码阅读笔记--暴露服务时序,继续梳理服务调用时序,下图右面红线流程. 整理了调用时序图 分为3步,connect,decode,invoke. 连接 AllChannelHandler.connected(Channel) line: 38 HeartbeatHandler.connected(Channel) line: 47 MultiMessageHandler(AbstractChannelHandlerDelegate).connected(Channel) line: