您的位置:首页 > 其它

联系人的侧边字母索引ListView 将手机通讯录姓名通过首字母排序。

2015-12-08 17:59 537 查看


packagecom.lixu.letterlistview;

importjava.util.ArrayList;
importjava.util.List;
importorg.apache.http.NameValuePair;
importorg.apache.http.message.BasicNameValuePair;
importcom.lixu.letterlistview.letter.LetterBaseListAdapter;
importcom.lixu.letterlistview.letter.LetterListView;
importcom.lixu.lianxirenlist.R;
importandroid.app.Activity;
importandroid.content.ContentResolver;
importandroid.database.Cursor;
importandroid.graphics.Color;
importandroid.net.Uri;
importandroid.os.Bundle;
importandroid.view.Gravity;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.TextView;

publicclassMainActivityextendsActivity{
privateArrayList<String>dataArray;

@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//通过获取手机通讯录的姓名
dataArray=newArrayList<String>();

Uriuri=Uri.parse("content://com.android.contacts/contacts");
ContentResolverresolver=this.getContentResolver();
//给query传递一个SORT_KEY_PRIMARY,让ContentResolver将获得的数据按照联系人名字首字母排序
Cursorcursor=resolver.query(uri,null,null,null,
android.provider.ContactsContract.Contacts.SORT_KEY_PRIMARY);
while(cursor.moveToNext())

{
//联系人的id
Stringid=cursor.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts._ID));
//将联系人按姓名首字母分组
Stringsort_key_primary=cursor
.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts.SORT_KEY_PRIMARY));
//获取联系人的名字
Stringname=cursor
.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts.DISPLAY_NAME));
dataArray.add(name);
}

LetterListViewletterListView=(LetterListView)findViewById(R.id.letterListView);
letterListView.setAdapter(newTestAdapter());

}

/**
*这里使用一个简单的NameValuePair对象,做为测试
*
*@Title:
*@Description:
*@Author:Justlcw
*@Since:2014-5-13
*@Version:
*/
classTestAdapterextendsLetterBaseListAdapter<NameValuePair>{
/**字母对应的key,因为字母是要插入到列表中的,为了区别,所有字母的item都使用同一的key.**/
privatestaticfinalStringLETTER_KEY="letter";

publicTestAdapter(){
super();

List<NameValuePair>dataList=newArrayList<NameValuePair>();
for(inti=0;i<dataArray.size();i++){
NameValuePairpair=newBasicNameValuePair(String.valueOf(i),dataArray.get(i));
dataList.add(pair);
}
setContainerList(dataList);
}

@Override
publicObjectgetItem(intposition){
returnlist.get(position);
}

@Override
publiclonggetItemId(intposition){
returnposition;
}

@Override
publicStringgetItemString(NameValuePairt){
returnt.getValue();
}

@Override
publicNameValuePaircreate(charletter){
returnnewBasicNameValuePair(LETTER_KEY,String.valueOf(letter));
}

@Override
publicbooleanisLetter(NameValuePairt){
//判断是不是字母行,通过key比较,这里是NameValuePair对象,其他对象,就由你自己决定怎么判断了.
returnt.getName().equals(LETTER_KEY);
}

@Override
publicViewgetLetterView(intposition,ViewconvertView,ViewGroupparent){
//这里是字母的item界面设置.
if(convertView==null){
convertView=newTextView(MainActivity.this);
((TextView)convertView).setGravity(Gravity.CENTER_VERTICAL);
convertView.setBackgroundColor(getResources().getColor(android.R.color.white));
}
((TextView)convertView).setText(list.get(position).getValue());
((TextView)convertView).setBackgroundColor(Color.GREEN);
((TextView)convertView).setTextSize(25);
returnconvertView;
}

@Override
publicViewgetContainerView(intposition,ViewconvertView,ViewGroupparent){
//这里是其他正常数据的item界面设置.
if(convertView==null){
convertView=newTextView(MainActivity.this);
((TextView)convertView).setGravity(Gravity.CENTER_VERTICAL);
}
((TextView)convertView).setText(list.get(position).getValue());
((TextView)convertView).setBackgroundColor(Color.YELLOW);
((TextView)convertView).setTextSize(20);

returnconvertView;
}
}
}


packagecom.lixu.letterlistview.letter;

importandroid.widget.BaseAdapter;

