實現一個android撥號聯絡人
工作之餘搗鼓了一個類似安卓聯絡人的小應用,記錄一下。
能夠匯入手機上的聯絡人並按拼音首字母排序,實現字母的索引。
有的演算法很笨很麻煩,還得加油。
實現效果如下:
首先定義一個PeopleLoader類,用來讀取聯絡人相關的姓名、電話:
public class PeopleLoader {
private static List<PeopleInfo> peopleList = new ArrayList<PeopleInfo>();//儲存聯絡人物件的List
private static PeopleLoader peopleLoader;
private static ContentResolver contentResolver;//使用ContentResolver查詢需要的資料
private Uri contentUri = Contacts.CONTENT_URI;//該URI用來查詢聯絡人資訊
public static PeopleLoader instance(ContentResolver pContentResolver){
if(peopleLoader == null){
contentResolver = pContentResolver;
peopleLoader = new PeopleLoader();
}
return peopleLoader;
}
public List<PeopleInfo> getPeopleList(){
return sort(peopleList);
}
public String getPinYinHeadChar(String str) {//該方法用來獲取聯絡人姓名首個漢字的首個拼音,需要在專案中匯入pinyin4j的包
String convert = "";
char word = str.charAt(0);
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);
if(pinyinArray != null){
convert += pinyinArray[0].charAt(0);
}else{
convert += word;
}
return convert;
}
public List<PeopleInfo> sort(List<PeopleInfo> l){//對獲取的PeopleList重新排序
List<PeopleInfo> newList = new ArrayList<PeopleInfo>();
int[] position = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27};//該陣列是插入資料的標誌位0-26對應a-z、#
for(int i=0; i<27; i++){//該迴圈插入A-Z、#,聯絡人會根據首個拼音插在相應欄目下方
if(i!=26){
char A = (char) (65+i);
newList.add(new PeopleInfo(String.valueOf(A), String.valueOf(A)));
}else{
newList.add(new PeopleInfo("#", "#"));
}
}
for(int i=0; i<l.size(); i++){//將聯絡人插入相應欄目,應該注意各個標誌位的增加(希望有人能教我簡單點的方法,感覺很麻煩)
String first = getPinYinHeadChar(l.get(i).getName());
switch (first){
case "a":
newList.add(position[0], l.get(i));
newList.get(position[0]).setId("a");
for(int j=0; j<27; j++){
position[j]++;
}
break;
case "b":
newList.add(position[1], l.get(i));
newList.get(position[1]).setId("b");
for(int j=0; j<27; j++){
position[j]++;
}
break;
case "c":
newList.add(position[2], l.get(i));
newList.get(position[2]).setId("c");
for(int j=2; j<27; j++){
position[j]++;
}
break;
case "d":
newList.add(position[3], l.get(i));
newList.get(position[3]).setId("d");
for(int j=3; j<27; j++){
position[j]++;
}
break;
case "e":
newList.add(position[4], l.get(i));
newList.get(position[4]).setId("e");
for(int j=4; j<27; j++){
position[j]++;
}
break;
case "f":
newList.add(position[5], l.get(i));
newList.get(position[5]).setId("f");
for(int j=5; j<27; j++){
position[j]++;
}
break;
case "g":
newList.add(position[6], l.get(i));
newList.get(position[6]).setId("g");
for(int j=6; j<27; j++){
position[j]++;
}
break;
case "h":
newList.add(position[7], l.get(i));
newList.get(position[7]).setId("h");
for(int j=7; j<27; j++){
position[j]++;
}
break;
case "i":
newList.add(position[8], l.get(i));
newList.get(position[8]).setId("i");
for(int j=8; j<27; j++){
position[j]++;
}
break;
case "j":
newList.add(position[9], l.get(i));
newList.get(position[9]).setId("j");
for(int j=9; j<27; j++){
position[j]++;
}
break;
case "k":
newList.add(position[10], l.get(i));
newList.get(position[10]).setId("k");
for(int j=10; j<27; j++){
position[j]++;
}
break;
case "l":
newList.add(position[11], l.get(i));
newList.get(position[11]).setId("l");
for(int j=11; j<27; j++){
position[j]++;
}
break;
case "m":
newList.add(position[12], l.get(i));
newList.get(position[12]).setId("m");
for(int j=12; j<27; j++){
position[j]++;
}
break;
case "n":
newList.add(position[13], l.get(i));
newList.get(position[13]).setId("n");
for(int j=13; j<27; j++){
position[j]++;
}
break;
case "o":
newList.add(position[14], l.get(i));
newList.get(position[14]).setId("o");
for(int j=14; j<27; j++){
position[j]++;
}
break;
case "p":
newList.add(position[15], l.get(i));
newList.get(position[15]).setId("p");
for(int j=15; j<27; j++){
position[j]++;
}
break;
case "q":
newList.add(position[16], l.get(i));
newList.get(position[16]).setId("q");
for(int j=16; j<27; j++){
position[j]++;
}
break;
case "r":
newList.add(position[17], l.get(i));
newList.get(position[17]).setId("r");
for(int j=17; j<27; j++){
position[j]++;
}
break;
case "s":
newList.add(position[18], l.get(i));
newList.get(position[18]).setId("s");
for(int j=18; j<27; j++){
position[j]++;
}
break;
case "t":
newList.add(position[19], l.get(i));
newList.get(position[19]).setId("t");
for(int j=19; j<27; j++){
position[j]++;
}
break;
case "u":
newList.add(position[20], l.get(i));
newList.get(position[20]).setId("u");
for(int j=20; j<27; j++){
position[j]++;
}
break;
case "v":
newList.add(position[21], l.get(i));
newList.get(position[21]).setId("v");
for(int j=21; j<27; j++){
position[j]++;
}
break;
case "w":
newList.add(position[22], l.get(i));
newList.get(position[22]).setId("w");
for(int j=22; j<27; j++){
position[j]++;
}
break;
case "x":
newList.add(position[23], l.get(i));
newList.get(position[23]).setId("x");
for(int j=23; j<27; j++){
position[j]++;
}
break;
case "y":
newList.add(position[24], l.get(i));
newList.get(position[24]).setId("y");
for(int j=24; j<27; j++){
position[j]++;
}
break;
case "z":
newList.add(position[25], l.get(i));
newList.get(position[25]).setId("z");
for(int j=25; j<27; j++){
position[j]++;
}
break;
default:
newList.add(position[26], l.get(i));
newList.get(position[26]).setId("#");
position[26]++;
break;
}
}
return newList;//返回排序後的PeopleList
}
private PeopleLoader(){
Cursor cursor = contentResolver.query(contentUri, new String[]{Contacts._ID,Contacts.DISPLAY_NAME}, null, null, null);//獲得所有聯絡人遊標
if(cursor == null){//判斷遊標
}else if(!cursor.moveToFirst()){//將遊標返回到第一項,可以不用else if
}else{
int mName = cursor.getColumnIndex(Contacts.DISPLAY_NAME);//獲取聯絡人名字所在列號
do{//將所有資料存入PeopleList
String name = cursor.getString(mName);//根據列號獲取名字
int ID = cursor.getInt(cursor.getColumnIndex(Contacts._ID));//根據聯絡人id列號獲取聯絡人id
Cursor c1 = contentResolver.query(Phone.CONTENT_URI, new String[]{Phone.NUMBER},
Phone.CONTACT_ID+"="+ID, null, null);//根據id獲取聯絡人電話
PeopleInfo peopleInfo = new PeopleInfo("", name);//以下插入資料到PeopleList
if(c1!=null){
while(c1.moveToNext()){
peopleInfo.setPhone(c1.getString(c1.getColumnIndex(Phone.NUMBER)));
}
}
//peopleInfo.setPhone(c1.getString(c1.getColumnIndex(Phone.NUMBER)));
peopleList.add(peopleInfo);
}while(cursor.moveToNext());
}
cursor.close();
}
//PeopleInfo實現parcelable介面,用來儲存聯絡人的資訊:
static class PeopleInfo implements Parcelable{
private String name;
private String phone;
private String id;//此處id值是後面判斷的一個標誌
public String getId(){
return id;
}
public String getName(){
return name;
}
public String getPhone(){
return phone;
}
public PeopleInfo(){
}
public PeopleInfo(String pId, String pName){
id = pId;
name = pName;
}
public void setId(String id){
this.id = id;
}
public void setName(String name){
this.name = name;
}
public void setPhone(String phone){
this.phone = phone;
}
//要實現的三個方法
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeString(id);
dest.writeString(name);
dest.writeString(phone);
}
public static final Parcelable.Creator<PeopleInfo>
CREATOR = new Creator<PeopleLoader.PeopleInfo>(){
@Override
public PeopleInfo createFromParcel(Parcel source) {
// TODO Auto-generated method stub
PeopleInfo peopleInfo = new PeopleInfo();
peopleInfo.setId(source.readString());
peopleInfo.setName(source.readString());
peopleInfo.setPhone(source.readString());
return peopleInfo;
}
@Override
public PeopleInfo[] newArray(int size) {
// TODO Auto-generated method stub
return new PeopleInfo[size];
}
};
}
}
MainActivity中程式碼如下:
public class MainActivity extends Activity {
private GroupListAdapter adapter = null;
private ListView listView = null;
public List<String> listName = new ArrayList<String>();
public static List<String> listPhone = new ArrayList<String>();
private List<PeopleInfo> peopleList;
private LinearLayout layoutIndex;
private boolean flag = false;
private int height;
private String[] indexStr = {"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", "#" };
class GroupListAdapter extends BaseAdapter{//定義一個介面卡繼承BaseAdapter
private View.OnClickListener myListener = new View.OnClickListener() {//實現一個OnClickListener用來監聽點選的物件,避免重複new多個監聽器
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent();
if(v.getId() == R.id.ivPhn){//根據id判斷是撥號還是發簡訊
intent.setAction(Intent.ACTION_CALL);
}else{
intent.setAction(Intent.ACTION_SENDTO);
//intent.putExtra("smsto:", "Hello");
}
intent.setData(Uri.parse(v.getTag().toString()));//去除Tag中存入的相應Uri
startActivity(intent);
}
};
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null){
convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.group_list_item,null);
ImageView photo = (ImageView) convertView.findViewById(R.id.iv);
TextView name = (TextView) convertView.findViewById(R.id.name);
TextView phone = (TextView) convertView.findViewById(R.id.phone);
ImageView btnCall = (ImageView) convertView.findViewById(R.id.ivPhn);
ImageView btnMsg = (ImageView) convertView.findViewById(R.id.ivMsg);
viewHolder = new ViewHolder(photo, name, phone, btnCall, btnMsg);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder)convertView.getTag();
}
if(peopleList.get(position).getName().length()==1){//判斷是不是A-Z、#等欄目標題(此處應該有更得體的方法而不是簡單的判定長度,畢竟使用者也有可能輸入長度為1的物件)
viewHolder.name.setText(peopleList.get(position).getName());//設定完顯示的A-Z、#字母后,簡單的將其他物件置為空,應該可以用setVisible一類的方法讓其直接消失
viewHolder.phone.setText(null);
viewHolder.photo.setImageResource(0);
viewHolder.btnCall.setImageResource(0);
viewHolder.btnMsg.setImageResource(0);
viewHolder.btnCall.setOnClickListener(null);
viewHolder.btnMsg.setOnClickListener(null);
viewHolder.name.setTextSize(40);
}else{//不是字母標題欄則插入相應聯絡人資料
viewHolder.name.setTextSize(15);
viewHolder.photo.setImageResource(0);
//viewHolder.photo.setImageResource(R.drawable.list_icon);
viewHolder.btnCall.setImageResource(R.drawable.call);
viewHolder.btnMsg.setImageResource(R.drawable.msg);
viewHolder.name.setText(peopleList.get(position).getName());
viewHolder.phone.setText(peopleList.get(position).getPhone());
viewHolder.btnCall.setTag( "tel:"+peopleList.get(position).getPhone());//將撥號、發簡訊要用到的資料存入Tag
viewHolder.btnMsg.setTag( "smsto:"+peopleList.get(position).getPhone());
viewHolder.btnCall.setOnClickListener(myListener);//設定監聽
viewHolder.btnMsg.setOnClickListener(myListener);
}
return convertView;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return peopleList.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return peopleList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
}
class ViewHolder{
public ViewHolder(ImageView photo,TextView name, TextView phone, ImageView call, ImageView msg){
this.photo = photo;
this.name = name;
this.phone = phone;
this.btnCall = call;
this.btnMsg = msg;
}
ImageView photo;
TextView name;
TextView phone;
ImageView btnCall;
ImageView btnMsg;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layoutIndex = (LinearLayout)findViewById(R.id.layout); //該layout用來插入右側字母索引
PeopleLoader peopleLoader = PeopleLoader.instance(getContentResolver());
peopleList = peopleLoader.getPeopleList();
adapter = new GroupListAdapter();
listView = (ListView)findViewById(R.id.group_list);
listView.setAdapter(adapter);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (!flag) {// flag確保if內容只執行一次,避免重複操作
height = layoutIndex.getMeasuredHeight() / indexStr.length;
//高度/資料項數目得到每個TextView的長寬
getIndexView();
flag = true;
}
}
private void getIndexView() {
// TODO Auto-generated method stub
LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, height);
for (int i = 0; i < indexStr.length; i++) {
//此迴圈插入字母索引
final TextView tv = new TextView(this);
tv.setLayoutParams(params); //設定插入TextView引數
tv.setText(indexStr[i]);
tv.setPadding(10, 0, 10, 0);
layoutIndex.addView(tv);
layoutIndex.setOnTouchListener(new OnTouchListener() {
//設定監聽,讓觸控某個字母索引時,ListView定位到相應字母欄
@Override
public boolean onTouch(View v, MotionEvent event)
{
float y = event.getY();
int index = (int) (y / height);
if (index > -1 && index < indexStr.length) {// 防止越界
String key = indexStr[index];
for(int i=0; i<peopleList.size(); i++){
if(peopleList.get(i).getName().equalsIgnoreCase(key)&&peopleList.get(i).getId().equalsIgnoreCase(key)){//找到相應的字母欄(此處應有簡單方法,很麻煩)
listView.setSelectionFromTop(i, 0); // 滑動到第一項
break;
}
}
}
return true;
}
});
}
}
}
學到了contentresolver物件、Parcelable介面、介面卡的使用,listview的佈局,根據拼音首字母的索引,側邊索引的實現。
佈局檔案沒貼了,下載連結http://download.csdn.net/detail/u012951394/8938043
相關推薦
實現一個android撥號聯絡人
工作之餘搗鼓了一個類似安卓聯絡人的小應用,記錄一下。 能夠匯入手機上的聯絡人並按拼音首字母排序,實現字母的索引。 有的演算法很笨很麻煩,還得加油。 實現效果如下: 首先定義一個PeopleLoader類,用來讀取聯絡人相關的姓名、電話: public class
Android App實現點選撥號、複製剪貼簿、新增手機聯絡人
1.概述 今天介紹一下實現Android App內實現點選撥號、複製剪貼簿、新增手機聯絡人等相關操作 2.實現效果 沒有gif圖 3.實現步驟 直接上程式碼: private void initService() { String[] info = n
Android實現一個自己定義相機的界面
content pic 圖片 log das img lis boolean xtend 我們先實現拍照button的圓形效果哈。Android開發中,當然能夠找美工人員設計圖片,然後直接拿進來。只是我們能夠自己寫代碼實現這個效果哈。最經常使用的的是用layout-
TitleLayout——一個Android輕松實現通用、標準、支持沈浸式狀態欄的標題欄庫
sub blog uri IT 特殊 java代碼 ber ext tar TitleLayout 多功能、通用的、可在布局或者使用Java代碼實現標題欄;支持沈浸式狀態欄,支持左側返回按鈕(不需要手動實現頁面返回),左側支持圖片+文字、圖片、文字;右側支持圖片、文字等。
在Android中實現一個簡易的Http服務器
.get json data ESS public 瀏覽器 顯示 getmethod blank 最近遇到一個需求需要在App中創建一個Http服務器供供瀏覽器調用,用了下開源的微型Htpp服務器框架:NanoHttpd,項目地址:https://github.com/Na
android實踐的一些思考:實現一個MVP架構設計
MVP是從MVC架構演變而來的,目的是為了使得程式開發高內聚低耦合,易於擴充套件,方便維護。 MVC中的M指的是model模型, V 指的是View檢視,C指的是Controller。 MVC 大體的思想是,控制器控
用TextView實現一個簡單的Android資訊顯示工具
本文用 TextView 實現一個在手機上顯示 Android 資訊的工具類。比如涉及到訊號的傳遞時,那種類似日誌記錄的功能。先看圖: 先看佈局檔案的程式碼,注意 TextView 裡面的幾個屬性就可以了。 <?xml version="1.0" encoding="utf-8"
Android下實現一個簡單的計算器原始碼
下面的內容是關於Android下實現一個簡單的計算器的內容。 import android.app.Activity; import android.os.Bundle;import android.view.View;import android.widget.Button;import android.w
在一個Android專案裡面有兩個可執行檔案,如何實現呼叫方式
我的處理方式是: 用Intent+AndroidManifest.xml的方法: 此方法是用Intent和修改AndroidManifest.xml達成的。 就是在要引用的AndroidManifest.xml檔案裡面加入被引用那個專案的activity: <activity
【Android】三行程式碼實現一個輪播BannerView
自己簡單封裝了一個帶hint的輪播ViewPager,用來展示app首頁的Banner,先看效果圖吧。 ezgif-1-437f7aee24.gif dependencies(依賴) compile 'com.coldmoqiuli:banners:1.0.0'
Android-實現一個簡單的自動翻譯外掛
實現一個簡單的自動翻譯外掛 最近在開發專案是要將Android相關的資源進行國際化,需要將values目錄中所有相關的字串資源(中文),生成匹配的一套英文且儲存在values-en目錄;當然國際化不僅僅是要英文還要提供臺灣等其他語言,這裡為了演示方便,只說下如
Android系統聯絡人全特效實現 下 ,字母表快速滾動
在上一篇文章中,我和大家一起實現了類似於Android系統聯絡人的分組導航和擠壓動畫功能,不過既然文章名叫做《Android系統聯絡人全特效實現》,那麼沒有快速滾動功能顯然是稱不上"全"的。因此本篇文章我將帶領大家在上篇文章的程式碼基礎上改進,加入快速滾動功能。其實ListVi
一個Android文字輪播控制元件,實現了可垂直跑、可水平跑的跑馬燈
Android文字輪播控制元件 現在的絕大數APP特別是類似淘寶京東等這些大型APP都有文字輪播介面,實現迴圈輪播多個廣告詞等功能;這種控制元件俗稱“跑馬燈”,而TextBannerView已經實現了可垂直跑、可水平跑的跑馬燈了。 效果圖 Attribute
Android 實現一個簡易橫向流式佈局
SimpleFlowLayout:一個簡易的橫向流式佈局,只實現核心功能,使用者可自行擴充套件 Demo圖片如下所示: SimpleFlowLayout直接繼承自ViewGroup,主要負責
開放一份自己實現的Android版智慧撥號器
1、 顯示聯絡人列表(點選列表,快速撥號) 2、 不同的搜尋方式(漢字模糊匹配,按姓氏分組,中文拼音縮寫查詢如張三,ws,全拼查詢 zhangsan) 3、 語音撥號(支援命令:撥打電話,打給xxx,打電話給xxx,傳送簡訊) 4、 簡訊
Android示例程式碼:如何實現一個文字列表
轉載自碼農場:Android示例程式碼:如何實現一個文字列表 在Android應用中,ListView是一個非常有用的控制元件。由於Android手機和普通Android平板電腦的螢幕尺寸有限,我們需要使用列表在有限的空間中顯示足夠都的內容。ListView非常容易使用,並且我們可以自定
Android開發自定義控制元件實現一個圓形進度條【帶數值和動畫】
實現一個如下圖所示的自定義控制元件,可以直觀地展示某個球隊在某個賽季的積分數和勝場、負場、平局數 首先對畫布進行區域劃分,整個控制元件分上下兩部分 上邊是個大的圓環,圓環中間兩行文字,沒什麼難度,選好圓心座標和半徑後直接繪製即可,繪製文字也是如此。 下部分是三個小的圓弧進
第一個Android專案--簡易計算器的設計與實現
這個簡易計算器的實現我是參照慕課網上的視訊課程學習的,下面梳理我的開發過程以及DEBUG 在這個專案中實現計算器的第一步驟是對介面UI的設計,UI的設計並不難,一個總的Lnearlayout的佈局下orientation設定為verti
android 實現城市選擇、聯絡人等功能的易拓展 RecyclerView 庫,包含自動索引,粘性等功能
A RecyclerView with indexable, sticky and many other features. 輕鬆實現:選擇城市,選擇聯絡人等需要索引的功能 替代之前的 IndexableStickyListView(移至該分支),進行大幅度重構,效能優化,更易使用的 API,更易拓展的
Android 基於Socket的長連線實現一個實時推送的功能
實現此功能需要考慮的幾點: 1)如何保證Socket長連線一直存在並有效執行 2)通過Service執行Socket,當服務端有資料時,通過廣播或者handler來更新UI 具體效果,來上程式碼: @Override public void run() { try