Android 联系人快速索引----学习笔记

1.布局

一个ListView,联系人的信息

一个TextView,显示字母

一个自定义的IndexView,在布局的右边,填充字母

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.quickindex.MainActivity">

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

    <TextView
        android:visibility="gone"
        android:layout_centerInParent="true"
        android:id="@+id/tv_word"
        android:text="A"
        android:textSize="40sp"
        android:background="#44000000"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:gravity="center"
        android:textColor="#000000"

        />
    <com.example.quickindex.IndexView
        android:id="@+id/iv_words"
        android:layout_width="30dp"
        android:background="#ff0000"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        />

</RelativeLayout>

2.绘制字母的位置

//1.把26个字母放入数组

//2.在onDraw计算每条的高itemHeight 和 宽itemWidth

//3.在ondraw计算wordWidth,wordHeight,wordX,wordY

Android 联系人快速索引----学习笔记

Android 联系人快速索引----学习笔记

已知:

itemWidth = viewWidth;

itemHeight = viewHeight / 26;

 

String word = words[i];//A

Android 联系人快速索引----学习笔记

Rect rect = new Rect();

paint.getTextBounds(word,0,1,rect);


//字母的高和宽

wordWidth = rect.width();

wordHeight = rect.height();

Android 联系人快速索引----学习笔记

//计算每个字母在视图上的坐标

wordX=itemWidth/2 - wordWidth/2;

wordY=itemHeight/2+wordHeight/2+ (i*itemHeight);

 

Canvas.drawText(word,wordX,wordY,paint);

public class IndexView extends View {
    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"};

    private int itemWidth;
    private int itemHeight;


    public IndexView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.WHITE);
        paint.setTypeface(Typeface.DEFAULT_BOLD);//设置粗体字
        paint.setTextSize(45);

    }

    @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++){
            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.设置手指按下字母变颜色

* 1.重写onTouchEvent(),返回true,在down.move的过程中计算 * int touchIndex = getY() / itemHeight;强制绘制

* 2.在onDraw()对应的下标设置画笔变色 

* 3.在up的时候 * touchIndex = -1; * 强制绘制 

            if(touchIndex == i){
                //设置灰色
                paint.setColor(Color.GRAY);
            }else {
                //设置白色
                paint.setColor(Color.WHITE);
            }
    //字母的下标位置
    private int touchIndex = -1;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                float Y = event.getY();
                int index = (int)(Y / itemHeight);
                if(index != touchIndex){
                    touchIndex = index;
                    invalidate();//强制绘制onDraw()
                }
                break;
            case MotionEvent.ACTION_UP:
                touchIndex = -1;
                invalidate();//强制绘制onDraw()
                break;
        }
        return true;
    }

4.设置手指按下字母的同时显示TextView

调用接口

什么时候用接口:有变化,并且要把变化告诉外界的情况下

    /**
     * 字母下标索引变化的监听器
     */
    public interface OnIndexChangeListener{
        /**
         * 当字母下标位置发生变化的时候回调
         * @param word 字母
         */
        void onIndexChange(String word);
    }

    private OnIndexChangeListener onIndexChangeListener;

    /**
     * 设置字母下标索引变化的监听
     * @param onIndexChangeListener
     */
    public void setOnIndexChangeListener(OnIndexChangeListener onIndexChangeListener){
        this.onIndexChangeListener = onIndexChangeListener;
    }

在onTouchEvent里面

                    if(onIndexChangeListener !=null && touchIndex< words.length){
                        onIndexChangeListener.onIndexChange(words[touchIndex]);
                    }

MainActivity.java

        //设置监听字母下标索引的变化
        iv_words.setOnIndexChangeListener(new IndexView.OnIndexChangeListener() {
            /**
             *
             * @param word 字母
             */
            @Override
            public void onIndexChange(String word) {
                updateWord(word);
            }
        });
    private void updateWord(String word) {
        //显示
        tv_word.setVisibility(View.VISIBLE);
        tv_word.setText(word);
    }

利用Handler使TextView显示几秒后消失

    private Handler handler = new Handler();
        handler.removeCallbacksAndMessages(null);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //也是运行主线程
                tv_word.setVisibility(View.GONE);
            }
        },2000);

5.根据字母索引到名字

隐藏相同的字母:

            if(position == 0){
                viewHolder.tv_word.setVisibility(View.VISIBLE);
            }else {
                //得到前一个位置对应的字母,如果当前字母和上一个字母相同,隐藏。
                String preword = persons.get(position-1).getPinyin().substring(0,1);
                if(word.equals(preword)){
                    viewHolder.tv_word.setVisibility(View.GONE);
                }else {
                    viewHolder.tv_word.setVisibility(View.VISIBLE);
                }
            }