/**
*带有侧边字母列表的listView适配器
*
*@Title:
*@Description:
*@Author:Justlcw
*@Since:2014-5-8
*@Version:
*/
publicabstractclassLetterBaseAdapterextendsBaseAdapter
{
/**字母表头部**/
protectedstaticfinalcharHEADER='+';
/**字母表尾部**/
protectedstaticfinalcharFOOTER='#';

/**
*是否需要隐藏没有匹配到的字母
*
*@returntrue隐藏,false不隐藏
*@Description:
*@AuthorJustlcw
*@Date2014-5-8
*/
publicabstractbooleanhideLetterNotMatch();

/**
*获取字母对应的位置
*
*@returnposition
*@Description:
*@AuthorJustlcw
*@Date2014-5-8
*/
publicabstractintgetIndex(charletter);
}


packagecom.lixu.letterlistview.letter;

importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
importandroid.text.TextUtils;
importandroid.util.Log;
importandroid.view.View;
importandroid.view.ViewGroup;

/**
*通用带有字母列表的泛型对象adapter
*
*@Title:
*@Description:
*@Author:Justlcw
*@Since:2014-5-9
*@Version:
*/
publicabstractclassLetterBaseListAdapter<T>extendsLetterBaseAdapter{
/**logtag.**/
privatestaticfinalStringTAG="LetterBaseListAdapter";

/**默认错误头部字母.**/
privatestaticfinalcharERROR_LETTER='';

/**viewtype的类型总数**/
privatestaticfinalintTYPE_COUNT=2;
/**字母类型**/
privatestaticfinalintTYPE_LETTER=0;
/**实体类型**/
privatestaticfinalintTYPE_CONTAINER=1;

/**添加字母之后的list**/
protectedfinalList<T>list;
/**字母头位置标示map**/
privatefinalMap<Character,Integer>letterMap;

/**
*构造方法
*/
publicLetterBaseListAdapter(){
list=newArrayList<T>();
letterMap=newHashMap<Character,Integer>();
}

/**
*构造方法
*
*@paramdataArray
*内容数组
*/
publicLetterBaseListAdapter(T[]dataArray){
this();
setContainerList(dataArray);
}

/**
*构造方法
*
*@paramdataList
*内容列表
*/
publicLetterBaseListAdapter(List<T>dataList){
this();
setContainerList(dataList);
}

/**
*设置主体内容
*
*@paramdataArray
*实体数组
*@Description:
*@AuthorJustlcw
*@Date2014-5-9
*/
protectedfinalvoidsetContainerList(T[]dataArray){
if(!list.isEmpty()){
list.clear();
}
if(!letterMap.isEmpty()){
letterMap.clear();
}

charletter=ERROR_LETTER;
intindex=0;
for(inti=0;i<dataArray.length;i++){
Tt=dataArray[i];

charl=getHeaderLetter(t);

if(letter!=l&&l!=ERROR_LETTER){
//如果发现这个字母没有添加过,更新一下标示
letter=l;
//创建一个T类型的字母头放进去
Ttl=create(letter);
if(tl!=null){
//如果创建成功,则插入到列表中
list.add(tl);
}
//存放最新字母对应的位置
letterMap.put(letter,index);
index++;
}
//添加原本的填充实体项
list.add(t);
index++;
}
}

/**
*设置主体内容.
*
*@paramdataList
*实体列表
*@Description:
*@AuthorJustlcw
*@Date2014-5-9
*/
protectedfinalvoidsetContainerList(List<T>dataList){
if(!list.isEmpty()){
list.clear();
}
if(!letterMap.isEmpty()){
letterMap.clear();
}

charletter='';
intindex=0;
for(inti=0;i<dataList.size();i++){
Tt=dataList.get(i);

charl=getHeaderLetter(t);

if(letter!=l&&l!=ERROR_LETTER){
//如果发现这个字母没有添加过,更新一下标示
letter=l;
//创建一个T类型的字母头放进去
Ttl=create(letter);
if(tl!=null){
//如果创建成功,则插入到列表中
list.add(tl);
}
//存放最新字母对应的位置
letterMap.put(letter,index);
index++;
}
//添加原本的填充实体项
list.add(t);
index++;
}
}

/**
*@paramt
*<实体item对象>
*
*@return<实体item对象>首字母,获取失败返回{@link#ERROR_LETTER}
*@Description:
*@AuthorJustlcw
*@Date2014-5-12
*/
privatechargetHeaderLetter(Tt){
//获取item对应的字符串
Stringstr=getItemString(t);
//如果为空,跳出继续
if(TextUtils.isEmpty(str)){
Log.e(TAG,"itemstringemptyin"+t.toString());
returnERROR_LETTER;
}
charl;
//获取第一个字母
charfirstChar=str.charAt(0);
if(firstChar==HEADER||firstChar==FOOTER||LetterUtil.isLetter(firstChar)){
l=firstChar;//如果是头,尾,字母,直接赋值
}else{
String[]letterArray=LetterUtil.getFirstPinyin(firstChar);
//如果是汉字,取拼音首字母
if(letterArray!=null&&letterArray.length>0){
l=letterArray[0].charAt(0);
}else{
//如果汉字转拼音失败了,跳过
Log.e(TAG,firstChar+"turntoletterfail,"+t.toString());
returnERROR_LETTER;
}
}

//如果是小写字母,转换为大写字母
if(l>='a'){
l=(char)(l-32);
}
returnl;
}

@Override
publicfinalintgetCount(){
returnlist.size();
}

@Override
publicfinalViewgetView(intposition,ViewconvertView,ViewGroupparent){
if(getItemViewType(position)==TYPE_LETTER){
returngetLetterView(position,convertView,parent);
}
returngetContainerView(position,convertView,parent);
}

@Override
publicfinalintgetItemViewType(intposition){
if(isLetter(list.get(position))){
returnTYPE_LETTER;
}
returnTYPE_CONTAINER;
}

@Override
publicfinalintgetViewTypeCount(){
returnTYPE_COUNT;
}

@Override
publicbooleanhideLetterNotMatch(){
returnfalse;
}

@Override
publicfinalintgetIndex(charletter){
Integerindex=letterMap.get(letter);
if(index==null){
return-1;
}
returnindex;
}

/**
*@paramT
*<实体item对象>
*
*@return<实体item对象>对应的String,用来获取<拼音首字母>
*@Description:
*@AuthorJustlcw
*@Date2014-5-9
*/
publicabstractStringgetItemString(Tt);

/**
*@paramletter
*<字母>
*
*@return根据<字母>创建一个<实体item对象>,用来显示<字母item>
*@Description:
*@AuthorJustlcw
*@Date2014-5-9
*/
publicabstractTcreate(charletter);

/**
*@paramt
*<实体item对象>
*
*@return根据<实体item对象>,判断是否是<字母item>
*@Description:
*@AuthorJustlcw
*@Date2014-5-9
*/
publicabstractbooleanisLetter(Tt);

/**
*返回<字母item>界面,其他的同
*<P>
*{@link#getView(int,View,ViewGroup)}
*
*@Description:
*@AuthorJustlcw
*@Date2014-5-9
*/
publicabstractViewgetLetterView(intposition,ViewconvertView,ViewGroupparent);

/**
*返回<实体item>界面,其他的同
*<P>
*{@link#getView(int,View,ViewGroup)}
*
*@Description:
*@AuthorJustlcw
*@Date2014-5-9
*/
publicabstractViewgetContainerView(intposition,ViewconvertView,ViewGroupparent);
}


