手机联系人快速索引

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

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;
    }
}

运行效果:

wKiom1ZzmOyQswULAACpZlebY-E309.jpg

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

你可能感兴趣的:(手机,import,private,public,联系人)