使用RecyclerView自定义目录快速索引

快速索引在众多APP中是很常见的一个功能,尤其是在即时通讯和搜索的功能中,最近使用到就写了一个,希望对大家有用!

  • 先看一下效果:

这里写图片描述

  • 首先我们要写的就是自定义QuickIndexBar快速索引类
package com.example.quickindebar.view;

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


public class QuickIndexBar extends View {
    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" };
    private Paint paint;
    private int mCellWidth;
    private int mCellHeight;
    private float mTextHeight;
    private int currentIndex  =-1;
    private OnLetterChangeListener onLetterChangeListener;

    public OnLetterChangeListener getOnLetterChangeListener() {
        return onLetterChangeListener;
    }

    public void setOnLetterChangeListener(OnLetterChangeListener onLetterChangeListener) {
        this.onLetterChangeListener = onLetterChangeListener;
    }

    public interface OnLetterChangeListener{
        void onLetterChange(String letter);
        //手指抬起
        void onReset();
    }


    public QuickIndexBar(Context context) {
        this(context,null);
    }

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

    public QuickIndexBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        paint = new Paint();
//        paint.setColor(Color.);
        paint.setColor(Color.BLACK);
        paint.setTextSize(20);
        //消除锯齿
        paint.setAntiAlias(true);


        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        mTextHeight = (float) Math.ceil( fontMetrics.descent - fontMetrics.ascent);  //1.1---2   2.1--3

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mCellWidth = getMeasuredWidth();
        mCellHeight = getMeasuredHeight()/LETTERS.length;
    }

    /**
     * 绘制控件
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        字.画字();
        for (int i = 0; i < LETTERS.length; i++) {
            String letter = LETTERS[i];
            float mTextWidth = paint.measureText(letter);
              float x =(mCellWidth- mTextWidth)*0.5f;
            float y = (mCellHeight + mTextHeight) *0.5f+mCellHeight*i;

            if (i == currentIndex){
                paint.setColor(Color.GREEN);
            }else{
                paint.setColor(Color.BLACK);
            }

            canvas.drawText(letter, x,y,paint);
        }
    }


    /**
     * 处理 按下 移动 手指抬起
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                System.out.println("我按下了!!");
                int downY = (int) event.getY();
                //获取当前索引
                currentIndex = downY/mCellHeight;
               if (currentIndex<0||currentIndex>LETTERS.length-1){

               }else{
//                   ToastUtil.showToast(getContext(),LETTERS[currentIndex]);
                   if (onLetterChangeListener != null){
                       onLetterChangeListener.onLetterChange(LETTERS[currentIndex]);
                   }
               }
                //重新绘制
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                System.out.println("我移动了!!");
                int moveY = (int) event.getY();
                //获取当前索引
                currentIndex = moveY/mCellHeight;
                if (currentIndex<0||currentIndex>LETTERS.length-1){

                }else{
//                    ToastUtil.showToast(getContext(),LETTERS[currentIndex]);
                    if (onLetterChangeListener != null){
                        onLetterChangeListener.onLetterChange(LETTERS[currentIndex]);
                    }
                }
                //重新绘制
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                System.out.println("我手指抬起了!!");
                currentIndex = -1;
                //手动刷新
                invalidate();
                //表示手指抬起了
                if(onLetterChangeListener!= null){
                    onLetterChangeListener.onReset();
                }


                break;
        }


        // 为了 能够接受  move+up事件
        return true;
    }
}
  • 然后在xml中进行应用
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    <com.example.quickindebar.view.QuickIndexBar
        android:layout_width="30dp"
        android:id="@+id/quickindexbar"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:background="#dcdcdc" />
    <TextView
        android:layout_width="80dp"
        android:textColor="#fff"
        android:visibility="gone"
        android:background="@drawable/shape_corners"
        android:layout_centerInParent="true"
        android:text="A"
        android:id="@+id/tv_tips"
        android:textSize="20dp"
        android:gravity="center"
        android:layout_height="80dp" />

</RelativeLayout>
  • 记得引入pinyin4j jar包,具体可以在网上下载也可以从demo获取然后查看bean对象,并获取拼音字母
package com.example.quickindebar.bean;


import com.example.quickindebar.utils.PinYinUtil;

/**
 * Created by 黄家三少 on 2017/1/11.
 */


public class HaoHan implements Comparable<HaoHan> {
    public String name;
    public String pinyin;

    public HaoHan(String name){

        this.name = name;
        this.pinyin= PinYinUtil.getPinYin(name);
    }

    @Override
    public int compareTo(HaoHan another) {

        return this.pinyin.compareTo(another.pinyin);
    }
}
  • 获得拼音转换类
package com.example.quickindebar.utils;

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;

/**
 * Created by 黄家三少 on 2017/1/11.
 */


public class PinYinUtil {

