Android自定义控件5----继承View通讯录索引功能之4在下按和移动时,列表更新

效果图:

Android自定义控件5----继承View通讯录索引功能之4在下按和移动时,列表更新_第1张图片

项目结构:

Android自定义控件5----继承View通讯录索引功能之4在下按和移动时,列表更新_第2张图片

核心代码

自定义索引:

IndexView
package com.example.mytongxunlu4;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.orhanobut.logger.Logger;

/**
 * 自定义通讯录
 */
public class IndexView extends View {
    /**
     * 每条的宽和高
     */
    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"};
    public IndexView(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        //设置颜色
        paint.setColor(Color.WHITE);
        //设置抗锯齿
        paint.setAntiAlias(true);
        //设置粗体字
        paint.setTypeface(Typeface.DEFAULT_BOLD);
//      设置字体大小
        paint.setTextSize(DensityUtil.dip2px(context,20));
    }
    /**
     * 测量方法
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        itemWidth = getMeasuredWidth();
        itemHeight = getMeasuredHeight() / words.length;
        Logger.t("111").d("onMeasure>>>");
    }

    /**
     * 绘制
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Logger.t("111").d("onDraw>>>");
        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);
        }
    }

    /**
     * 字母的下标位置
     */
    private int touchIndex = -1;

    /**
     * 设置事件
     * 按下的字母背景设置成灰色,放开时所有字母的背景设置为白色
     * 手指按下文字变色
     * 1.重写onTouchEvent(),返回true,在down/move的过程中计算
     * int touchIndex = Y / itemHeight; 强制绘制
     * 

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

* 3.在up的时候 * touchIndex = -1; * 强制绘制 * * @param event * @return */ @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();//强制绘制onDraw(); break; } return true; } /** * 接口回调 * 字母下标索引变化的监听器 */ public interface OnIndexChangeListener{ /** * 当字母下标位置发生变化的时候回调 * @param word 字母(A~Z) */ void onIndexChange(String word); } private OnIndexChangeListener onIndexChangeListener; /** * 设置字母下标索引变化的监听 * @param onIndexChangeListener */ public void setOnIndexChangeListener(OnIndexChangeListener onIndexChangeListener) { this.onIndexChangeListener = onIndexChangeListener; } }

工具类
DensityUtil
package com.example.mytongxunlu4;

import android.content.Context;

/**
 * 工具类
 */
public class DensityUtil {
    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
     */
    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }
}
适配器:
IndexAdapter
package com.example.mytongxunlu4;

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

import java.util.ArrayList;

/**
 *ListView适配器
 */
class IndexAdapter extends BaseAdapter {
    private Context context;
    private ArrayList persons;
    public IndexAdapter(Context context,ArrayList persons){
        this.context=context;
        this.persons=persons;

    }


    @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(context, 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;
    }
}
MainActivity
package com.example.mytongxunlu4;

import android.app.Activity;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.api.GoogleApiClient;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

/**
 * 在下按和移动时,列表更新
 */
public class MainActivity extends Activity {
    private ListView lv_main;
    private TextView tv_word;
    private IndexView iv_words;
    ArrayList persons;
    IndexAdapter adapter;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
//                  关闭显示的字母提示
                    tv_word.setVisibility(View.GONE);
                    break;
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        myOnclick();
//      准备数据
        initData();
        //设置适配器
        adapter = new IndexAdapter(MainActivity.this,persons);
        lv_main.setAdapter(adapter);
    }

    private void myOnclick() {
//      IndexView中回调出来的点击事件
        iv_words.setOnIndexChangeListener(new IndexView.OnIndexChangeListener() {
            @Override
            public void onIndexChange(String word) {
                updateWord(word);//提示框的字母显示和隐藏
                updateListView(word);//A~Z   根据右边的索引listView定位到某个位置
            }
        });

    }

    /**
     * 提示框的字母显示和隐藏
     * @param word
     */
    private void updateWord(String word) {
        //              显示提示框
        tv_word.setVisibility(View.VISIBLE);
        tv_word.setText(word + "");
        handler.removeCallbacksAndMessages(null);
        handler.sendEmptyMessageDelayed(1, 3000);
    }

    /**
     * 根据右边的索引listView定位到某个位置
     * @param word
     */
    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;
            }
        }
    }

    /**
     * 初始化控件
     */
    private void initView() {
        lv_main = (ListView) findViewById(R.id.lv_main);
        tv_word = (TextView) findViewById(R.id.tv_word);
        iv_words = (IndexView) findViewById(R.id.iv_words);
    }

    /**
     * 初始化数据
     */
    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("乔竞飞"));
        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() {
            @Override
            public int compare(Person lhs, Person rhs) {
                return lhs.getPinyin().compareTo(rhs.getPinyin());
            }
        });

    }





}
实体类:

package com.example.mytongxunlu4;

/**
 * 作者:杨光福 on 2016/5/18 11:25
 * 微信:yangguangfu520
 * QQ号:541433511
 * 作用:姓名:阿福
 *      拼音:AFU
 */
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 + '\'' +
                '}';
    }
}
汉字转化 拼音工具类:(对应要用jar包 pinyin4j-2.5.0.jar)

PinYinUtils
package com.example.mytongxunlu4;

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.exception.BadHanyuPinyinOutputFormatCombination;

/**
 * 作者:杨光福 on 2016/4/14 13:57
 * 微信:yangguangfu520
 * QQ号:541433511
 * 作用:把汉字转换成拼音
 * 阿福
 * AFU
 */
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;
    }
}
activity_main.xml


    
    
    


item_main.xml



    

    


源码下载:
Myself ---- mytongxunlu4
http://download.csdn.net/download/zhaihaohao1/10111351
参考视频:
 http://www.gulixueyuan.com/course/124/learn#lesson/1926


















你可能感兴趣的:(自定义)