HTTP://www.uml.org.cn/mobiledev/201110121.asp

 

HTTP://blog.csdn.net/jiahui524/article/details/7785606

 

感謝這兩位的博客:






模仿微信好友清單功能(數據從手機中讀取),實現漢首字母排序篩選:

 

用到了一個pinyin4j-2.5.0.jar這個包




這個包的介紹:HTTP://sourceforge.net/projects/pinyin4j/files/




其中還有一個 ContentResolver的知識點:

 

HTTP://www.cnblogs.com/ruiyi1987/archive/2011/06/20/2084925.html




這篇文章中用到這樣一個查詢條件:

 

String[] proj1=new String[]{ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts.LOOKUP_KEY};

 

ContactsContract.Contacts已經不推薦使用,現在推薦使用phone




下面是代碼:




main.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="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="@+id/llParent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/lvShow"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<TextView
android:id="@+id/tvLetter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/show_head_toast_bg"
android:gravity="center"
android:maxWidth="70dip"
android:minWidth="70dip"
android:padding="10dip"
android:textColor="#99FFFFFF"
android:textSize="50sp" >
</TextView>
<mypack.aaron.conact.MySideBar
android:id="@+id/myView"
android:layout_width="30dip"
android:layout_height="fill_parent"
android:layout_gravity="right" >
</mypack.aaron.conact.MySideBar>
</FrameLayout>
</LinearLayout>

 

list_item.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:descendantFocusability="blocksDescendants"
android:orientation="vertical">
<TextView
android:id="@+id/tv_catalog"
style="@style/MMListCatalog"
android:layout_height="wrap_content"
android:paddingRight="4.0dip" />
<LinearLayout
android:id="@+id/contactitem_layout"
style="@style/MMListItem"
android:layout_height="56.0dip"
android:background="@drawable/mm_listitem"
android:paddingLeft="8.0dip" >
<ImageView
android:id="@+id/contactitem_avatar_iv"
android:layout_width="40.0dip"
android:layout_height="40.0dip" android:src="@drawable/default_avatar" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:orientation="vertical"
android:paddingLeft="8.0dip" >
<TextView
android:id="@+id/tv_nick"
style="@style/MMFontTitleInList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true" android:text="姓名" />
<TextView
android:id="@+id/tv_mobile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="13123456789"
android:textColor="#666666" />
</LinearLayout>
<ImageButton
android:id="@+id/imgbtn_nav"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="5dip"
android:background="@drawable/nav_left"
android:focusable="false"
android:focusableInTouchMode="false" />
</LinearLayout>
</LinearLayout>

 

style.xml



<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 聯系分組樣式 -->
<style name="MMListItem">
<item name="android:gravity">center_vertical</item>
<item name="android:orientation">horizontal</item>
<item name="android:paddingLeft">4.0dip</item>
<item name="android:paddingTop">4.0dip</item>
<item name="android:paddingRight">4.0dip</item>
<item name="android:paddingBottom">4.0dip</item>
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>

 

<style name="MMFriendListItem">
<item name="android:gravity">center_vertical</item>
<item name="android:orientation">horizontal</item>
<item name="android:paddingLeft">16.0dip</item>
<item name="android:paddingTop">6.0dip</item>
<item name="android:paddingRight">6.0dip</item>
<item name="android:paddingBottom">6.0dip</item>
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>

<style name="MMListCatalog">
<item name="android:textSize">14.0dip</item>
<item name="android:textStyle">bold</item>
<item name="android:textColor">#ff595c61</item>
<item name="android:gravity">center_vertical</item>
<item name="android:orientation">horizontal</item>
<item name="android:background">#ffced2d7</item>
<item name="android:paddingLeft">10.0dip</item>
<item name="android:paddingTop">2.0dip</item>
<item name="android:paddingBottom">2.0dip</item>
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="MMFontTitleInList">
<item name="android:textSize">16.0dip</item>
<item name="android:textColor">#ff595c61</item>
<item name="android:ellipsize">end</item>
<item name="android:gravity">center_vertical</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:singleLine">true</item>
</style>

<style name="MMFontTipInList">
<item name="android:textSize">14.0dip</item>
<item name="android:textColor">#fff</item>
<item name="android:ellipsize">end</item>
<item name="android:gravity">center_vertical</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:singleLine">true</item>
</style>
</resources>

PinyinUtils.java

這個java檔是生成漢字首字母拼音