    public static String getPinYin(String text) {
        {
            StringBuilder stringBuilder = null;
            try {
                HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
                format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
                format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
                stringBuilder = new StringBuilder();
                char[] chars = text.toCharArray();
                for (char ch : chars) {
                    if (Character.isWhitespace(ch)) {
                        continue;
                    }

                    if (ch > 128 || ch < -127) {

                        String[] array = PinyinHelper.toHanyuPinyinStringArray(ch, format);
                        stringBuilder.append(array[0]);
                    }
                }
            } catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
                badHanyuPinyinOutputFormatCombination.printStackTrace();
            }

            return stringBuilder.toString();
        }
    }
}

  • 跳转指定条目

    /**
     * RecyclerView 移动到当前位置,
     *
     * @param manager      manager 
     * @param mRecyclerView 当前的RecyclerView
     * @param n             要跳转的位置
     */
    public static void MoveToPosition(LinearLayoutManager manager, RecyclerView mRecyclerView, int n) {
        int firstItem = manager.findFirstVisibleItemPosition();
        int lastItem = manager.findLastVisibleItemPosition();
        if (n <= firstItem) {
            mRecyclerView.scrollToPosition(n);
        } else if (n <= lastItem) {
            int top = mRecyclerView.getChildAt(n - firstItem).getTop();
            mRecyclerView.scrollBy(0, top);
        } else {
            mRecyclerView.scrollToPosition(n);
        }

    }
  • MainActivity中的操作
package com.example.quickindebar;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;

import com.example.quickindebar.adapter.MyAdapter;
import com.example.quickindebar.bean.Cheeses;
import com.example.quickindebar.bean.HaoHan;
import com.example.quickindebar.utils.UIUtils;
import com.example.quickindebar.view.QuickIndexBar;
import com.example.quickindebar.view.RecycleViewDivider;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private QuickIndexBar quickindexbar;
    private RecyclerView mRecyclerView;
    private List<HaoHan> haoHans = new ArrayList<HaoHan>();
    private TextView tv_tips;
    private Context mContext;
    private MyAdapter mAdapter;
    private LinearLayoutManager manager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        fillDataAndSort();
        initView();
        initListener();
    }

    /**
     * 填充数据&排序
     */
    private void fillDataAndSort() {
        HaoHan haoHan;
        for (int i = 0; i < Cheeses.NAMES.length; i++) {
            haoHan = new HaoHan(Cheeses.NAMES[i]);
            haoHans.add(haoHan);
        }

        //排序
        Collections.sort(haoHans);

    }

    private void initView() {
        tv_tips = (TextView) findViewById(R.id.tv_tips);
        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        quickindexbar = (QuickIndexBar) findViewById(R.id.quickindexbar);
        manager = new LinearLayoutManager(mContext);
        manager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(manager);
        int mColor = ContextCompat.getColor(mContext, R.color.light_gray);
        mRecyclerView.addItemDecoration(new RecycleViewDivider(mContext, LinearLayoutManager.HORIZONTAL, 2, mColor));
        mAdapter = new MyAdapter(mContext, haoHans);
        mRecyclerView.setAdapter(mAdapter);
    }

    private void initListener() {
        quickindexbar.setOnLetterChangeListener(new QuickIndexBar.OnLetterChangeListener() {
            //选择的字母 变化的时候调用
            @Override
            public void onLetterChange(String letter) {
//                ToastUtil.showToast(MainActivity.this, letter);
                tv_tips.setVisibility(View.VISIBLE);
                tv_tips.setText(letter);
                for (int i = 0; i < haoHans.size(); i++) {
                    if (TextUtils.equals(haoHans.get(i).pinyin.charAt(0) + "", letter)) {
                        UIUtils.MoveToPosition(manager, mRecyclerView, i);
                        break;
                    }
                }

            }

            //手指抬起的时候调用
            @Override
            public void onReset() {
                tv_tips.setVisibility(View.GONE);
            }
        });

        mAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
            @Override
            public void OnClick(int position) {
                UIUtils.showToast(Cheeses.NAMES[position]);
            }
        });
    }
}
  • 最后看看Adapter中的操作
package com.example.quickindebar.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.example.quickindebar.R;
import com.example.quickindebar.bean.HaoHan;

import java.util.List;

import butterknife.ButterKnife;
import butterknife.InjectView;


public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private Context mContext;
    private List<HaoHan> haoHans;

    public MyAdapter(Context context) {
        this.mContext = context;
    }

    private OnItemClickListener onItemClickListener;

    public MyAdapter(Context mContext, List<HaoHan> haoHans) {
        this.mContext = mContext;
        this.haoHans = haoHans;
    }

    public interface OnItemClickListener {
        void OnClick(int position);
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.item_haohan, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        HaoHan preHaohan = null;
        if (position == 0) {
            preHaohan = null;
        } else {
            preHaohan = haoHans.get(position - 1);// 上一个好汉
        }


        HaoHan haoHan = haoHans.get(position);

        boolean showPinyin = true;
        if (preHaohan == null) {
            showPinyin = true;
        } else {
            if (haoHan.pinyin.charAt(0) == preHaohan.pinyin.charAt(0)) {
                showPinyin = false;
            } else {
                showPinyin = true;
            }
        }
// char
        holder.tvPinyin.setVisibility(showPinyin ? View.VISIBLE : View.GONE);
        holder.tvPinyin.setText(haoHan.pinyin.charAt(0) + "");  //
        holder.tvName.setText(haoHan.name);
        holder.tvName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (onItemClickListener != null) {
                    onItemClickListener.OnClick(position);
                }
            }
        });
    }


    @Override
    public int getItemCount() {
        return haoHans.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {

        @InjectView(R.id.tv_pinyin)
        TextView tvPinyin;
        @InjectView(R.id.tv_name)
        TextView tvName;

        public ViewHolder(View itemView) {
            super(itemView);
            ButterKnife.inject(this, itemView);
        }
    }

}

到这里完成操作,睡觉啦!困屎了……………………….

Demo下载地址:http://download.csdn.net/download/huangxiaoguo1/9735282

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值