快速索引的简单实现

防微信联系人快速索引的简单实现,
首先,要画出26个英文字母,所以,我们就要自定义控件的技术了,这里直接继承View,进行重绘比较简单的实现
1.定义一个自己的类,去继承View, 具体的代码如下:

public class QuickIndexView extends View {
    // 画笔的 类
    private Paint mPaint;

    // 单元格的宽和高
    private int singleWindth;
    private float singleHeight;
    private OnLetterUpdeteListener mListener;
    // 需要用到的26个字母
    private static final String[] LETTERS = new String[] { "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 QuickIndexView(Context context) {
        this(context, null);
    }

    public QuickIndexView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public QuickIndexView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint = new Paint();
        // 设置抗锯齿
        mPaint.setAntiAlias(true);
        // 设置画笔的颜色为 白色
        mPaint.setColor(Color.WHITE);
        // 设置文本的 格式为 加粗的格式
        mPaint.setTypeface(Typeface.DEFAULT_BOLD);
        // 设置显示字体的大小 参数为 float
        mPaint.setTextSize(20);
    }

自定义一个类继承View,把用到的26个字母声明出来 .把前两个构造方法,串起来,还有就是画笔的初始化,在代码里面也都有对应的注释. 还有声明出来的两个int的变量 主要的作用就是去确定每一个字母在屏幕显示的位置,用来绘制的
接下来,就是去重写onDraw()方法去绘制,

@Override
    protected void onDraw(Canvas canvas) {
        for (int i = 0; i < LETTERS.length; i++) {
            String text = LETTERS[i];
            // mPaint.measureText 画笔的方法 可以得到画的文本的 宽度
            // 通过这个方法 得到x轴的 坐标点
            int x = (int) (singleWindth / 2.0f - mPaint.measureText(text) / 2.0f);
            // 获得 文本的所在的 矩形
            Rect bounds = new Rect();
            // 获取文本的高度
            // 参数1 文本的内容,string类型 ,参数2和参数3 是文本内容的长度
            mPaint.getTextBounds(text, 0, text.length(), bounds);
            // 通过矩形的四个参数得到文本的高度
            int textHeight = bounds.height();
            // 得到每个 字母画的y轴的坐标
            int y = (int) (singleHeight / 2.0f + textHeight / 2.0f + i
                    * singleHeight);
            canvas.drawText(text, x, y, mPaint);

        }
    }

这里在刚刚前面声明的两个int类型的变量就用到了,但是我们并没有看到,在哪里赋值,看下 变量在哪里赋值的把,


    // 当view的大小 改变的时候回调的方法
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        singleWindth = getMeasuredWidth();
        int height = getMeasuredHeight();
        singleHeight = height * 1.0f / LETTERS.length;

    }

下面就可以简单的运行下,看下效果了.当然我们要在xml布局中 引用我们的控件的
代码如下

<LinearLayout 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"
    android:orientation="horizontal"
    tools:context=".MainActivity" >
      <ListView 
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:id="@+id/lv_main"
        ></ListView>


    <com.qianfeng.quickindex.ui.QuickIndexView
        android:layout_width="40dp"
        android:background="#ff0000"
        android:id="@+id/my_indexView"
        android:layout_height="match_parent"
         />

</LinearLayout>

布局也很简单,下面就可以简单的运行下,看下效果了.效果图

图是我截的,嘻嘻,
下面就是处理我们的点击事件了,其实点击的事件,也很好的处理 ,下面看具体的代码:

private int lastIndex= -1;
    @SuppressLint("NewApi") @Override
    public boolean onTouchEvent(MotionEvent event) {
        int index=  -1;
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            surePostion(index, event);

            break;
        case MotionEvent.ACTION_MOVE:

            surePostion(index, event);

            break;
        case MotionEvent.ACTION_UP:
            index=-1;
            break;
        }
        // 这里返回true 表示持续接收事件的处理 
        return true;
    }
    // 确定当前的位置 跟上一次的位置不相等的时候,才去显示吐司
    private void surePostion( int index,MotionEvent event){
        index =(int) event.getY()/LETTERS.length;
        if(index>0&&index<LETTERS.length){
            if (index!=lastIndex) {

                if (mListener!=null) {
                    mListener.onLetterUpdete(LETTERS[index]);
                }

//              Utils.showToast(getContext(), LETTERS[index]);
            }

        }
         lastIndex=index;
    }

