Android手机联系人带字母索引的快速查找

喜欢另辟蹊径的我,在这里废话不多说了,直接上代码和图片了。
效果图如下:

第一步:MainActivity的代码如下:

package net.loonggg.test; 

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.TreeSet; 

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.LinearLayout.LayoutParams; 

public class MainActivity extends Activity {
  private HashMap<String, Integer> selector;// 存放含有索引字母的位置
  private LinearLayout layoutIndex;
  private ListView listView;
  private TextView tv_show;
  private ListViewAdapter adapter;
  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" };
  private List<Person> persons = null;
  private List<Person> newPersons = new ArrayList<Person>();
  private int height;// 字体高度
  private boolean flag = false; 

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 去标题栏
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_main);
    layoutIndex = (LinearLayout) this.findViewById(R.id.layout);
    layoutIndex.setBackgroundColor(Color.parseColor("#00ffffff"));
    listView = (ListView) findViewById(R.id.listView);
    tv_show = (TextView) findViewById(R.id.tv);
    tv_show.setVisibility(View.GONE);
    setData();
    String[] allNames = sortIndex(persons);
    sortList(allNames); 

    selector = new HashMap<String, Integer>();
    for (int j = 0; j < indexStr.length; j++) {// 循环字母表,找出newPersons中对应字母的位置
      for (int i = 0; i < newPersons.size(); i++) {
        if (newPersons.get(i).getName().equals(indexStr[j])) {
          selector.put(indexStr[j], i);
        }
      } 

    }
    adapter = new ListViewAdapter(this, newPersons);
    listView.setAdapter(adapter);
  } 

  /**
   * 重新排序获得一个新的List集合
   *
   * @param allNames
   */
  private void sortList(String[] allNames) {
    for (int i = 0; i < allNames.length; i++) {
      if (allNames[i].length() != 1) {
        for (int j = 0; j < persons.size(); j++) {
          if (allNames[i].equals(persons.get(j).getPinYinName())) {
            Person p = new Person(persons.get(j).getName(), persons
                .get(j).getPinYinName());
            newPersons.add(p);
          }
        }
      } else {
        newPersons.add(new Person(allNames[i]));
      }
    }
  } 

  @Override
  public void onWindowFocusChanged(boolean hasFocus) {
    // 在oncreate里面执行下面的代码没反应,因为oncreate里面得到的getHeight=0
    if (!flag) {// 这里为什么要设置个flag进行标记,我这里不先告诉你们,请读者研究,因为这对你们以后的开发有好处
      height = layoutIndex.getMeasuredHeight() / indexStr.length;
      getIndexView();
      flag = true;
    }
  } 

  /**
   * 获取排序后的新数据
   *
   * @param persons
   * @return
   */
  public String[] sortIndex(List<Person> persons) {
    TreeSet<String> set = new TreeSet<String>();
    // 获取初始化数据源中的首字母,添加到set中
    for (Person person : persons) {
      set.add(StringHelper.getPinYinHeadChar(person.getName()).substring(
          0, 1));
    }
    // 新数组的长度为原数据加上set的大小
    String[] names = new String[persons.size() + set.size()];
    int i = 0;
    for (String string : set) {
      names[i] = string;
      i++;
    }
    String[] pinYinNames = new String[persons.size()];
    for (int j = 0; j < persons.size(); j++) {
      persons.get(j).setPinYinName(
          StringHelper
              .getPingYin(persons.get(j).getName().toString()));
      pinYinNames[j] = StringHelper.getPingYin(persons.get(j).getName()
          .toString());
    }
    // 将原数据拷贝到新数据中
    System.arraycopy(pinYinNames, 0, names, set.size(), pinYinNames.length);
    // 自动按照首字母排序
    Arrays.sort(names, String.CASE_INSENSITIVE_ORDER);
    return names;
  } 

  /**
   * 绘制索引列表
   */
  public void getIndexView() {
    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);
      tv.setText(indexStr[i]);
      tv.setPadding(10, 0, 10, 0);
      layoutIndex.addView(tv);
      layoutIndex.setOnTouchListener(new OnTouchListener() { 

        @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];
            if (selector.containsKey(key)) {
              int pos = selector.get(key);
              if (listView.getHeaderViewsCount() > 0) {// 防止ListView有标题栏,本例中没有。
                listView.setSelectionFromTop(
                    pos + listView.getHeaderViewsCount(), 0);
              } else {
                listView.setSelectionFromTop(pos, 0);// 滑动到第一项
              }
              tv_show.setVisibility(View.VISIBLE);
              tv_show.setText(indexStr[index]);
            }
          }
          switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
            layoutIndex.setBackgroundColor(Color
                .parseColor("#606060"));
            break; 

          case MotionEvent.ACTION_MOVE: 

            break;
          case MotionEvent.ACTION_UP:
            layoutIndex.setBackgroundColor(Color
                .parseColor("#00ffffff"));
            tv_show.setVisibility(View.GONE);
            break;
          }
          return true;
        }
      });
    }
  } 

  /**
   * 设置模拟数据
   */
  private void setData() {
    persons = new ArrayList<Person>();
    Person p1 = new Person("耿琦");
    persons.add(p1);
    Person p2 = new Person("王宝强");
    persons.add(p2);
    Person p3 = new Person("柳岩");
    persons.add(p3);
    Person p4 = new Person("文章");
    persons.add(p4);
    Person p5 = new Person("马伊琍");
    persons.add(p5);
    Person p6 = new Person("李晨");
    persons.add(p6);
    Person p7 = new Person("张馨予");
    persons.add(p7);
    Person p8 = new Person("韩红");
    persons.add(p8);
    Person p9 = new Person("韩寒");
    persons.add(p9);
    Person p10 = new Person("丹丹");
    persons.add(p10);
    Person p11 = new Person("丹凤眼");
    persons.add(p11);
    Person p12 = new Person("哈哈");
    persons.add(p12);
    Person p13 = new Person("萌萌");
    persons.add(p13);
    Person p14 = new Person("蒙混");
    persons.add(p14);
    Person p15 = new Person("烟花");
    persons.add(p15);
    Person p16 = new Person("眼黑");
    persons.add(p16);
    Person p17 = new Person("许三多");
    persons.add(p17);
    Person p18 = new Person("程咬金");
    persons.add(p18);
    Person p19 = new Person("程哈哈");
    persons.add(p19);
    Person p20 = new Person("爱死你");
    persons.add(p20);
    Person p21 = new Person("阿莱");
    persons.add(p21); 

  } 

}

