主布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.yijia.myapplication.MainActivity">
<ListView
android:id="@+id/lv_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/tv_word"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_centerInParent="true"
android:background="#44000000"
android:gravity="center"
android:text="A"
android:textColor="#000000"
android:textSize="30sp"
android:visibility="gone" />
<com.yijia.myapplication.IndexView
android:id="@+id/iv_words"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:background="#ff0000" />
</RelativeLayout>
自定义IndexView:首先绘制所有字母
public class IndexView extends View {
//每条item的高
private int itemWidth;
private int itemHeight;
private Paint paint;
private String[] words = {"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"};
public IndexView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
paint.setColor(Color.WHITE);//设置画笔颜色为白色
paint.setAntiAlias(true);//设置抗锯齿
paint.setTypeface(Typeface.DEFAULT_BOLD);//设置字体加粗
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
itemWidth = getMeasuredWidth();
itemHeight = getMeasuredHeight()/words.length;//总高除以26
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < words.length; i++) {
String word = words[i];//A
Rect rect = new Rect();
paint.getTextBounds(word, 0, 1, rect);
//获取字母的宽高
int wordWidth = rect.width();
int wordHeight = rect.height();
//字体的位置坐标(以矩形右下方为坐标)
float wordX = itemWidth / 2 - wordWidth / 2;
float wordY = itemHeight / 2 + wordHeight / 2 + i * itemHeight;
canvas.drawText(word, wordX, wordY, paint);
}
}
}
手指按下文字变色
1.重写onTouchEvent(),返回true,在down/move的过程中计算: int touchIndex = Y / itemHeight; 强制绘制
2.在onDraw()方法对于的下标设置画笔变色
3.在up的时候
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
float Y = (int) event.getY();
int index = (int) (Y / itemHeight);
if (index != touchIndex) {
touchIndex = index;
postInvalidate();
}
break;
case MotionEvent.ACTION_UP:
touchIndex=-1;
postInvalidate();
break;
}
return true;
}
重新绘制OnDraw添加代码: if(touchIndex==i){ paint.setColor(Color.GRAY);//设置灰色 }else{ paint.setColor(Color.WHITE);//设置白色 }
在移动和和按下时显示更新字母
自定义的view中天添加接口回掉数据
OnIndexChangeListener onIndexChangeListener;
public interface OnIndexChangeListener {
void onIndexChange(String word);
}
public void setOnIndexChangeListener(OnIndexChangeListener onIndexChangeListener) {
this.onIndexChangeListener = onIndexChangeListener;
}
在改变的位置设置接口回掉方法
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
float Y = (int) event.getY();
int index = (int) (Y / itemHeight);
if (index != touchIndex) {
touchIndex = index;
postInvalidate();
if (onIndexChangeListener != null && touchIndex < words.length) {
onIndexChangeListener.onIndexChange(words[index]);
}
}
break;
调用回掉接口
iv_words.setOnIndexChangeListener(new IndexView.OnIndexChangeListener() {
@Override
public void onIndexChange(String word) {
tv_word.setVisibility(View.VISIBLE);
tv_word.setText(word);
handler.postDelayed(new Runnable() {
@Override
public void run() {
tv_word.setVisibility(View.GONE);
}
}, 2000);
}
});
}
MainActivity中初始化数据并排序
/**
* 初始化数据
*/
private void initData() {
persons = new ArrayList<>();
persons.add(new Person("胡歌"));
persons.add(new Person("刘德华"));
persons.add(new Person("刘亦菲"));
persons.add(new Person("李小璐"));
persons.add(new Person("李小龙"));
persons.add(new Person("陈龙"));
persons.add(new Person("成龙"));
persons.add(new Person("赵立新"));
persons.add(new Person("周建"));
persons.add(new Person("杜甫"));
persons.add(new Person("阳泉"));
persons.add(new Person("和僧"));
persons.add(new Person("阿德"));
persons.add(new Person("奥丁"));
persons.add(new Person("路飞"));
persons.add(new Person("香克斯"));
persons.add(new Person("丁香"));
persons.add(new Person("苏有朋"));
persons.add(new Person("杨紫"));
persons.add(new Person("张一山"));
persons.add(new Person("可心"));
persons.add(new Person("小甜馨"));
persons.add(new Person("巴德"));
persons.add(new Person("武器大师"));
persons.add(new Person("任我行"));
persons.add(new Person("伊泽瑞尔"));
persons.add(new Person("维恩"));
persons.add(new Person("机器人"));
persons.add(new Person("崔浩月"));
persons.add(new Person("莫晓俊"));
//排序
Collections.sort(persons, new Comparator<Person>() {
@Override
public int compare(Person lhs, Person rhs) {
return lhs.getPinyin().compareTo(rhs.getPinyin());
}
});
}
添加适配器
class IndexAdapter extends BaseAdapter {
@Override
public int getCount() {
return persons.size();
}
@Override
public Object getItem(int position) {
return persons.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = View.inflate(MainActivity.this, R.layout.item_main, null);
holder = new ViewHolder();
holder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);
holder.tv_word = (TextView) convertView.findViewById(R.id.tv_word);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Person person = persons.get(position);
String word = person.getPinyin().substring(0, 1);
holder.tv_word.setText(word);//A
holder.tv_name.setText(person.getName());
if (position == 0) {
holder.tv_word.setVisibility(View.VISIBLE);
} else {
String preword = persons.get(position - 1).getPinyin().substring(0, 1);//获取前一个拼音
if (preword.equals(word)) {
holder.tv_word.setVisibility(View.GONE);
} else {
holder.tv_word.setVisibility(View.VISIBLE);
}
}
return convertView;
}
}
static class ViewHolder {
TextView tv_word;
TextView tv_name;
}
点击右边索引时定位到相应的位置
/**
* 点击后定位到某个单词
*/
private void updateListView(String word) {
for (int i = 0; i < persons.size(); i++) {
String pinyin = persons.get(i).getPinyin().substring(0, 1);//HUGE->H
if (word.equals(pinyin)) {
lv_main.setSelection(i);
return;//定位到第一个的时候就return,否则会定位到相应字母的最后一个
}
}
}