还有就是自定义的一个监听器的实现 看实现

    // 监听 字母被点击的时候回调接口
    public interface OnLetterUpdeteListener{

        // 当字母被点击的时候回调的方法
        void onLetterUpdete(String msg);
    }

    public void setonLetterUpdeteListener(OnLetterUpdeteListener letterListener){
        this.mListener=letterListener;
    }```

 下面就是ListView填充数据还有拼音字母的转化了,话不多说,直接上代码

public class MainActivity extends Activity {
private QuickIndexView mIndexView;
private ListView mlistView;
private List mPersons;

// private MyListViewAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mlistView = (ListView) findViewById(R.id.lv_main);
    mIndexView = (QuickIndexView) findViewById(R.id.my_indexView);
    // 监听 利用接口回调的

    mIndexView.setonLetterUpdeteListener(new OnLetterUpdeteListener() {

        @Override
        public void onLetterUpdete(String msg) {
            Utils.showToast(MainActivity.this, msg);

            for (int i = 0; i < mPersons.size(); i++) {
                Person person = mPersons.get(i);
                String l = person.getPinyin().charAt(0) + "";
                if (TextUtils.equals(l, msg)) {
                    mlistView.setSelection(i);
                    break;

                }

            }
        }
    });

    getDataAndSort();

    mlistView.setAdapter(new MyListViewAdapter(mPersons, this));

}

private void getDataAndSort() {
    mPersons = new ArrayList<Person>();
    for (int i = 0; i < Cheeses.NAMES.length; i++) {
        mPersons.add(new Person(Cheeses.NAMES[i]));
    }

    Collections.sort(mPersons);
}

}

汉子转化的拼音的类

public class PinyinUtils {

/**
 * 根据传入的字符串(包含汉子),得到 字母
 * 
 * @param str
 * @return
 */
public static String getPinyin(String str) {
    // 汉字拼音输出的类型 都封装到这个类上面去了 
    HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
    format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
    format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

    StringBuilder sb = new StringBuilder();

    char[] charArray = str.toCharArray();
    try {
        for (int i = 0; i < charArray.length; i++) {
            char c = charArray[i];
            // Character.isWhitespace 判断得到的字符串是不是空格 如果是空格跳过
            if (Character.isWhitespace(c)) {
                continue;
            }
            // 如果是特殊的字符, 直接添加到 sb上面去
            if (c >= -127 && c < 128) {
                sb.append(c);
            } else {
                String s = "";

                s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];
                sb.append(s);

            }
        }
    } catch (BadHanyuPinyinOutputFormatCombination e) {
        e.printStackTrace();

    }

    return sb.toString();
}

}

当然这里要用到一个jar包,下面有连接 自己去下载吧,还有就是ListViewAdapter的实现了

public class MyListViewAdapter extends BaseAdapter {
private List mPersons;
private Context context;

public MyListViewAdapter(List<Person> mPersons, Context context) {
    this.mPersons = mPersons;
    this.context = context;
}

@Override
public int getCount() {
    return mPersons.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) {

    if (convertView == null) {
        convertView = View.inflate(context, R.layout.list_item, null);



    }
    Viewholder holder = Viewholder.getHolder(convertView);



    Person p=mPersons.get(position);
    String flag=null;
    String currentPinyin=p.getPinyin().charAt(0)+"";

    if (position==0) {
        flag= currentPinyin;
    }else {
        String lastString=mPersons.get(position-1).getPinyin().charAt(0)+"";
        if (!lastString.equals(currentPinyin)) {
            flag=currentPinyin;
        }

    }
    holder.tv_name.setText(p.getName());
    // 如果flag ==null 的时候 不让它 显示 .不等于null 的时候显示 
    holder.tv_title.setVisibility(flag==null? View.GONE:View.VISIBLE);
    holder.tv_title.setText(currentPinyin);
    return convertView;
}

static class Viewholder {
    TextView tv_name;
    TextView tv_title;

    public static Viewholder getHolder(View view) {
        Object tag = view.getTag();

        if (tag != null) {
            return (Viewholder) (tag);
        } else {
            Viewholder viewholder = new Viewholder();
            viewholder.tv_name = (TextView) view.findViewById(R.id.tv_name);
            viewholder.tv_title = (TextView) view
                    .findViewById(R.id.tv_title);
            view.setTag(viewholder);
            return viewholder;

        }

    }
}

}

listView的布局文件

<?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_title"
        android:layout_width="match_parent"
        android:textColor="#ffffff"
        android:layout_height="40dp"
        android:background="#888888" />
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="match_parent"
        android:layout_height="40dp"/>

</LinearLayout>

下面是代码的下载连接
http://download.csdn.net/detail/ma229358084/9249367

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值