根据字母找到对应的名字:

    private void updateListView(String word) {
        for(int i = 0;i<persons.size();i++){
            String listWord = persons.get(i).getPinyin().substring(0,1);
            if(word.equals(listWord)){
                //i是Listview钟的位置
                lv.setSelection(i);//定位到ListView钟的某个位置
                return;
            }
        }

    }

源码:

MainActivity

public class MainActivity extends Activity {
    private ListView lv;
    private TextView tv_word;
    private IndexView iv_words;
    private Handler handler = new Handler();
    private ArrayList<Person> persons;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv = (ListView) findViewById(R.id.lv);
        tv_word=(TextView)findViewById(R.id.tv_word);
        iv_words=(IndexView)findViewById(R.id.iv_words);

        //准备数据
        initData();
        //设置适配器
        lv.setAdapter(new IndexAdpater());

        //设置监听字母下标索引的变化
        iv_words.setOnIndexChangeListener(new IndexView.OnIndexChangeListener() {
            /**
             *
             * @param word 字母
             */
            @Override
            public void onIndexChange(String word) {
                updateWord(word);
                updateListView(word);
            }
        });
    }

    private void updateListView(String word) {
        for(int i = 0;i<persons.size();i++){
            String listWord = persons.get(i).getPinyin().substring(0,1);
            if(word.equals(listWord)){
                //i是Listview钟的位置
                lv.setSelection(i);//定位到ListView钟的某个位置
                return;
            }
        }

    }

    private void updateWord(String word) {
        //显示
        tv_word.setVisibility(View.VISIBLE);
        tv_word.setText(word);
        handler.removeCallbacksAndMessages(null);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //也是运行主线程
                tv_word.setVisibility(View.GONE);
            }
        },2000);
    }

    class IndexAdpater extends BaseAdapter {

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

        @Override
        public Object getItem(int position) {
            return null;
        }

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

        @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);
            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);
                if(word.equals(preword)){
                    viewHolder.tv_word.setVisibility(View.GONE);
                }else {
                    viewHolder.tv_word.setVisibility(View.VISIBLE);
                }
            }

            return convertView;
        }

    }

    static class ViewHolder{
        TextView tv_word;
        TextView tv_name;
    }
    private void initData(){
        persons = new ArrayList<>();
        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 o1, Person o2) {
                return o1.getPinyin().compareTo(o2.getPinyin());
            }
        });
    }
}
Person
public class Person {
    public Person(String name){
        this.name = name;
        this.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;
    }

    private String name;
    private String pinyin;
}

IndexView

public class IndexView extends View {
    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"};

    private int itemWidth;
    private int itemHeight;


    public IndexView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.WHITE);
        paint.setTypeface(Typeface.DEFAULT_BOLD);//设置粗体字
        paint.setTextSize(45);

    }

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


    /**
     * 手指按下文字变色
     * 1.重写onTouchEvent(),返回true,在down.move的过程中计算
     * int touchIndex = getY() / itemHeight;强制绘制
     *
     * 2.在onDraw()对应的下标设置画笔变色
     *
     * 3.在up的时候
     * touchIndex = -1;
     * 强制绘制
     */
    //字母的下标位置
    private int touchIndex = -1;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
            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;
    }

    /**
     * 字母下标索引变化的监听器
     */
    public interface OnIndexChangeListener{
        /**
         * 当字母下标位置发生变化的时候回调
         * @param word 字母
         */
        void onIndexChange(String word);
    }

    private OnIndexChangeListener onIndexChangeListener;

    /**
     * 设置字母下标索引变化的监听
     * @param onIndexChangeListener
     */
    public void setOnIndexChangeListener(OnIndexChangeListener onIndexChangeListener){
        this.onIndexChangeListener = onIndexChangeListener;
    }
}

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="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_word"
        android:textSize="25sp"
        android:text="A"
        android:textColor="#000000"
        android:background="#44000000"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />


    <TextView
        android:id="@+id/tv_name"
        android:textSize="25sp"
        android:text="张三"
        android:textColor="#000000"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.quickindex.MainActivity">

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

    <TextView
        android:visibility="gone"
        android:layout_centerInParent="true"
        android:id="@+id/tv_word"
        android:text="A"
        android:textSize="40sp"
        android:background="#44000000"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:gravity="center"
        android:textColor="#000000"

        />
    <com.example.quickindex.IndexView
        android:id="@+id/iv_words"
        android:layout_width="30dp"
        android:background="#ff0000"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        />

</RelativeLayout>

 

上一篇:Sublime Text 3安装


下一篇:sublime text 4 for Mac(前端代码编辑神器)v4.0(4122) 中文