手机联系人快速索引

这是一个手机联系人快速索引的效果,总体来说代码不算难,拼音转换的地方略有复杂。下面上源码:源码中有注释。

MainActivity:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
/**
 * 这里是主布局
 * @author lxd
 *
 */
public class MainActivity extends Activity {

    private ListView lv_main;
    private FriendAdapter adapter;
    private List<Friend> data = new ArrayList<Friend>();
    private QuickIndexView qiv_main;
    private TextView tv_main_word;
    private Handler handler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            //隐藏word
            tv_main_word.setVisibility(View.GONE);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        lv_main = (ListView) findViewById(R.id.lv_main);
        qiv_main = (QuickIndexView) findViewById(R.id.qiv_main);
        tv_main_word = (TextView) findViewById(R.id.tv_main_word);
        
        //设置监听
        qiv_main.setOnIndexChangedListener(new QuickIndexView.OnIndexChangedListener() {
            
            @Override
            public void onIndexChanged(String word) {
                tv_main_word.setText(word);
                tv_main_word.setVisibility(View.VISIBLE);
            
                //handler.removeMessages(1);
                //移除未处理的消息
                handler.removeCallbacksAndMessages(null);
                //发延迟消息
                handler.sendEmptyMessageDelayed(1, 2000);
                
                //滑动listview
                //查找对应的item
                for(int i=0;i<data.size();i++) {
                    String fWord = data.get(i).getPinyin().substring(0, 1);
                    if(word.equals(fWord)) {
                        lv_main.setSelection(i);
                        return;
                    }
                }
            }

            @Override
            public void onUp() {
                //tv_main_word.setVisibility(View.GONE);
            }
        });
        
        //显示列表
        adapter = new FriendAdapter();
        initData();
        lv_main.setAdapter(adapter);
        
        //lv_main.setSelection(5);
    }
    
    private void initData() {
        data.add(new Friend("张三"));
        data.add(new Friend("杨九"));
        data.add(new Friend("胡继群"));
        data.add(new Friend("刘畅"));

        data.add(new Friend("钟泽兴"));
        data.add(new Friend("尹革新"));
        data.add(new Friend("安传鑫"));
        data.add(new Friend("张骞壬"));

        data.add(new Friend("温松"));
        data.add(new Friend("李凤秋"));
        data.add(new Friend("刘甫"));
        data.add(new Friend("娄全超"));
        data.add(new Friend("张猛"));

        data.add(new Friend("王英杰"));
        data.add(new Friend("李振南"));
        data.add(new Friend("孙仁政"));
        data.add(new Friend("唐春雷"));
        data.add(new Friend("牛鹏伟"));
        data.add(new Friend("姜宇航"));

        data.add(new Friend("刘挺"));
        data.add(new Friend("张洪瑞"));
        data.add(new Friend("张建忠"));
        data.add(new Friend("侯亚帅"));
        data.add(new Friend("刘帅"));

        data.add(new Friend("乔竞飞"));
        data.add(new Friend("徐雨健"));
        data.add(new Friend("吴亮"));
        data.add(new Friend("王兆霖"));

        data.add(new Friend("阿三"));
        
        Collections.sort(data);
    }

    class FriendAdapter extends BaseAdapter {

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

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

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            if(convertView==null) {
                holder = new ViewHolder();
                convertView = View.inflate(MainActivity.this, R.layout.item_main, null);
                holder.wordTV = (TextView) convertView.findViewById(R.id.tv_item_word);
                holder.nameTV = (TextView) convertView.findViewById(R.id.tv_item_name);
                convertView.setTag(holder);//***********?
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            
            Friend friend = data.get(position);
            String word = friend.getPinyin().substring(0, 1);
            holder.wordTV.setText(word);
            holder.nameTV.setText(friend.getName());
            
            //下标为0的显示
            if(position==0) {
                holder.wordTV.setVisibility(View.VISIBLE);
            } else {
                //取出上一个friend, 并得到的第一个word
                String preWord = data.get(position-1).getPinyin().substring(0, 1);
                //判断是否于当前行的word是否相同
                    //如果相同, 隐藏
                if(word.equals(preWord)) {
                    holder.wordTV.setVisibility(View.GONE);
                } else {
                    //如果不同, 显示
                    holder.wordTV.setVisibility(View.VISIBLE);
                }
            }
        
            return convertView;
        }
        
        class ViewHolder {
            public TextView wordTV;
            public TextView nameTV;
        }
        
    }
}

