您的位置:首页 > 其它

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

2017-01-11 23:26 357 查看
快速索引在众多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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: