QQ5.0之快速索引

本文介绍如何在Android应用中自定义实现右侧索引栏,包括绘制索引字母、处理触摸事件、设置监听回调及使用拼音工具类进行数据排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一步先自定义画出来右边的索引栏

1用自定义布局画出来右边的索引栏

 private String[] letterArr = {"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"};

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < letterArr.length; i++) {
            String s = letterArr[i];
            ****这个是字体的高度****
            int textHeight = getTextHeight(s);
               **这个是把整个高度平分成26块**
            cellHeight = getMeasuredHeight() * 1f / letterArr.length;
            x = getMeasuredWidth() / 2;
            **这里看图**
            float y = cellHeight / 2 + textHeight / 2 + cellHeight * i;
            **这个是设置点击后字体的效果index在此处的引用在后面有赋值,先不要看**
            paint.setColor(index==i?pressColor:defColor);
            canvas.drawText(s,x,y,paint);

        }
    }

这里写图片描述

 private int getTextHeight(String s) {
        Rect rect = new Rect();
        **把字体的参数储存在矩形里面**
        paint.getTextBounds(s,0,s.length(),rect);
        return rect.height();
    }
 ```
 #2写触摸事件
 ```
 private  int index= -1;
  @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
            **这里会出现问题点了之后字体回不到白色,就要保存一下按下的字母,手松开之后在让字母变回白色**
            **获取 索引,每个字体的左边除以每层的高度再转化成int就是当前按下子母的坐标,保存一下,然后按下的index在上面的那一步设置按下的颜色黑色,**
                int tempindex = (int) (event.getY() / cellHeight);
                if (index != tempindex) {
                    index = tempindex;
                    if (index > -1 && index < letterArr.length) {
                        String letter = letterArr[index];

                    }
                }

                break;
                **松开手,在让索引变回去**
            case MotionEvent.ACTION_UP:
                index = -1;

                break;


        }
        **这里记得让重新刷新一下,**
        invalidate();
        return true;
    }

3设置监听,将当前的按下的字母穿个activity

在按下和抬起里面设置这两个回调

  public interface OnPressLetterListener {
  **这个是按下去传的字母**
        public void getLetter(String letter);
        **这个是收抬起来的时候把收抬起的状态传过去**
        public void release();
    }

    public void setOnPressLetterListener(OnPressLetterListener listener) {
        this.listener = listener;
    }

4从图片看这个activity是一个listView和quickindexbar组成的

4.1 findviewByid

4.2准备好我们要的数据bean并且排序

public class Friend implements Comparable<Friend>{
    public String pinYin;
    public  String name;
    public Friend(String name){
        this.name = name;
        this.pinYin = PinYinUtil.getPinYin(name);
    }

    @Override
    public int compareTo(Friend friend) {
        return this.pinYin.compareTo(friend.pinYin);
    }
}

 List<Friend> friends = new ArrayList<>();
 Collections.sort(friends);
 listview.setAdapter(new myAdapter());

4.2myAdapter

class myAdapter extends BaseAdapter {

        private ViewHolder viewHolder;

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

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

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

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            if (view == null) {
            **这个布局是有连个部分组成的,一个字母一条数据,组成listview的一个条目**
            ![这两个才是一个条目](http://img.blog.youkuaiyun.com/20170123141309758?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveHBkMzA4NDk3OTI2/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
                view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.adapter_friend, null);
                viewHolder =  new ViewHolder(view);
                view.setTag(viewHolder);
            }else{
                viewHolder   = (ViewHolder) view.getTag();

            }
            Friend friend = friends.get(i);
            viewHolder.tvName.setText(friend.name);
            String letter = friend.pinYin.substring(0, 1);
            if (i>0){
                String preletter = friends.get(i - 1).pinYin.substring(0, 1);
                **获取上一个条目的首字母比较是不是跟当前的一样,如果一样就隐藏当前首字母的那个布局**
                if(letter.equals(preletter)){
                    viewHolder.tvLetter.setVisibility(View.GONE);
                }else {
                    viewHolder.tvLetter.setVisibility(View.VISIBLE);
                    viewHolder.tvLetter.setText(letter);
                }

            }else {
                viewHolder.tvLetter.setVisibility(View.VISIBLE);
                viewHolder.tvLetter.setText(letter);
            }

            return view;
        }


    }
    static class ViewHolder {
        @InjectView(R.id.tv_letter)
        TextView tvLetter;
        @InjectView(R.id.tv_name)
        TextView tvName;

        ViewHolder(View view) {
            ButterKnife.inject(this, view);
        }
    }
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv_letter"
        android:text="A"
        android:textColor="#fff"
        android:background="#aa2b2b2b"
        android:padding="15dp"
        android:textSize="18sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tv_name"
        android:text="刘德华"
        android:textColor="#111"
        android:background="#fff"
        android:padding="15dp"
        android:textSize="18sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

4.4首字母的工具类

需要添加pinyin4j-2.5.0.jar

public class PinYinUtil  {
    /**
     * 获取汉字的拼音
     * @param chinese
     * @return
     */
    public static String getPinYin(String chinese){
        if(TextUtils.isEmpty(chinese))return null;

        //拼音转换的格式化,主要控制字母的大小写,以及是否需要声调
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.UPPERCASE);//设置大写字母
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);//不需要声调

        //ps:由于不支持对多个汉字进行获取,所以要将字符串转为字符数组,对单个汉字进行获取
        //最后,将每个字的拼音拼接起来,就是所有汉字的拼音
        StringBuilder builder = new StringBuilder();

        char[] chars = chinese.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];

            //1.要进行过滤空格,选择忽略
            if(Character.isWhitespace(c)){
                continue;
            }

            //2.要判断是否是中文,粗略的判断一下:由于一个汉字2个字节,
            //一个字节范围是-128~127,因此汉字肯定大于127
            if(c > 127){
                //有可能是汉字,就利用pinyin4j进行获取
                try {
                    //由于多音字的存在,所以返回的是数组,比如单:[chan, dan, shan]
                    String[] arr = PinyinHelper.toHanyuPinyinStringArray(c, format);
                    if(arr!=null){
                        //此处只能用第0个,原因:
                        //1.首先大部分汉字只有一个读音,多音字属于少数
                        //2.其次,我们也确实无能为力去判断应该用哪个,要判断一个汉字在一串文字
                        //中的精确读音,至少需要几个技术:a.分词算法 b.非常庞大的分词数据库
                        builder.append(arr[0]);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    //说明不是正确的汉字,选择忽略
                }
            }else {
                //肯定不是汉字,一般是ASCII码表中的字母,对于这个情况,我们选择
                //直接拼接
                builder.append(c);
            }
        }
        return  builder.toString();
    }
}

5设置回调的显示

quickIndexBar.setOnPressLetterListener(new QuickIndexBar.OnPressLetterListener() {
            @Override
            public void getLetter(String letter) {
                for (int i = 0; i < friends.size(); i++) {
                    String substring = friends.get(i).pinYin.substring(0, 1);
                    **如果点的首字母跟传过来的一样,就让listview跳转到当前的首字母**
                    if (substring.equals(letter)) {
                        listview.setSelection(i);
                    break;
                    }
                    showTextView(letter);
                }
            }

            @Override
            public void release() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        textView.setVisibility(View.GONE);
                    }
                },500);

            }
        });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值