效果图
思考
- 将字母 A - Z 画出来
- 处理字母的触摸事件
- 提供使用的回调
- 联系人汉字转成拼音
- 按拼音排序
- 分组(同一个拼音开头的为一组)
- 将自定义的view和ListView绑定
实现
1. 绘制A-Z
- 准备好A-Z 26个字母
- 在onDraw方法里面计算每个字母的位置并绘制
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"};
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < LETTERS.length; i++) {
Rect rect = new Rect();
paint.getTextBounds(LETTERS[i], 0, 1, rect);
int width = (int) (screenWidth * 1.0 / 2 - rect.width() * 1.0 / 2);
int height = (int) (cellHeight * 1.0 / 2 + rect.height() * 1.0 / 2 + i * cellHeight);
canvas.drawText(LETTERS[i], width, height, paint);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
screenWidth = getMeasuredWidth();
screenHeight = getMeasuredHeight();
cellHeight = screenHeight * 1.0 / LETTERS.length;
}
2. 处理onTouchEvent事件
int touchIndex = -1;
@Override
public boolean onTouchEvent(MotionEvent event) {
int y;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
y = (int) event.getY();
for (int i = 0; i < LETTERS.length; i++) {
if (y > i * cellHeight && y < (i + 1) * cellHeight) {
if (touchIndex != i) {
Log.e(TAG, LETTERS[i]);
Toast.makeText(getContext(), LETTERS[i], 0).show();
touchIndex = i;
}
break;
}
}
break;
case MotionEvent.ACTION_MOVE:
y = (int) event.getY();
for (int i = 0; i < LETTERS.length; i++) {
if (y > i * cellHeight && y < (i + 1) * cellHeight) {
if (touchIndex != i) {
Log.e(TAG, LETTERS[i]);
Toast.makeText(getContext(), LETTERS[i], 0).show();
touchIndex = i;
}
break;
}
}
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
3. 提供回调方法
private OnIndexChangedListener listener;
public void setOnIndexChangedListener(OnIndexChangedListener listener) {
this.listener = listener;
}
public interface OnIndexChangedListener {
void onIndexChanged(String index);
}
@Override
public final boolean onTouchEvent(MotionEvent event) {
int y;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
y = (int) event.getY();
for (int i = 0; i < LETTERS.length; i++) {
if (y > i * cellHeight && y < (i + 1) * cellHeight) {
if (touchIndex != i) {
if (listener != null) {
listener.onIndexChanged(LETTERS[i]);
}
touchIndex = i;
}
break;
}
}
break;
case MotionEvent.ACTION_MOVE:
y = (int) event.getY();
for (int i = 0; i < LETTERS.length; i++) {
if (y > i * cellHeight && y < (i + 1) * cellHeight) {
if (touchIndex != i) {
if (listener != null) {
listener.onIndexChanged(LETTERS[i]);
}
touchIndex = i;
}
break;
}
}
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
4. 汉字转拼音
/** * 描述:汉字转拼音的工具类 * 作者 mjd * 日期:2015/12/10 12:50 */
public class PinYinUtils {
public static String getPinYin(String hanZi) {
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
format.setToneType(HanyuPinyinToneType.WITH_TONE_NUMBER);
StringBuilder sb = new StringBuilder();
char[] charArray = hanZi.toCharArray();
for (int i = 0; i < charArray.length; i++) {
char c = charArray[i];
if (Character.isWhitespace(c)) {
continue;
}
if (c >= -127 && c < 128) {
sb.append(c);
} else {
String s = "";
try {
s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];
sb.append(s);
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
sb.append(s);
}
}
}
return sb.toString();
}
}
5. 汉字按拼音排序
public class Person implements Comparable<Person> {
private String name;
private String pinyin;
public Person(String name) {
this.name = name;
this.pinyin = PinYinUtils.getPinYin(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPinyin() {
return pinyin;
}
public void setPinyin(String pinyin) {
this.pinyin = pinyin;
}
@Override
public int compareTo(@NonNull Person another) {
return this.pinyin.compareTo(another.getPinyin());
}
}
public class MainActivity extends AppCompatActivity {
private FastIndexBar fastIndexBar;
private RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fastIndexBar = (FastIndexBar) findViewById(R.id.fast_index_bar);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
fastIndexBar.setOnIndexChangedListener(new FastIndexBar.OnIndexChangedListener() {
@Override
public void onIndexChanged(String index) {
Toast.makeText(MainActivity.this, index, 0).show();
}
});
ContactAdapter adapter = new ContactAdapter(getContacts());
recyclerView.setAdapter(adapter);
RecyclerView.LayoutManager manager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(manager);
}
private List<Person> getContacts() {
List<Person> list = new ArrayList<>();
String[] names = Cheeses.NAMES;
for (int i = 0; i < names.length; i++) {
list.add(new Person(names[i]));
}
Collections.sort(list);
return list;
}
}
public class ContactAdapter extends RecyclerView.Adapter<MyViewHolder> {
private List<Person> personList;
public ContactAdapter(List<Person> personList) {
this.personList = personList;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = View.inflate(parent.getContext(), R.layout.item_contact, null);
view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Person person = personList.get(position);
holder.tvIndex.setText(String.valueOf(person.getPinyin().charAt(0)));
holder.tvName.setText(person.getName());
}
@Override
public int getItemCount() {
return personList.size();
}
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView tvIndex;
TextView tvName;
public MyViewHolder(View itemView) {
super(itemView);
tvIndex = (TextView) itemView.findViewById(R.id.tv_index);
tvName = (TextView) itemView.findViewById(R.id.tv_name);
}
}
6. 汉字按拼音分组
//在适配器的onBindViewHolder方法中判断
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Person person = personList.get(position)
String currentIndex = String.valueOf(person.getPinyin().charAt(0))
String str = null
if (position == 0) {
str = currentIndex
} else {
String preIndex = String.valueOf(personList.get(position - 1).getPinyin().charAt(0))
if (!currentIndex.equals(preIndex)) {
str = currentIndex
}
}
holder.tvIndex.setVisibility(str == null ? View.GONE : View.VISIBLE)
holder.tvIndex.setText(currentIndex)
holder.tvName.setText(person.getName())
}
7. 将快速索引控件与RecyclerView绑定
fastIndexBar.setOnIndexChangedListener(new FastIndexBar.OnIndexChangedListener() {
@Override
public void onIndexChanged(String index) {
showIndex(index);
for (int i = 0; i < personList.size(); i++) {
String currentIndex = String.valueOf(personList.get(i).getPinyin().charAt(0));
if (currentIndex.equals(index)) {
recyclerView.scrollToPosition(i);
break;
}
}
}
});
private Handler handler = new Handler();
private void showIndex(String index) {
tvCenter.setVisibility(View.VISIBLE);
tvCenter.setText(index);
handler.removeCallbacksAndMessages(null);
handler.postDelayed(new Runnable() {
@Override
public void run() {
tvCenter.setVisibility(View.GONE);
}
}, 2000);
}