主布局:

<RelativeLayout xmlns: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"
    tools:context="${relativePackage}.${activityClass}" >

    <ListView
        android:id="@+id/lv_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

    <!-- com.atguigu.quickindex.QuickIndexView -->

    <com.atguigu.quickindex.QuickIndexView
        android:id="@+id/qiv_main"
        android:layout_width="40dp"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:background="#ffffff" >
    </com.atguigu.quickindex.QuickIndexView>

    <TextView
        android:id="@+id/tv_main_word"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:background="#66666666"
        android:text="A" 
        android:textSize="40sp"
        android:gravity="center"
        android:visibility="gone"/>

</RelativeLayout>

Item:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv_item_word"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="A" 
        android:background="#66666666"
        android:textSize="18sp"
        android:padding="5dp"/>
    <TextView
        android:id="@+id/tv_item_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="某人" 
        android:textSize="18sp"
        android:padding="5dp"/>

</LinearLayout>

自定义View:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
 * 这里是自定义View
 * @author lxd
 *
 */
public class QuickIndexView extends View {

    private float itemWidth;
    private float itemHeight;
    // private float wordWidth;
    // private float wordHeight;

    private String[] indexArr = { "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 Paint paint;

    public QuickIndexView(Context context, AttributeSet attrs) {
        super(context, attrs);

        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setTextSize(16);
        paint.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        itemWidth = this.getMeasuredWidth();
        itemHeight = this.getMeasuredHeight() / 26f;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //当每次触发重绘的时候,就把26个字母循环一遍
        for (int i = 0; i < indexArr.length; i++) {
            String word = indexArr[i];
            // 设置文字的颜色
            if (i == touchIndex) {
                //这里设置被点击的字母变化:颜色变灰色、字体变25sp
                paint.setColor(Color.GRAY);
                paint.setTextSize(25);
            } else {
                //其他没被点击的字母,保持原有状态:设置颜色、字体大小为18sp
                paint.setColor(Color.BLACK);
                paint.setTextSize(18);
            }
            // 得到word的宽高
            Rect bounds = new Rect();
            paint.getTextBounds(word, 0, word.length(), bounds);
            //得到字体的宽
            int wordWidth = bounds.width();
            //得到字体的高
            int wordHeight = bounds.height();
            
            // 计算word的左上角的坐标:字母所在的X坐标、Y坐标
            float x = itemWidth / 2 - wordWidth / 2;
            float y = itemHeight / 2 + wordHeight / 2 + i * itemHeight;
            // 绘制word
            canvas.drawText(word, x, y, paint);
        }
    }

    // ///////////////////////////////////////////////////////////////////////
    private int touchIndex = -1;// 触摸的字母的下标

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        // 得到事件坐标
        float eventY = event.getY();

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:
            // 计算下标
            int index = (int) (eventY / itemHeight);
            if (index > 25) {
                index = 25;
            }
            if (index < 0) {
                index = 0;
            }

            // 如果下标有改变, 强制重绘
            if (index != touchIndex) {
                // 更新touchIndex
                touchIndex = index;
                // 强制重绘
                invalidate();

                // 通知Activity更新TextView
                if (onIndexChangedListener != null) {
                    onIndexChangedListener.onIndexChanged(indexArr[index]);
                }
            }
            break;
        case MotionEvent.ACTION_UP:
            touchIndex = -1;
            // 强制重绘
            invalidate();

            // 通知Activity更新TextView
            if (onIndexChangedListener != null) {
                onIndexChangedListener.onUp();
            }
            break;

        default:
            break;
        }
        return true;// 所有的事件都由当前视图消费
    }

    private OnIndexChangedListener onIndexChangedListener;

    /*
     * 设置监听对象的方法 这个方法一般是Activity调用
     */
    public void setOnIndexChangedListener(
            OnIndexChangedListener onIndexChangedListener) {
        this.onIndexChangedListener = onIndexChangedListener;
    }

    interface OnIndexChangedListener {
        // 当操作的下标改变时自动调用
        public void onIndexChanged(String word);

        // 当up时调用
        public void onUp();
    }

}

联系人类:

/**
 * 联系人类
 * @author lxd
 *
 */
public class Friend implements Comparable<Friend> {

    private String name;
    private String pinyin;

    public Friend(String name) {
        super();
        this.name = name;
        pinyin = PinYinUtils.getPinYin(name);
    }

    public String getName() {
        return name;
    }

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

    public String getPinyin() {
        return pinyin;
    }

    public void setPinyin(String pinyin) {
        this.pinyin = pinyin;
    }

    @Override
    public String toString() {
        return "Friend [name=" + name + ", pinyin=" + pinyin + "]";
    }

    @Override
    public int compareTo(Friend another) {
        return this.pinyin.compareTo(another.getPinyin());
    }

}

工具类:用于将汉字转换为拼音

/**
 * 将汉字转换为拼音
 * @author lxd
 *
 */
public class PinYinUtils {
    /**
     * 得到指定汉字的拼音
     * 注意:不应该被频繁调用,它消耗一定内存
     * @param hanzi
     * @return
     */
    public static String getPinYin(String hanzi){
        String pinyin = "";
        
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();//控制转换是否大小写,是否带音标
        format.setCaseType(HanyuPinyinCaseType.UPPERCASE);//大写
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        
        //由于不能直接对多个汉字转换,只能对单个汉字转换
        char[] arr = hanzi.toCharArray();
        for (int i = 0; i < arr.length; i++) {
            if(Character.isWhitespace(arr[i]))continue;//如果是空格,则不处理,进行下次遍历
            
            //汉字是2个字节存储,肯定大于127,所以大于127就可以当为汉字转换
            if(arr[i]>127){
                try {
                    //由于多音字的存在,单 dan shan
                    String[] pinyinArr = PinyinHelper.toHanyuPinyinStringArray(arr[i], format);
                    
                    if(pinyinArr!=null){
                        pinyin += pinyinArr[0];
                    }else {
                        pinyin += arr[i];
                    }
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    e.printStackTrace();
                    //不是正确的汉字
                    pinyin += arr[i];
                }
            }else {
                //不是汉字,
                pinyin += arr[i];
            }
        }
        return pinyin;
    }
}

运行效果:

以上就是全部代码了,需要的同学可以直接拿去用,样式的话根据需要自己改下就行了。

时间: 2024-10-16 06:50:36

手机联系人快速索引的相关文章

浅谈android中手机联系人字母索引表的实现

实际上字母索引表的效果,可以说在现在的众多APP中使用的非常流行,比如支付宝,微信中的联系人,还有购物,买票的APP中选择全国城市,切换城市的时候,这时候的城市也就是按照一个字母索引的顺序来显示,看起来是很方便的.其实这种字母索引表的效果最开始是出现在微信的联系人中.因为觉得这种效果功能在今后的项目中可以说是非常常见,可能会用的上,所以准备来波博客讲述一下实现的原理,一来方便以后自己复习,二来如果能够帮助一些android路上奋斗小伙伴也是蛮有意义的. 下面我们先来看下效果图, 看完效果图后我们

安卓仿微信联系人快速索引

半成品效果图: 代码 import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import

Android 快速索引(城市列表和联系人)

最近需要实现一个城市列表的快速索引功能.类似于联系人应用,根据姓名首字母快速索引功能. 要实现这个功能只需要解决两个问题: 1.对列表进行分组(具有同一特征),并且能够快速定位到该组的第一项 2.右侧分组'特征'快速索引栏的实现 第一个问题比较好解决,列表项可以根据相同的'特征'来分组,比如说城市列表可以根据相同首字母的城市名来进行分组. 如何来定位到分组的第一项,只需要把分组的'特征'和分组第一项下标关联起来,快速索引栏就能快速定位分组第一项 第二个问题可以通过自定义控件来实现,实现的形式有很

获取手机联系人,并通过拼音字母快速查询

获取手机联系人,并通过拼音字母快速查询. 通过工具类转换联系人首字的首字母,并排序显示. 通过画布的方式在布局右侧添加快速查询的字母布局 显示效果如下图: 右侧点击[★]时回到顶部: 滑动到[N]时N开头的联系人置顶 代码: 通过画布的方式在布局右侧添加快速查询的字母布局 http://download.csdn.net/detail/zengchao2013/8750259 欢迎指正~ 通过画布的方式在布局右侧添加快速查询的字母布局

8.快速索引、listview

实现这样的效果 布局: <RelativeLayout xmlns: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" tools

快速索引

如下是快速索引的效果图,是从网上下的实例.如图实现的难点1:是最右侧的索引是用自定义View来实现的,主要通过onDraw的方法将其画出: 难点2:是如何拿到每个名字的首字母用的是pinyin4j-2.5.0.jar  将汉字转化成拼音再去第一个字符:难点3:ListView的adapte不好实现 下图的布局是一个ListView右侧是一个自定义的View,中间是一个TextView点击的时候显示 如下是自定义的View来实现快速索引 1 package com.demo.sb.widget;

ListView的快速索引

在玩即时通讯app比如微信的联系人列表的时候,发现联系人列表的右侧有个竖排的字母索引,点击字母,可以快速索引到相应的联系人.本篇就是实现这个功能. 效果图: 快速索引 快速索引 需要实现: 将右侧的字母画到屏幕上去: 联系人列表排序: 根据联系人名字的首字母为ListView打上TAG 选中索引的某个字母,出现相应的TAG下的联系人: 画索引字母到屏幕上 新建一个类,继承自View public class QuickIndexBar extends View 并提供构造器方法,在构造器中完成相

安卓手机联系人被误删如何找回呢?该怎么找回

安卓手机联系人被误删如何找回呢?该怎么找回.我们经常的会因为自己的而一些比较细小的因素导致自己的手机联系人被误删,当我们误删之后我们便会想要找回我们删除的手机联系人. 其实我们误删我们的手机联系人之后,可以看看自己有没有进行备份,若是有备份我们直接还原就可以,若是没有备份的话,我们也可以选择从自己的云同步中找回,若是都不行的话,你也可以试试下面的方法. 第一步:首先在恢复过程需要我们首先打开电脑, 可以先在电脑浏览器上下载安装"互盾安卓恢复大师"的安装包,用数据线将电脑和手机连接在一起

手机联系人没了怎么恢复呢?快速恢复

手机联系人没了怎么恢复呢?如何恢复呢?我们有些时候会因为自己的一些原因,而使我们的手机联系人被我们给误删了,误删之后,我们便会想要找回我们误删的联系人,这是我们该怎么恢复呢? 其实我们若是误删了联系人之后,我们可以选择看看自己有没有进行备份,若是有备份的话直接还原,没有备份的话,我们也不用担心,我们或许可以使用下面的方法帮助我们找回误删的联系人. 1.首先在准备恢复的时候我们先打开电脑,在电脑上浏览器上下载安装"强力安卓恢复精灵",安装结束之后用数据线将电脑和丢失数据手机连接在一起,之