此Activity的布局文件如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="match_parent"
  android:background="#ffffff"
  android:orientation="vertical" > 

  <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:text="列表显示"
    android:textColor="#000000"
    android:textSize="16sp" /> 

  <FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff" > 

    <ListView
      android:id="@+id/listView"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:cacheColorHint="#00000000"
      android:fadingEdge="none"
      android:scrollbars="none" >
    </ListView> 

    <TextView
      android:id="@+id/tv"
      android:layout_width="60dp"
      android:layout_height="60dp"
      android:layout_gravity="center"
      android:background="#f0606060"
      android:gravity="center"
      android:text="A"
      android:textColor="#ffffff"
      android:textSize="30sp" /> 

    <LinearLayout
      android:id="@+id/layout"
      android:layout_width="wrap_content"
      android:layout_height="fill_parent"
      android:layout_gravity="right"
      android:background="#d7d7d7"
      android:gravity="center"
      android:orientation="vertical" >
    </LinearLayout>
  </FrameLayout> 

</LinearLayout> 

第二步:自定义了一个Adapter,代码如下:

package net.loonggg.test; 

import java.util.List; 

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView; 

public class ListViewAdapter extends BaseAdapter {
  private Context context;
  private List<Person> list;
  private ViewHolder viewHolder; 

  public ListViewAdapter(Context context, List<Person> list) {
    this.context = context;
    this.list = list;
  } 

