快速索引在众多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