美文网首页
联系人快速索引

联系人快速索引

作者: GeekGray | 来源:发表于2018-10-02 22:51 被阅读23次

    阅读原文

    联系人快速索引

    1.界面布局

    <?xml version="1.0" encoding="utf-8"?>
    <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="com.contactquickindex.MainActivity">
    
        <ListView
            android:id="@+id/lv_main"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
        <TextView
            android:id="@+id/tv_word"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:layout_centerInParent="true"
            android:background="#44000000"
            android:gravity="center"
            android:text="A"
            android:textColor="#000000"
            android:textSize="30sp"
            android:visibility="gone" />
    
        <com.contactquickindex.IndexView
            android:id="@+id/iv_words"
            android:layout_width="30dp"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:background="#ff0000" />
    </RelativeLayout>
    

    2.初始化显示字母列表

    1.自定义IndexView继承于View

    /**
     * 
     * @author: Hashub.NG
     * @description: 绘制快速索引的字母 1.把26个字母放入数组 2.在onMeasure计算每条的高itemHeight和宽itemWidth,
     *               3.在onDraw和wordWidth,wordHeight,wordX,wordY
     *               <p/>
     *               手指按下文字变色 1.重写onTouchEvent(),返回true,在down/move的过程中计算 int
     *               touchIndex = Y / itemHeight; 强制绘制
     *               <p/>
     *               2.在onDraw()方法对于的下标设置画笔变色
     *               <p/>
     *               3.在up的时候 touchIndex = -1; 强制绘制
     * @update: 2018年8月1日 下午7:43:44
     */
    public class IndexView extends View{}
    

    2.定义变量

        /**
         * 每条的宽和高
         */
        private int itemWidth;
        private int itemHeight;
    
        private Paint paint;
    
        private String[] words = { "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" };
    

    3.初始化字母位置

        public IndexView(Context context, AttributeSet attrs)
        {
            super(context, attrs);
            paint = new Paint();
            paint.setColor(Color.WHITE);// 设置颜色
            paint.setAntiAlias(true);// 设置抗锯齿
            paint.setTypeface(Typeface.DEFAULT_BOLD);// 设置粗体字
        }
    
        /**
         * 测量方法
         *
         * @param widthMeasureSpec
         * @param heightMeasureSpec
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
        {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            itemWidth = getMeasuredWidth();
            itemHeight = getMeasuredHeight() / words.length;
        }
    
        @Override
        protected void onDraw(Canvas canvas)
        {
            super.onDraw(canvas);
            for (int i = 0; i < words.length; i++)
            {
                if (touchIndex == i)
                {
                    // 设置灰色
                    paint.setColor(Color.GRAY);
                }
                else
                {
                    // 设置白色
                    paint.setColor(Color.WHITE);
                }
                String word = words[i];// A
                Rect rect = new Rect();
                // 画笔
                // 0,1的取一个字母
                paint.getTextBounds(word, 0, 1, rect);
    
                // 字母的高和宽
                int wordWidth = rect.width();
                int wordHeight = rect.height();
    
                // 计算每个字母在视图上的坐标位置
                float wordX = itemWidth / 2 - wordWidth / 2;
                float wordY = itemHeight / 2 - wordHeight / 2 + i * itemHeight;
    
                canvas.drawText(word, wordX, wordY, paint);
    
            }
        }
    

    3.在按下和移动的时候使操作字母变色

    实现步骤分析

    .在按下和移动时候,使操作的字母变色

    a.重写onTouchEvent(),返回true

    b.在down/move时,计算出操作的下标,并且在onDraw(),设置不同颜色画笔,强制绘制

    c.在up时,重置操作下标,强制重绘制

            /**
             * 字母的下标位置
             */
            private int touchIndex = -1;
    
        /**
         * 手指按下文字变色
         * 1.重写onTouchEvent(),返回true,在down/move的过程中计算
         * int touchIndex = Y / itemHeight; 强制绘制
         * <p/>
         * 2.在onDraw()方法对于的下标设置画笔变色
         * <p/>
         * 3.在up的时候
         * touchIndex  = -1;
         * 强制绘制
         *
         * @param event
         * @return
         */
        @Override
        public boolean onTouchEvent(MotionEvent event)
        {
             super.onTouchEvent(event);
             switch (event.getAction())
            {
            case MotionEvent.ACTION_DOWN://Down和Move都需要处理,不需要break
    
            case MotionEvent.ACTION_MOVE:
                float Y=event.getY();
                int index=(int) (Y/itemHeight);//字母索引
                if(index!=touchIndex)
                {
                    touchIndex=index;
                    invalidate();//强制绘制onDraw();
                    if(onIndexChangeListener!=null && touchIndex<words.length)//判空及防止数组越界
                    {
                        onIndexChangeListener.onIndexChange(words[touchIndex]);
                    }
                }
                break;
    
            case MotionEvent.ACTION_UP:
                touchIndex=-1;
                invalidate();
                break;
            }
             return true;
        }
    

    4.在按下和移动时显示更新提示字母

    使用接口,封装变化,供外界调用

        /**
         * 字母下标索引变化的监听器
         */
        public interface OnIndexChangeListener
        {
            /**
             * 当字母下标位置发生变化的时候回调
             * 
             * @param word
             *            字母(A~Z)
             */
            void onIndexChange(String word);
        }
    
        /**
         * 设置字母下标索引变化的监听
         * 把接口写成类的成员变量,提供set方法
         * @param onIndexChangeListener
         */
        public void setOnIndexChangeListener(OnIndexChangeListener onIndexChangeListener)
        {
            this.onIndexChangeListener = onIndexChangeListener;
        }
    

    在MainActivity中使用接口

        private ListView lv_main;
        private TextView tv_word;
        private IndexView iv_words;
    
        private Handler handler = new Handler();
        /**
         * 联系人的集合
         */
        private ArrayList<Person> persons;
        private  IndexAdapter adapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            lv_main = (ListView) findViewById(R.id.lv_main);
            tv_word = (TextView) findViewById(R.id.tv_word);
            iv_words = (IndexView) findViewById(R.id.iv_words);
            //设置监听字母下标索引的变化
            iv_words.setOnIndexChangeListener(new MyOnIndexChangeListener());
            //准备数据
            initData();
            //设置适配器
            adapter = new IndexAdapter();
            lv_main.setAdapter(adapter);
        }
    

    使用handler延迟隐藏

            //显示
            tv_word.setVisibility(View.VISIBLE);
            tv_word.setText(word);
            handler.removeCallbacksAndMessages(null);
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    //也是运行在主线程
                    System.out.println(Thread.currentThread().getName()+"------------");
    
                    tv_word.setVisibility(View.GONE);
                }
            }, 3000);
    

    5.列表显示联系人

    导入汉字转拼音jar包和工具类

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

    Person bean类

    public class Person
    {
    
        private String name;
    
        private String pinyin;
    
        public Person(String name)
        {
            this.name = name;
            this.pinyin = PinYinUtils.getPinYin(name);
        }
    
        public String getPinyin()
        {
            return pinyin;
        }
    
        public void setPinyin(String pinyin)
        {
            this.pinyin = pinyin;
        }
    
        public String getName()
        {
            return name;
        }
    
        public void setName(String name)
        {
            this.name = name;
        }
    
        @Override
        public String toString()
        {
            return "Person{" + "name='" + name + '\'' + ", pinyin='" + pinyin + '\'' + '}';
        }
    }
    

    初始化联系人列表数据

        /**
         * 初始化数据
         */
        private void initData() {
    
            persons = new ArrayList<Person>();
            persons.add(new Person("张晓飞"));
            persons.add(new Person("杨光福"));
            persons.add(new Person("胡继群"));
            persons.add(new Person("刘畅"));
    
            persons.add(new Person("钟泽兴"));
            persons.add(new Person("尹革新"));
            persons.add(new Person("安传鑫"));
            persons.add(new Person("张骞壬"));
    
            persons.add(new Person("温松"));
            persons.add(new Person("李凤秋"));
            persons.add(new Person("刘甫"));
            persons.add(new Person("娄全超"));
            persons.add(new Person("张猛"));
    
            persons.add(new Person("王英杰"));
            persons.add(new Person("李振南"));
            persons.add(new Person("孙仁政"));
            persons.add(new Person("唐春雷"));
            persons.add(new Person("牛鹏伟"));
            persons.add(new Person("姜宇航"));
    
            persons.add(new Person("刘挺"));
            persons.add(new Person("张洪瑞"));
            persons.add(new Person("张建忠"));
            persons.add(new Person("侯亚帅"));
            persons.add(new Person("刘帅"));
    
            persons.add(new Person("乔竞飞"));
            persons.add(new Person("徐雨健"));
            persons.add(new Person("吴亮"));
            persons.add(new Person("王兆霖"));
    
            persons.add(new Person("阿三"));
            persons.add(new Person("李博俊"));
    

    联系人列表排序

            //排序
            Collections.sort(persons, new Comparator<Person>() {
                @Override
                public int compare(Person lhs, Person rhs) {
                    return lhs.getPinyin().compareTo(rhs.getPinyin());
                }
            });
    

    item_main.xml布局

    <?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_word"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#44000000"
            android:text="A"
            android:textColor="#000000"
            android:textSize="25sp" />
    
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="阿福"
            android:textColor="#000000"
            android:textSize="25sp" />
    
    
    </LinearLayout>
    

    listview填充数据显示

     class IndexAdapter extends BaseAdapter{
    
            @Override
            public int getCount() {
                return persons.size();
            }
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                ViewHolder viewHolder;
                if(convertView ==null){
                    convertView = View.inflate(MainActivity.this,R.layout.item_main,null);
                    viewHolder = new ViewHolder();
                    viewHolder.tv_word = (TextView) convertView.findViewById(R.id.tv_word);
                    viewHolder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);
                    convertView.setTag(viewHolder);
                }else{
                    viewHolder = (ViewHolder) convertView.getTag();
                }
    
                String name = persons.get(position).getName();//阿福
                String word = persons.get(position).getPinyin().substring(0,1);//AFU->A
                viewHolder.tv_word.setText(word);
                viewHolder.tv_name.setText(name);
                if(position ==0){
                    viewHolder.tv_word.setVisibility(View.VISIBLE);
                }else{
                    //得到前一个位置对应的字母,如果当前的字母和上一个相同,隐藏;否则就显示
                    String preWord = persons.get(position-1).getPinyin().substring(0,1);//A~Z
                    if(word.equals(preWord)){
                        viewHolder.tv_word.setVisibility(View.GONE);
                    }else{
                        viewHolder.tv_word.setVisibility(View.VISIBLE);
                    }
    
    
                }
    
    
                return convertView;
            }
    
            @Override
            public Object getItem(int position) {
                return null;
            }
    
            @Override
            public long getItemId(int position) {
                return 0;
            }
    
    
        }
    
        static class ViewHolder{
            TextView tv_word;
            TextView tv_name;
        }
    

    6.在按下和移动是列表更新

    更新列表

     private void updateListView(String word) {
            for(int i=0;i<persons.size();i++){
                String listWord = persons.get(i).getPinyin().substring(0,1);//YANGGUANGFU-->Y
                if (word.equals(listWord)) {
                    //i是listView中的位置
                    lv_main.setSelection(i);//定位到ListVeiw中的某个位置
                    return;
                }
            }
        }
    

    相关文章

      网友评论

          本文标题:联系人快速索引

          本文链接:https://www.haomeiwen.com/subject/ifoaoftx.html