  @Override
  public int getCount() {
    return list.size();
  } 

  @Override
  public Object getItem(int position) {
    return list.get(position);
  } 

  @Override
  public long getItemId(int position) {
    return position;
  } 

  @Override
  public boolean isEnabled(int position) {
    // TODO Auto-generated method stub
    if (list.get(position).getName().length() == 1)// 如果是字母索引
      return false;// 表示不能点击
    return super.isEnabled(position);
  } 

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    String item = list.get(position).getName();
    viewHolder = new ViewHolder();
    if (item.length() == 1) {
      convertView = LayoutInflater.from(context).inflate(R.layout.index,
          null);
      viewHolder.indexTv = (TextView) convertView
          .findViewById(R.id.indexTv);
    } else {
      convertView = LayoutInflater.from(context).inflate(R.layout.item,
          null);
      viewHolder.itemTv = (TextView) convertView
          .findViewById(R.id.itemTv);
    }
    if (item.length() == 1) {
      viewHolder.indexTv.setText(list.get(position).getName());
    } else {
      viewHolder.itemTv.setText(list.get(position).getName());
    }
    return convertView;
  } 

  private class ViewHolder {
    private TextView indexTv;
    private TextView itemTv;
  } 

} 

第三步:用到的ListView中的子布局文件如下:
1、index.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="#9c9c9c"
  android:orientation="vertical"
  android:paddingBottom="5dp"
  android:paddingLeft="10dp"
  android:paddingTop="5dp" > 

  <TextView
    android:id="@+id/indexTv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="#0f0f0f" /> 

</LinearLayout>

2、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:background="#ffffff"
  android:orientation="vertical"
  android:paddingBottom="5dp"
  android:paddingLeft="20dp"
  android:paddingTop="5dp" > 

  <TextView
    android:id="@+id/itemTv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="#000000"
    android:textSize="20sp" /> 

</LinearLayout> 

第四步:用到的实体类及工具类如下:
1、Person.java代码如下:

package net.loonggg.test; 

public class Person {
  private String name;
  private String pinYinName; 

  public Person(String name) {
    super();
    this.name = name;
  } 

  public Person(String name, String pinYinName) {
    super();
    this.name = name;
    this.pinYinName = pinYinName;
  } 

  public String getName() {
    return name;
  } 

  public void setName(String name) {
    this.name = name;
  } 

  public String getPinYinName() {
    return pinYinName;
  } 

  public void setPinYinName(String pinYinName) {
    this.pinYinName = pinYinName;
  } 

} 

2、工具类代码如下:

package net.loonggg.test; 

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; 

public class StringHelper {
  /**
   * 得到 全拼
   *
   * @param src
   * @return
   */
  public static String getPingYin(String src) {
    char[] t1 = null;
    t1 = src.toCharArray();
    String[] t2 = new String[t1.length];
    HanyuPinyinOutputFormat t3 = new HanyuPinyinOutputFormat();
    t3.setCaseType(HanyuPinyinCaseType.LOWERCASE);
    t3.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
    t3.setVCharType(HanyuPinyinVCharType.WITH_V);
    String t4 = "";
    int t0 = t1.length;
    try {
      for (int i = 0; i < t0; i++) {
        // 判断是否为汉字字符
        if (java.lang.Character.toString(t1[i]).matches(
            "[\\u4E00-\\u9FA5]+")) {
          t2 = PinyinHelper.toHanyuPinyinStringArray(t1[i], t3);
          t4 += t2[0];
        } else {
          t4 += java.lang.Character.toString(t1[i]);
        }
      }
      return t4;
    } catch (BadHanyuPinyinOutputFormatCombination e1) {
      e1.printStackTrace();
    }
    return t4;
  } 

  /**
   * 得到首字母
   *
   * @param str
   * @return
   */
  public static String getHeadChar(String str) { 

    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.toUpperCase();
  } 

  /**
   * 得到中文首字母缩写
   *
   * @param str
   * @return
   */
  public static String getPinYinHeadChar(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.toUpperCase();
  }
}

