主要实现功能:
一、实现名单的中英文混合排序,按照联系人名单的首字母进行分类。
二、实现右侧的字母导航功能,根据字母定位相应的名单组,方便查找。
三、实现搜索功能(1)输入字母进行搜索时,按照精确查找(如查找张 输入z ;查找张三 输入zs)。
(2)输入汉字进行搜索时,按照相对模糊的查找(如输入“张”,即查找所有包含“张”字的名单,输入“张三”,即查找所有包含“张三”的名单)。
(3)输入其他字符串查找时,只根据第一个字符进行查询。
程序功能效果如下
代码结构:
MainActivity.java 主界面 MyAdapter.java重写一个adapter Sort.java处理数据的类
activity_main.xml 主界面
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="@+id/listView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</ListView>
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical|right"
android:scaleType="center"
android:src="@drawable/contact_list_scroll_normal" />
</FrameLayout>
icon.xml当点击导航时,显示在屏幕中间的提示图标
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/bg_hitchar"
android:gravity="center"
android:maxWidth="100dp"
android:minWidth="100dp"
android:padding="10dp"
android:textColor="#ffffffff"
android:textSize="70sp"
android:visibility="invisible" />
list_item_tag.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:background="#555555"
android:paddingLeft="10dip">
<TextView
android:id="@+id/group_list_item_text"
android:layout_width="wrap_content"
android:layout_height="20dip"
android:gravity="center_vertical"
android:textColor="#ffffff" />
</LinearLayout>
list_item.xml名单item
<?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:padding="5dip" >
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/list_addfriend_icon" />
<TextView
android:id="@+id/group_list_item_text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:paddingLeft="5dip" />
</LinearLayout>
search.xml搜索框
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/searchText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="@string/search_text" />
代码实现:
在初始化、设置监听、在主界面添加icon、把search添加进ListView之后,首先,调用Sort中的autoSort(String[])方法,对数据进行排序,然后使用排序后的String[]创建两个ArrayList,第一个ArrayList(newDataArrayList)调用Sort.addChar(String [])方法添加分组的字母,使用于ListView中。第二个ArrayList(checkArrayList)单纯的把排序后的String[]转换成ArrayList用于数据的搜索。 接着使用newDataArrayList创建MyAdapter对象,MyAdapter根据重写的getView方法生成ListView。当点击导航图片时,根据用户点击的位置判断出用户想要点击的字母,然后查找这个字母在newDataArrayList(即MyAda中的mObject)中的位置,使用ListView.setSelectionFromTop()方法把对应的分组字母显示在最上面。使用搜索功能时,判断输入字符串的是字母还是汉字,如果这个字符串都是字母,则每个字母匹配一次,不成功则从checkArrayList中remove掉。如果输入的全部为汉字,则使用String.contains()判断联系人名单包不包含搜索的字符,不包含则remove。在操作完成后的checkArrayList即为搜索到数据,然后通过MyAdapter用ListView现实出来
一、MainActivity.java
package com.example.tongxunlu;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity implements OnTouchListener,
OnGestureListener
{
private String searchStr = null;
private Sort mSort = null;
private Context mContext = null;
private TextView mIcon = null;
private MyAdapter mAdapter = null;
private ListView mListView = null;
private EditText mSearchText = null;
private ImageView mImageView = null;
private GestureDetector mGesture = null;
private ArrayList<String> newDataArrayList;
private ArrayList<String> checkArrayList;
private String[] newData;
private String[] english = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
"W", "X", "Y", "Z"};
private String[] oldData = {"一败如水", "胆小如鼠", "引狼入室", "风驰电掣", "刀山火海", "一贫如洗",
"料事如神", "视死如归", "对答如流", "挥金如土", "铁证如山", "度日如年", "心急如焚", "巧舌如簧",
"如雷贯耳", "如履薄冰", "如日中天", "势如破竹", "稳如泰山", "骨瘦如柴", "爱财如命", "暴跳如雷",
"门庭若市", "恩重如山", "从善如流", "观者如云", "浩如烟海", "弃暗投明", "取长补短", "厚今薄古",
"同甘共苦", "因小失大", "优胜劣败", "自生自灭", "评头论足", "远交近攻", "求同存异", "well",
"hello", "one", "goodtime", "running", "java", "android", "jsp",
"html", "struts", "Charles", "Mark", "Bill", "Vincent", "William",
"Joseph", "James", "Henry", "Gary", "Martin"};
@Override
/**
* 初始化、添加icon、search等view,设置监听
*/
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = MainActivity.this;
mImageView = (ImageView) this.findViewById(R.id.imageView1);
mListView = (ListView) this.findViewById(R.id.listView1);
mSearchText = (EditText) this.getLayoutInflater().inflate(
R.layout.search, null);
mIcon = (TextView) this.getLayoutInflater()
.inflate(R.layout.icon, null);
mGesture = new GestureDetector(this);
getWindowManager()
.addView(
mIcon,
new WindowManager.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT));
mSort = new Sort();
checkArrayList = new ArrayList<String>();
//得到排序后的数据(String[])
newData = mSort.autoSort(oldData);
newDataArrayList = mSort.addChar(newData);//
mListView.addHeaderView(mSearchText);
mAdapter = new MyAdapter(this, android.R.layout.simple_list_item_1,
newDataArrayList);
mListView.setAdapter(mAdapter);
mListView.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
// TODO Auto-generated method stub
if(mSearchText.hasFocus())
mSearchText.clearFocus();
return false;
}
});
//搜索框监听
mSearchText.addTextChangedListener(new MyWatchToSearch());
mImageView.setOnTouchListener(this);
mImageView.setLongClickable(true);
}
class MyWatchToSearch implements TextWatcher
{
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after)
{
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count)
{
// TODO Auto-generated method stub
//搜索功能只针对ListView中的内容数据,不针对标题数据。
//使用没添加的分组字母的数据创建新的ArrayList
checkArrayList = mSort.toArrayList(newData);
searchStr = mSearchText.getText().toString();
if (searchStr.length() != 0)
{
checkSearchStr(searchStr);
mAdapter = new MyAdapter(mContext,
android.R.layout.simple_list_item_1, checkArrayList);
mListView.setAdapter(mAdapter);
}
}
@Override
public void afterTextChanged(Editable s)
{
// TODO Auto-generated method stub
if (searchStr.length() == 0)
{
mAdapter = new MyAdapter(mContext,
android.R.layout.simple_list_item_1, newDataArrayList);
mListView.setAdapter(mAdapter);
}
mSearchText.requestFocus();
}
/**
*
*/
public void checkSearchStr(String search)
{
String tempSearch;
String tempList;
String newDataChar = null;
String checkArrayListItem = null;
//当输入的搜索字符为字母时
if (search.matches("[a-zA-Z]+"))
{
for (int i = 0; i < search.length(); i++)
{
for (int j = 0; j < checkArrayList.size(); j++)
{
checkArrayListItem = checkArrayList.get(j);
//如果联系人名称不为字母,则得到联系人名称的所有首字母
if (!checkArrayListItem.matches("[a-zA-Z]+"))
{
newDataChar = mSort
.getAllPinYinHeadChar(checkArrayListItem);
}
else
{
newDataChar = checkArrayListItem;
}
//取出输入的字符串的第i个字母,并转换为大写
tempSearch = String.valueOf(search.charAt(i))
.toUpperCase();
//取出得到的联系人名称所有首字母的第i个字母,并转换为大写
tempList = String.valueOf(newDataChar.charAt(i))
.toUpperCase();
if (!(tempSearch.equals(tempList)))
{
checkArrayList.remove(j);
newDataChar = null;
j--;
}
}
}
}
//当输入的搜索字符为汉字时
else if (search.matches("[\u4e00-\u9fa5]+"))
{
for (int j = 0; j < checkArrayList.size(); j++)
{
if (!checkArrayList.get(j).contains(search))
{
checkArrayList.remove(j);
j--;
}
}
}
else
{
search = String.valueOf(search.charAt(0));
for (int j = 0; j < checkArrayList.size(); j++)
{
if (!checkArrayList.get(j).contains(search))
{
checkArrayList.remove(j);
j--;
}
}
}
}
}
@Override
public boolean onTouch(View v, MotionEvent event)
{
// TODO Auto-generated method stub
if(mSearchText.hasFocus())
mSearchText.clearFocus();
return mGesture.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent e)
{
// TODO Auto-generated method stub
util(e);
return false;
}
@Override
public void onShowPress(MotionEvent e)
{
// TODO Auto-generated method stub
}
@Override
public boolean onSingleTapUp(MotionEvent e)
{
// TODO Auto-generated method stub
mImageView.setImageResource(R.drawable.contact_list_scroll_normal);
mIcon.setVisibility(View.INVISIBLE);
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY)
{
util(e2);
// TODO Auto-generated method stub
return false;
}
@Override
public void onLongPress(MotionEvent e)
{
// TODO Auto-generated method stub
mImageView.setImageResource(R.drawable.contact_list_scroll_normal);
mIcon.setVisibility(View.INVISIBLE);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY)
{
// TODO Auto-generated method stub
mImageView.setImageResource(R.drawable.contact_list_scroll_normal);
mIcon.setVisibility(View.INVISIBLE);
return false;
}
public void util(MotionEvent e2)
{
//获取触摸点在导航图片中的位置
int i = (int) (e2.getY() - mImageView.getTop());
mImageView.setImageResource(R.drawable.contact_list_scroll_pressed);
int pos;
int count;
if (0 <= i && i <= 30)
{
mIcon.setText("搜");
mIcon.setVisibility(View.VISIBLE);
mListView.setSelectionFromTop(0, 0);
}
else
{
count = (int) ((i - 31) / ((float) (mImageView.getHeight() - 62) / 26f));
if (0 <= count && count < 26)
{
mIcon.setText(english[count]);
mIcon.setVisibility(View.VISIBLE);
pos = mAdapter.checkSection(english[count]) + 1;
if (pos >= 0) mListView.setSelectionFromTop(pos, 0);
}
else
{
mIcon.setVisibility(View.VISIBLE);
mIcon.setText("#");
}
}
}
}
二、Sort.java
package com.example.tongxunlu;
import java.util.ArrayList;
import net.sourceforge.pinyin4j.PinyinHelper;
public class Sort
{
/**中英文混合排序
*
* @param strArr 原始的通讯录名单
* @return 排序后的通讯录名单
*/
public String[] autoSort(String[] strArr)
{
String temp = "";
String headchar1 ;
String headchar2 ;
for (int i = 0; i < strArr.length; i++)
{
for (int j = i; j < strArr.length; j++)
{
headchar1 = getPinYinHeadChar(strArr[i]).toUpperCase();
headchar2 = getPinYinHeadChar(strArr[j]).toUpperCase();
if (headchar1.charAt(0) > headchar2.charAt(0))
{
temp = strArr[i];
strArr[i] = strArr[j];
strArr[j] = temp;
}
}
}
return strArr;
}
/**得到当前联系人名称的的一个汉字的首字母
*
* @param str 联系人名称
* @return 首字母
*/
public String getPinYinHeadChar(String str)
{
String convert = "";
char word = str.charAt(0);
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
if(pinyinArray!= null)
convert = String .valueOf(pinyinArray[0].charAt(0));
else {
convert = String .valueOf(word);
}
return convert;
}
/**实现数据分组
*
* @param strArr 排序后的通讯录名单
* @return 对数据添加了分组字母的ArrayList(如在所有首字母为B的名单组之前添加一个B实现分组)
*/
public ArrayList<String> addChar(String[] strArr)
{
String headchar = "" ;
ArrayList<String> list = new ArrayList<String>();
int j= 0;
for (int i = 0; i < strArr.length; i++)
{
headchar = String.valueOf(getPinYinHeadChar(strArr[i]).charAt(0)).toUpperCase();
if(!list.contains(headchar))
{
list.add(headchar);
list.add(strArr[i]);
}
else {
list.add(strArr[i]);
}
}
return list;
}
public ArrayList<String> toArrayList(String[] str)
{
ArrayList<String> arrayList = new ArrayList<String>();
for(int i = 0; i<str.length;i++)
arrayList.add(str[i]);
return arrayList;
}
/**
*
* @param str联系人名称
* @return 联系人名称中每个汉字的首字母
*/
public String getAllPinYinHeadChar(String str) {
String convert = "";
for (int j = 0; j < str.length(); j++) {
char word = str.charAt(j);
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
if (pinyinArray != null) {
convert += pinyinArray[0].charAt(0);
}else {
convert += word;
}
}
return convert;
}
}
三、MyAdapter.java
package com.example.tongxunlu;
import java.util.ArrayList;
import java.util.HashMap;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class MyAdapter extends ArrayAdapter<String>
{
public String[] sections;
public ArrayList<String> mObject;
public HashMap<String, Integer> alphaIndexer;
private View view = null;
private TextView tView = null;
private ArrayList<String> arrayList = new ArrayList<String>();
private String[] english = {"A", "B", "C", "D", "E", "F", "G", "H", "I",
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
"W", "X", "Y", "Z"};
public MyAdapter(Context context, int textViewResourceId,
ArrayList<String> objects)
{
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
initArrayList();
mObject = objects;
}
@Override
/**
* 添加item时判断,如果读取到的数据可以在arrayList中找到(即大写的单独字母),则添加为标题,否则是内容
*
*/
public View getView(int position, View convertView, ViewGroup parent)
{
// TODO Auto-generated method stub
if (arrayList.contains(getItem(position)))
{
view = LayoutInflater.from(getContext()).inflate(
R.layout.list_item_tag, null);
}
else
{
view = LayoutInflater.from(getContext()).inflate(
R.layout.list_item, null);
}
tView = (TextView) view
.findViewById(R.id.group_list_item_text);
tView.setText(getItem(position));
return view;
}
/**
* 根据字母导航所点击的字母,锁定名单中对应标题的位置
* @param str 所点击的字母
* @return 返回字母在数据源中的位置。
*/
public int checkSection(String str)
{
for (int i = 0; i < mObject.size(); i++)
{
if (mObject.get(i).equals(str))
return i;
}
return -1;
}
/**
* 讲26字母添加进list中,方便getView判断
*/
public void initArrayList()
{
for (int i = 0; i < english.length; i++)
arrayList.add(english[i]);
}
}