packagecom.lixu.letterlistview.letter;

importjava.lang.ref.SoftReference;
importjava.util.ArrayList;
importjava.util.List;

importcom.lixu.lianxirenlist.R;
importandroid.content.Context;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.util.AttributeSet;
importandroid.view.Gravity;
importandroid.view.LayoutInflater;
importandroid.view.MotionEvent;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.AbsListView;
importandroid.widget.BaseAdapter;
importandroid.widget.FrameLayout;
importandroid.widget.ListView;
importandroid.widget.TextView;
importandroid.widget.AdapterView.OnItemClickListener;

/**
*带有字母列表的listView
*
*@Title:
*@Description:
*@Author:Justlcw
*@Since:2014-5-7
*@Version:
*/
publicclassLetterListViewextendsFrameLayout{
/**隐藏字母消息**/
privatefinalintMSG_HIDE_LETTER=0x0;

/**字母列表的宽度**/
privatefinalintLETTER_LIST_VIEW_WIDTH=50;//TODO这里宽度写死了,按着一定的比例比较好

/**内容列表**/
privateListViewmListView;
/**内容列表适配器**/
privateLetterBaseAdaptermAdapter;

/**字母列表**/
privateListViewmLetterListView;
privateLetterAdaptermLetterAdapter;

privateTextViewmLetterTextView;

/**字母消息Handler**/
privateHandlermLetterhandler;

/**
*构造方法
*
*@paramcontext
*/
publicLetterListView(Contextcontext){
super(context);
initListView(context);
}

/**
*构造方法
*
*@paramcontext
*@paramattrs
*/
publicLetterListView(Contextcontext,AttributeSetattrs){
super(context,attrs);
initListView(context);
}

/**
*初始化内容列表字母列表
*
*@Description:
*@AuthorJustlcw
*@Date2014-5-7
*/
privatevoidinitListView(Contextcontext){
LayoutInflaterinflater=LayoutInflater.from(getContext());
//TODO这里添加内容列表,可以在这里对ListView进行一些你想要的设置
mListView=(ListView)inflater.inflate(R.layout.letter_list_container,null,false);
LayoutParamslp=newLayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
addView(mListView,lp);

//TODO这里添加字母列表,可以在这里对ListView进行一些你想要的设置
mLetterListView=(ListView)inflater.inflate(R.layout.letter_list_letter,null,false);
mLetterListView.setOnTouchListener(mLetterOnTouchListener);
LayoutParamsletterListLp=newLayoutParams(LETTER_LIST_VIEW_WIDTH,LayoutParams.MATCH_PARENT,Gravity.RIGHT);
addView(mLetterListView,letterListLp);

//TODO这里对显示的字母进行设置
mLetterTextView=(TextView)inflater.inflate(R.layout.letter_list_position,null,false);
LayoutParamsletterLp=newLayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT,Gravity.CENTER);
addView(mLetterTextView,letterLp);
mLetterTextView.setVisibility(View.INVISIBLE);

//初始化letter消息发送者
mLetterhandler=newLetterHandler(this);
}