到这里就完事,非常简单吧!

(0)

相关推荐

  • android仿微信通讯录搜索示例(匹配拼音,字母,索引位置)

    前言: 仿微信通讯录搜索功能,通过汉字或拼音首字母找到匹配的联系人并显示匹配的位置 一:先看效果图 字母索引 搜索匹配 二:功能分析 1:汉字转拼音 通讯录汉字转拼音(首个字符当考虑姓氏多音字), 现在转换拼音常见的有pinyin4j和tinypinyin, pinyin4j的功能强大,包含声调多音字,tinypinyin执行快占用内存少, 如果只是简单匹配通讯录,建议使用tinypinyin,用法也很简单这里不详细介绍 拼音类 public class CNPinyin <T extends

  • Android 实现带字母索引的侧边栏功能

    之前已经用自定义View做出如下这样一个效果了 这两天需要重新拿来使用,发现效果虽然做出来了,不过思路不太对,就重新参考写了一个,用法也更为简单了 首要的自然是需要继承View绘制出侧边栏,并向外提供一个监听字母索引变化的方法 /** * 作者:叶应是叶 * 时间:2017/8/20 11:38 * 描述: */ public class LetterIndexView extends View { public interface OnTouchingLetterChangedListener

  • android将搜索引擎设置为中国雅虎无法搜索问题解决方法

    该问题是由于yahoo的搜索接口改变导致,请修改 Donottranslate-all_search_engines.xml (x:\6575gb2\v2.12\alps\mediatek\source\frameworks\banyan\res\res\values)41753 8/11/2011 中的<string-array name="yahoo_cn" translatable="false">的定义为 复制代码 代码如下: <strin

  • Android ItemDecoration 实现分组索引列表的示例代码

    本文介绍了Android ItemDecoration 实现分组索引列表的示例代码,分享给大家.具体如下: 先来看看效果: 我们要实现的效果主要涉及三个部分: 分组 GroupHeader 分割线 SideBar 前两个部分涉及到一个ItemDecoration类,也是我们接下来的重点,该类是RecyclerView的一个抽象静态内部类,主要作用就是给RecyclerView的ItemView绘制额外的装饰效果,例如给RecyclerView添加分割线. 使用ItemDecoration时需要继

  • Android自定义View实现通讯录字母索引(仿微信通讯录)

    一.效果:我们看到很多软件的通讯录在右侧都有一个字母索引功能,像微信,小米通讯录,QQ,还有美团选择地区等等.这里我截了一张美团选择城市的图片来看看: 我们今天就来实现图片中右侧模块的索引功能,包括触摸显示以选中的索引字母.这里我的UI界面主要是参照微信的界面来实现,所以各位也可以对照微信来看看效果,什么都不说了,只有效果图最具有说服力! 二.分析: 我们看到这样的效果我们心理都回去琢磨,他是如何实现的: 首先,它肯定是通过自定义 View 来实现的,因为 Android 没有提供类似这样的控件

  • Android手机联系人快速索引(手机通讯录)

    最近需要实现一个手机通讯录的快速索引功能.根据姓名首字母快速索引功能.下面是一个手机联系人快速索引的效果,总体来说代码不算难,拼音转换的地方略有复杂.下面上源码:源码中有注释. 下面是效果图: MainActivity: import java.util.ArrayList; import java.util.Collections; import java.util.List; import android.app.Activity; import android.os.Bundle; imp

  • android 左右滑动+索引图标实现方法与代码

    使用Gallery和ImageView实现android左右滑动+索引图标效果. 首先自定义Gallery实现一次只能滑动一个页面 复制代码 代码如下: public class MGalleryView extends Gallery{ public MGalleryView(Context context, AttributeSet attrs) { super(context, attrs); } //一次只能滑动一张图片注:一张图充满全屏 @Override public boolean

  • Android通用索引栏实现代码

    偶尔看到之前写过的代码,感觉好多东西几乎在很多项目中都要用到,虽然每个项目的需求和设计都不同,不过实现的效果都是一样的,可能只是数据格式和一些颜色等的细微差距.但是有的时候因为一个小改变,就要去重复的修改代码,麻烦不说,也容易导致新的问题和BUG. 就拿忽然想到的索引栏来说,几乎写过的项目中都用到了,比如城市选择.联系人等等.这些地方全都需要用到索引栏,但是用法都是一样的.翻看了几处之前写过的代码,发现每次用到索引栏,都要重新去写方法来处理数据或者对数据的索引进行提取这些,做法也都大同小异.于是

  • Android手机联系人带字母索引的快速查找

    喜欢另辟蹊径的我,在这里废话不多说了,直接上代码和图片了. 效果图如下: 第一步:MainActivity的代码如下: package net.loonggg.test; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.TreeSet; import android.os.Bundle; import and

  • Android实现recyclerview城市字母索引列表

    转拼音的依赖 implementation 'com.github.SilenceDut:jpinyin:v1.0' FastIndexView实现列表右侧字母索引列表 public class FastIndexView extends View { private static final String INDEX_NAME = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private OnLetterUpdateListener listener; priva

  • PC版与Android手机版带断点续传的多线程下载

    一.多线程下载 多线程下载就是抢占服务器资源 原理:服务器CPU 分配给每条线程的时间片相同,服务器带宽平均分配给每条线程,所以客户端开启的线程越多,就能抢占到更多的服务器资源. 1.设置开启线程数,发送http请求到下载地址,获取下载文件的总长度           然后创建一个长度一致的临时文件,避免下载到一半存储空间不够了,并计算每个线程下载多少数据              2.计算每个线程下载数据的开始和结束位置           再次发送请求,用 Range 头请求开始位置和结束位

  • 浅谈Android手机联系人开发之增删查改功能

    最近在做手机联系人的功能模块的时候,遇到了很多的坑,在网上搜索的有一些所谓的最全的手机联系人开发的介绍还存在一些bug,所以我把我最近的项目心得和方法写下来,既能帮助大家减少了解android开发手机联系人的门槛,好,废话少说,接下来直奔主题. 一.深入浅出手机联系人的前奏(小米手机的data表跟模拟器的data表不一样) 1.手机联系人主要是对contacts2.db数据库表的操纵,这个数据库中有三个表是比较重要的,分别是data,raw_contacts,mimetyps这三个表.在下面的增

  • Android仿微信联系人列表字母侧滑控件

    仿微信联系人列表字母侧滑控件, 侧滑控件参考了以下博客: Android实现ListView的A-Z字母排序和过滤搜索功能 首先分析一下字母侧滑控件应该如何实现,根据侧滑控件的高度和字母的数量来平均计算每个字母应该占据的高度. 在View的onDraw()方法下绘制每一个字母 protected void onDraw(Canvas canvas) { super.onDraw(canvas); int height = getHeight();// 获取对应高度 int width = get

  • 浅析Android手机卫士读取联系人

    推荐阅读: 浅析Android手机卫士sim卡绑定 深入浅析Android手机卫士保存密码时进行md5加密 详解Android 手机卫士设置向导页面 浅析Android手机卫士关闭自动更新 浅析Android手机卫士自定义控件的属性 获取ContentResolver内容解析器对象,通过getContentResolver()方法 调用ContentResolver对象的query()方法,得到raw_contacts表里面的数据,得到Cursor对象 参数:Uri对象,字段String数组 获

  • Android ContentProvider查看/读取手机联系人实例

    看到某些App里面有读取联系人的功能,然后自己尝试了一下.发现这个挺简单的.然后自己就做了一个demo给大家,希望借这个demo可以让大家学习一下怎么实现读取手机联系人. 这里我用了两种方法去读取:第一张图片是跳转到系统自带的联系人界面,第二种就是直接去读取让后绑上来显示在主页面.话不多说直接上代码. 记得在AndroidManifest.xml 记得加入这两句,不然就读取不到联系人. <uses-permission android:name="android.permission.RE

随机推荐