public class PinyinUtils {
// 獲得漢語拼音首字母
public static String getAlpha(String chines) {
String pinyinName = "";
char[] nameChar = chines.toCharArray();
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
for (int i = 0; i < nameChar.length; i++) {
if (nameChar[i] > 128) {
try {
pinyinName += PinyinHelper.toHanyuPinyinStringArray(
nameChar[i], defaultFormat)[0].charAt(0);
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
} else {
pinyinName += nameChar[i];
}
}
return pinyinName;
}

/**
* 將字串中的中文轉化為拼音,其他字元不變
*
* @param inputString
* @return
*/
public static String getPingYin(String inputString) {
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
format.setVCharType(HanyuPinyinVCharType.WITH_V);

char[] input = inputString.trim().toCharArray();
String output = "";

try {
for (int i = 0; i < input.length; i++) {
if (java.lang.Character.toString(input[i]).matches(
"[\\u4E00-\\u9FA5]+")) {
String[] temp = PinyinHelper.toHanyuPinyinStringArray(
input[i], format);
output += temp[0];
} else
output += java.lang.Character.toString(input[i]);
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
return output;
}

/**
* 漢字轉換位漢語拼音首字母,英文字元不變
*
* @param chines
* 漢字
* @return 拼音
*/
public static String converterToFirstSpell(String chines) {
String pinyinName = "";
char[] nameChar = chines.toCharArray();
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
for (int i = 0; i < nameChar.length; i++) {
if (nameChar[i] > 128) {
try {
pinyinName += PinyinHelper.toHanyuPinyinStringArray(
nameChar[i], defaultFormat)[0].charAt(0);
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
} else {
pinyinName += nameChar[i];
}
}
return pinyinName;
}
}

MySideBar.java

右邊拼音


public class MySideBar extends View{
OnTouchingLetterChangedListener onTouchingLetterChangedListener;
// 26個字母
public static String[] b = { "#", "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" };
int choose = -1;
Paint paint = new Paint();

public MySideBar(CoNtext coNtext, AttributeSet attrs, int defStyle) {
super(coNtext, attrs, defStyle);
}

public MySideBar(CoNtext coNtext, AttributeSet attrs) {
super(coNtext, attrs);
}

public MySideBar(CoNtext coNtext) {
super(coNtext);
}

/**
* 重寫這個方法
*/
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (showBkg) {
canvas.drawColor(Color.parseColor("#40000000"));
}

int height = getHeight();
int width = getWidth();
int singleHeight = height / b.length;
for (int i = 0; i < b.length; i++) {
paint.setColor(Color.BLACK);
// paint.setColor(Color.WHITE);
paint.setTypeface(Typeface.DEFAULT_BOLD);
paint.setAntiAlias(true);
paint.setTextSize(20);
if (i == choose) {
paint.setColor(Color.parseColor("#3399ff"));
paint.setFakeBoldText(true);
}
float xPos = width / 2 - paint.measureText(b[i]) / 2;
float yPos = singleHeight * i + singleHeight;
canvas.drawText(b[i], xPos, yPos, paint);
paint.reset();
}

}

private boolean showBkg = false;

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
final int action = event.getAction();
final float y = event.getY();
final int oldChoose = choose;
final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
final int c = (int) (y / getHeight() * b.length);

switch (action) {
case MotionEvent.ACTION_DOWN:
showBkg = true;
if (oldChoose != c && listener != null) {
if (c > 0 && c < b.length) {
listener.onTouchingLetterChanged(b[c]);
choose = c;
invalidate();
}
}

break;
case MotionEvent.ACTION_MOVE:
if (oldChoose != c && listener != null) {
if (c > 0 && c < b.length) {
listener.onTouchingLetterChanged(b[c]);
choose = c;
invalidate();
}
}
break;
case MotionEvent.ACTION_UP:
showBkg = false;
choose = -1;
invalidate();
break;
}
return true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}

/**
* 向外公開的方法
*
* @param onTouchingLetterChangedListener
*/
public void setOnTouchingLetterChangedListener(
OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
}

/**
* 介面
*
* @author coder
*
*/
public interface OnTouchingLetterChangedListener {
public void onTouchingLetterChanged(String s);
}
}

最後就是activity:


public class ContactsActivity extends Activity implements OnTouchingLetterChangedListener {
private ListView lv_list;
/**聯系人顯示名稱**/
private static final int PHONES_DISPLAY_NAME_INDEX = 0;
/**電話號碼**/
private static final int PHONES_NUMBER_INDEX = 1;
/**頭像ID**/
private static final int PHONES_PHOTO_ID_INDEX = 2;
/**聯系人的ID**/
private static final int PHONES_CONTACT_ID_INDEX = 3;
/**聯系人名稱**/
private ArrayList<String> mContactsName = new ArrayList<String>();
/**聯系人頭像**/
private ArrayList<String> mContactsNumber = new ArrayList<String>();
/**聯系人頭像**/
private ArrayList<Bitmap> mContactsPhonto = new ArrayList<Bitmap>();
/**拼音**/
private ArrayList<String> mPy=new ArrayList<String>();
/**左側拼音字母**/
private MySideBar myView;
/**顯示到螢幕中間的拼音**/
private TextView overlay;

private OverlayThread overlayThread = new OverlayThread();

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv_list=(ListView)findViewById(R.id.lv_lsit);
overlay=(TextView)findViewById(R.id.tvLetter);

lv_list.setTextFilterEnabled(true);
overlay.setVisibility(View.INVISIBLE);//默認隱藏


myView = (MySideBar) findViewById(R.id.myView);
myView.setOnTouchingLetterChangedListener(this);


ContentResolver resolver = getContentResolver();
String[] proj1=new String[]{Phone.DISPLAY_NAME,
Phone.NUMBER,Phone.PHOTO_ID,Phone.CONTACT_ID,
};
Cursor curContacts=resolver.query(Phone.CONTENT_URI,proj1, null, null, null);
if(curContacts.getCount()>0){
while(curContacts.moveToNext()){
//得到手機號碼
String phoneNumber = curContacts.getString(PHONES_NUMBER_INDEX);
//當手機號碼為空的或者為空欄位 跳過當前循環

if (TextUtils.isEmpty(phoneNumber)){
continue;
}
//得到聯系人名稱

String contactName = curContacts.getString(PHONES_DISPLAY_NAME_INDEX);
//拼音
String py=PinyinUtils.getAlpha(contactName);

//得到聯系人ID

Long contactid = curContacts.getLong(PHONES_CONTACT_ID_INDEX);

//得到聯系人頭像ID

Long photoid = curContacts.getLong(PHONES_PHOTO_ID_INDEX);

//得到聯系人頭像Bitamp

Bitmap contactPhoto = null;

//photoid 大於0 表示聯系人有頭像 如果沒有給此人設置頭像則給他一個默認的
 


if(photoid > 0 ) {

Uri uri =ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,contactid);

InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(resolver, uri);

contactPhoto = BitmapFactory.decodeStream(input);

}else {

contactPhoto = BitmapFactory.decodeResource(getResources(), R.drawable.contact_photo);

}
mContactsName.add(contactName);
mContactsPhonto.add(contactPhoto);
mContactsNumber.add(phoneNumber);
mPy.add(py);



}
curContacts.close();
}
ListViewAdapter ltAdapter=new ListViewAdapter();
lv_list.setAdapter(ltAdapter);
}
/**綁定數據**/
public class ListViewAdapter extends BaseAdapter{


@Override
public int getCount() {
// TODO Auto-generated method stub
return mContactsName.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater =getLayoutInflater();

// 使用View的對象itemView與R.layout.item關聯
if(convertView==null){
convertView=inflater.inflate(R.layout.list_item, null);
}

// 通過findViewById()方法實例R.layout.item內各組件
TextView tvName = (TextView) convertView.findViewById(R.id.tv_nick);
TextView tvPhone=(TextView) convertView.findViewById(R.id.tv_mobile);
ImageView iv_pic = (ImageView) convertView.findViewById(R.id.contactitem_avatar_iv);
TextView tv_catalog=(TextView)convertView.findViewById(R.id.tv_catalog);

/*首字拼音*/
String catalog = PinyinUtils.converterToFirstSpell(mContactsName.get(position).substring(0, 1));

if(position==0){
tv_catalog.setVisibility(View.VISIBLE);
tv_catalog.setText(catalog);
}else {
/*下一個漢字首字拼音,如果兩個漢字的首字母相等,下一個漢字的tv_catalog隱藏,這裏其實就是把相同首字母的漢字疊加在一起*/
String lastCatalog = PinyinUtils.converterToFirstSpell(mContactsName.get(position - 1)).substring(0,1);
if (catalog.equals(lastCatalog)) {
tv_catalog.setVisibility(View.GONE);
} else {
tv_catalog.setVisibility(View.VISIBLE);
tv_catalog.setText(catalog);
}
}

tvName.setText(mContactsName.get(position));
iv_pic.setImageBitmap(mContactsPhonto.get(position));
tvPhone.setText(mContactsNumber.get(position));
return convertView;
}
}
/*下面是觸摸左側拼音*/

private Handler handler = new Handler() {
};

private class OverlayThread implements Runnable {

public void run() {
overlay.setVisibility(View.GONE);
}

}

/**字母觸摸事件**/
@Override
public void onTouchingLetterChanged(String s) {
Log.i("coder", "s:" + s);

overlay.setText(s);
overlay.setVisibility(View.VISIBLE);
handler.removeCallbacks(overlayThread);
handler.postDelayed(overlayThread, 1000);
if (AlphaIndexer(s) > 0) {
int position = AlphaIndexer(s);
Log.i("coder", "position:" + position);
lv_list.setSelection(position);

}
}
//根據 字母的值找到mPy存儲的漢字首字母拼音的索引,listView中根據這個索引定位顯示
public int AlphaIndexer(String s) {
int position = 0;
for (int i = 0; i < mContactsPhonto.size(); i++) {
if (mPy.get(i).startsWith(s)) {
position = i;
break;
}
}
Log.i("coder", "i" + position + mPy.get(position));
return position;
}

}
經過了手機測試成功,代碼比較臃腫,還沒有實現輸入篩選條件查詢,正在研究中
 
 
創作者介紹
創作者 shadow 的頭像
shadow

資訊園

shadow 發表在 痞客邦 留言(0) 人氣()