/**
*设置内容列表适配器
*
*@paramadapter
*{@linkLetterBaseAdapter}
*@Description:
*@AuthorJustlcw
*@Date2014-5-7
*/
publicvoidsetAdapter(LetterBaseAdapteradapter){
if(adapter!=null){
mAdapter=adapter;
mListView.setAdapter(mAdapter);
}
}

/**
*{@linkAbsListView#setOnItemClickListener(OnItemClickListener)}
*
*@Description:
*@AuthorJustlcw
*@Date2014-5-14
*/
publicvoidsetOnItemClickListener(OnItemClickListeneronItemClickListener){
mListView.setOnItemClickListener(onItemClickListener);
}

@Override
protectedvoidonSizeChanged(intw,inth,intoldw,intoldh){
super.onSizeChanged(w,h,oldw,oldh);

mLetterAdapter=newLetterAdapter(h-getPaddingTop()-getPaddingBottom());
mLetterListView.setAdapter(mLetterAdapter);
}

/**
*显示字母
*
*@Description:
*@AuthorJustlcw
*@Date2014-5-8
*/
privatevoidshowLetter(Stringletter){
if(mLetterTextView.getVisibility()!=View.VISIBLE){
mLetterTextView.setVisibility(View.VISIBLE);
mLetterListView.setBackgroundResource(android.R.color.darker_gray);
}
mLetterTextView.setText(letter);

mLetterhandler.removeMessages(MSG_HIDE_LETTER);
mLetterhandler.sendEmptyMessageDelayed(MSG_HIDE_LETTER,500);
}

/**
*处理消息{@linkLetterHandler#handleMessage(Message)}
*
*@parammsg
*消息
*@Description:
*@AuthorJustlcw
*@Date2014-5-8
*/
privatevoidhandleLetterMessage(Messagemsg){
mLetterTextView.setVisibility(View.INVISIBLE);
mLetterListView.setBackgroundResource(android.R.color.white);
}

/**字母栏touch事件**/
privateView.OnTouchListenermLetterOnTouchListener=newView.OnTouchListener(){
@Override
publicbooleanonTouch(Viewv,MotionEventevent){
intheight=(int)event.getY()-v.getTop();

intposition=mLetterAdapter.getTouchPoistion(height);
if(position>=0){
charletter=(Character)mLetterAdapter.getItem(position);
//显示字母
showLetter(String.valueOf(letter));

//显示到字母对应的位置
intselect=mAdapter.getIndex(letter);
if(select>=0){
mListView.setSelection(select);
}
returntrue;
}
returnfalse;
}
};

/**
*字母列表设配器
*
*@Title:
*@Description:
*@Author:Justlcw
*@Since:2014-5-7
*@Version:
*/
privateclassLetterAdapterextendsBaseAdapter{
/**字母表**/
privatestaticfinalStringLETTER_STR="+ABCDEFGHIJKLMNOPQRSTUVWXYZ#";
/**最终显示的字母array**/
privatechar[]letterArray;
/**每个字母的高度**/
privateintitemHeight;

/**
*构造方法
*
*@paramheight
*viewheight
*/
publicLetterAdapter(intheight){
if(mAdapter.hideLetterNotMatch()){
List<Character>list=newArrayList<Character>();
char[]allArray=LETTER_STR.toCharArray();
for(inti=0;i<allArray.length;i++){
charletter=allArray[i];
intposition=mAdapter.getIndex(letter);
if(position>=0){
list.add(letter);
}
}
letterArray=newchar[list.size()];
for(inti=0;i<list.size();i++){
letterArray[i]=list.get(i);
}
list.clear();
list=null;
}else{
letterArray=LETTER_STR.toCharArray();
}
itemHeight=height/letterArray.length;
}

@Override
publicintgetCount(){
returnletterArray.length;
}

@Override
publicObjectgetItem(intposition){
returnletterArray[position];
}

@Override
publiclonggetItemId(intposition){
returnposition;
}

@Override
publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
if(convertView==null){
convertView=newTextView(getContext());
((TextView)convertView).setTextColor(getResources().getColor(android.R.color.black));
((TextView)convertView).setGravity(Gravity.CENTER);
AbsListView.LayoutParamslp=newAbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT,
itemHeight);
convertView.setLayoutParams(lp);
}
((TextView)convertView).setText(String.valueOf(letterArray[position]));

returnconvertView;
}

/**
*获取touch的位置
*
*@returnposition
*@Description:
*@AuthorJustlcw
*@Date2014-5-8
*/
publicintgetTouchPoistion(inttouchHeight){
intposition=touchHeight/itemHeight;
if(position>=0&&position<getCount()){
returnposition;
}
return-1;
}
}

/**
*处理字母显示的handler.
*
*@Title:
*@Description:
*@Author:Justlcw
*@Since:2014-5-8
*@Version:
*/
privatestaticclassLetterHandlerextendsHandler{
/**弱引用{@linkLetterListView}**/
privateSoftReference<LetterListView>srLetterListView;

/**
*构造方法
*
*@paramletterListView
*{@linkLetterListView}
*/
publicLetterHandler(LetterListViewletterListView){
srLetterListView=newSoftReference<LetterListView>(letterListView);
}

@Override
publicvoidhandleMessage(Messagemsg){
LetterListViewletterListView=srLetterListView.get();
//如果view没有被销毁掉,交给view处理这个消息
if(letterListView!=null){
letterListView.handleLetterMessage(msg);
}
}
}
}


packagecom.lixu.letterlistview.letter;

importnet.sourceforge.pinyin4j.PinyinHelper;

/**
*字母工具类
*@Title:
*@Description:
*@Author:Justlcw
*@Since:2014-5-8
*@Version:
*/
publicclassLetterUtil
{
/**
*@paramchinese一个汉字
*@return拼音首字母
*@Description:
*@AuthorJustlcw
*@Date2014-5-8
*/
publicstaticString[]getFirstPinyin(charchinese)
{
returnPinyinHelper.toHanyuPinyinStringArray(chinese);
}

/**
*是否是字母
*
*@returntrue字母,false非字母
*@Description:
*@AuthorJustlcw
*@Date2014-5-8
*/
publicstaticbooleanisLetter(charc)
{
return(c>=65&&c<=90)||(c>=97&&c<=112);
}
}


xml文件:

<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.lixu.letterlistview.letter.LetterListView
android:id="@+id/letterListView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.lixu.letterlistview.letter.LetterListView>

</RelativeLayout>


<?xmlversion="1.0"encoding="utf-8"?>
<ListViewxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="@android:color/transparent"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:scrollbars="none"/>


<?xmlversion="1.0"encoding="utf-8"?>
<ListViewxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f44336"
android:cacheColorHint="@android:color/transparent"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:scrollbars="none"/>


<?xmlversion="1.0"encoding="utf-8"?>
<TextViewxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#f44336"
android:gravity="center"
android:maxWidth="70dip"
android:minWidth="70dip"
android:padding="10dip"
android:textColor="@android:color/black"
android:textSize="50sp"/>


运行效果图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: