首先看下自定义viewfastindex的实现
package cn.yuan.yu.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.support.v4.view.MotionEventCompat; import android.util.AttributeSet; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import cn.yuan.yu.R; /** * Created by yukuo on 2016/4/7. * 这是一个自定义的一个快速索引的自定义的控件 */ public class FastIndexBar extends View { /** * 上下文 */ private Context context; /** * 宽度 */ private int Width; /** * 高度 */ private int Height; /** * 字体的颜色 */ private int TextColor; /** * 字体大小 */ private int TextSize; /** * 控件的背景色 */ private int BackgroundColor; /** * 单元格高度 */ private float cellHeight; private static final String[] WORDS = 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; //这是一个索引 int index = -1; //监听器 private OnLetterChangeListener onLetterChangeListener; /** * 字母更新监听 */ public interface OnLetterChangeListener { /** * 当手指移动或者按下的时候调用的方法 * * @param letter */ void onLetterChange(String letter); /** * 当手指离开这个控件的时候调用的方法 */ void onUp(); } public void setOnLetterChangeListener( OnLetterChangeListener onLetterChangeListener) { this.onLetterChangeListener = onLetterChangeListener; } public FastIndexBar(Context context, AttributeSet attrs) { this(context, attrs, 0); this.context = context; } public FastIndexBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context = context; init(attrs, defStyleAttr); } /** * 初始化各种属性 */ private void init(AttributeSet attrs, int defStyleAttr) { /** * 获得我们所定义的自定义样式属性 */ TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.FastIndexBar, defStyleAttr, 0); for (int i = 0; i < typedArray.getIndexCount(); i++) { int attr = typedArray.getIndex(i); if (attr == R.styleable.FastIndexBar_BackgroundColor) { BackgroundColor = typedArray.getColor(attr, Color.WHITE); } else if (attr == R.styleable.FastIndexBar_TextColor) { TextColor = typedArray.getColor(attr, Color.BLUE); } else if (attr == R.styleable.FastIndexBar_TextSize) { TextSize = typedArray.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, getResources().getDisplayMetrics())); } } //释放资源 typedArray.recycle(); /** * 初始化一个画笔 */ paint = new Paint(); paint.setColor(TextColor);//设置画笔的颜色 paint.setTextSize(TextSize);//设置字体的大小 } /** * 绘制 * * @param canvas */ @Override protected void onDraw(Canvas canvas) { for (int i = 0; i < WORDS.length; i++) { String text = WORDS[i]; float x = (int) (Width * 0.5f - paint.measureText(text) * 0.5f); Rect bounds = new Rect(); // 把矩形对象赋值 paint.getTextBounds(text, 0, text.length(), bounds); int textHeight = bounds.height(); float y = (int) (cellHeight * 0.5f + textHeight * 0.5 + cellHeight * i); // 如果当前绘制的字母和按下的字母索引一样, 用灰色的画笔 // paint.setColor(i == index ? Color.GRAY : Color.BLACK); canvas.drawColor(BackgroundColor); canvas.drawText(text, x, y, paint); } } /** * 控件的手指触摸事件的监听 * * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { float y = -1; //选择的索引 int currentIndex = -1; switch (MotionEventCompat.getActionMasked(event)) { case MotionEvent.ACTION_DOWN://按下的时候 y = event.getY();//获得当时按下的y值 currentIndex = (int) (y / cellHeight); if (currentIndex >= 0 && currentIndex < WORDS.length) { // 健壮性处理, 在正常范围内 if (index != currentIndex) { // 字母的索引发生了变化 if (onLetterChangeListener != null) { onLetterChangeListener .onLetterChange(WORDS[currentIndex]); } index = currentIndex; } } break; case MotionEvent.ACTION_MOVE://移动的时候 y = event.getY(); currentIndex = (int) (y / cellHeight); if (currentIndex >= 0 && currentIndex < WORDS.length) { // 健壮性处理, 在正常范围内 if (index != currentIndex) { // 字母的索引发生了变化 if (onLetterChangeListener != null) { onLetterChangeListener .onLetterChange(WORDS[currentIndex]); } index = currentIndex; } } break; case MotionEvent.ACTION_UP://离开的时候 index = -1; if (onLetterChangeListener != null) { onLetterChangeListener .onUp(); } break; } invalidate(); return true; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); //单元格宽度 Width = getMeasuredWidth(); Height = getMeasuredHeight(); //单元格高度 cellHeight = Height * 1.0f / WORDS.length; } }布局如何应用呢?如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <cn.yuan.yu.view.ElasticListView android:id="@+id/lv_mylistview" android:layout_width="match_parent" android:layout_height="match_parent" /> <cn.yuan.yu.view.FastIndexBar android:id="@+id/fib_demo" android:layout_width="30dp" android:layout_height="280dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" app:TextColor="@color/themecolor" app:TextSize="9sp" /> <TextView android:id="@+id/tv_tip" android:layout_width="120dp" android:layout_height="120dp" android:layout_centerInParent="true" android:background="@drawable/text_bg_tip" android:gravity="center" android:textColor="@android:color/white" android:textSize="100sp" android:visibility="gone" /> </RelativeLayout>定义这个列表的适配器
package cn.yuan.qi.demomodule.adapter; import android.content.Context; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import java.util.List; import cn.yuan.qi.R; import cn.yuan.yu.bean.PhoneNumber; /** * Created by yukuo on 2016/4/12. */ public class PhoneNumberAdapter extends BaseAdapter { private List<PhoneNumber> list; private Context context; public PhoneNumberAdapter(Context context, List<PhoneNumber> list) { this.list = list; this.context = context; } @Override public View getView(int position, View convertView, ViewGroup parent) { MyHolder myHolder; if (convertView == null) { myHolder = new MyHolder(); convertView = View.inflate(context, R.layout.item_fastindex, null); myHolder.textViewname = (TextView) convertView.findViewById(R.id.tv_item_phone_name); myHolder.textViewphone = (TextView) convertView.findViewById(R.id.tv_item_phone_number); myHolder.index = (TextView) convertView.findViewById(R.id.tv_index); convertView.setTag(myHolder); } else { myHolder = (MyHolder) convertView.getTag(); } // 进行分组, 比较上一个拼音的首字母和自己是否一致, 如果不一致, 就显示tv_index String currentLetter = list.get(position).getPinyin(); String indexStr = null; if (position == 0) { // 1. 如果是第一位 indexStr = currentLetter; } else { // 获取上一个拼音 String preLetter = list.get(position-1).getPinyin(); if (!TextUtils.equals(currentLetter, preLetter)) { // 2. 当跟上一个不同时, 赋值, 显示 indexStr = currentLetter; } } myHolder.index.setVisibility(indexStr == null ? View.GONE : View.VISIBLE); myHolder.index.setText(indexStr == null ? "" : list.get(position).getPinyin()); myHolder.textViewname.setText(list.get(position).getName()); myHolder.textViewphone.setText(list.get(position).getNumber()); return convertView; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } class MyHolder { TextView textViewname; TextView textViewphone; TextView index; } }条目布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tv_index" android:layout_width="match_parent" android:layout_height="20dp" android:background="@color/themecolor" android:gravity="center_vertical" android:paddingLeft="10dp" android:text="A" android:textColor="@android:color/white" android:textSize="15sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal"> <TextView android:id="@+id/tv_item_phone_name" android:layout_width="100dp" android:layout_height="match_parent" android:layout_marginLeft="15dp" android:gravity="center_vertical" /> <TextView android:id="@+id/tv_item_phone_number" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="50dp" android:gravity="center_vertical" /> </LinearLayout> </LinearLayout>Activity界面业务代码
package cn.yuan.qi.demomodule.activity; import android.os.Bundle; import android.view.View; import android.widget.TextView; import java.util.Collections; import java.util.Comparator; import java.util.List; import butterknife.Bind; import cn.yuan.qi.R; import cn.yuan.qi.common.activity.BaseActivity; import cn.yuan.qi.common.application.QiApplication; import cn.yuan.qi.demomodule.adapter.PhoneNumberAdapter; import cn.yuan.yu.bean.PhoneNumber; import cn.yuan.yu.utils.GetPhoneData; import cn.yuan.yu.view.ElasticListView; import cn.yuan.yu.view.FastIndexBar; /** * Created by yukuo on 2016/4/4. */ public class FastIndexOfActivity extends BaseActivity { @Bind(R.id.lv_mylistview) ElasticListView lvMylistview; @Bind(R.id.fib_demo) FastIndexBar fibDemo; @Bind(R.id.tv_tip) TextView tvTip; private PhoneNumberAdapter phoneNumberAdapter; private List<PhoneNumber> lists; @Override public void initdata(Bundle extras) { // WeekGridAdapter weekGridAdapter = new WeekGridAdapter(this); fibDemo.setOnLetterChangeListener(new FastIndexBar.OnLetterChangeListener() { @Override public void onLetterChange(String letter) { tvTip.setText(letter); tvTip.setVisibility(View.VISIBLE); if (lists != null) { for (int i = 0; i < lists.size(); i++) { if (letter.equals(lists.get(i).getPinyin())) { lvMylistview.setSelection(i); return; } } } } @Override public void onUp() { tvTip.setVisibility(View.GONE); } }); GetPhoneData.getPhoneNumberData(this, new GetPhoneData.OnLoadSuccessListener() { @Override public void onSuccess(final List<PhoneNumber> list) { QiApplication.mainHandler.post(new Runnable() { @Override public void run() { lists = list; // 排序 Collections.sort(list, new Comparator<PhoneNumber>() { @Override public int compare(PhoneNumber lhs, PhoneNumber rhs) { return lhs.getPinyin().compareToIgnoreCase(rhs.getPinyin()); } }); phoneNumberAdapter = new PhoneNumberAdapter(FastIndexOfActivity.this, list); lvMylistview.setAdapter(phoneNumberAdapter); } }); } @Override public void onFailure() { } }); } @Override public int getContentLayout() { return R.layout.activity_fastindex; } }用到的工具类和实体
package cn.yuan.yu.utils; import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.provider.ContactsContract; import java.util.ArrayList; import java.util.List; import cn.yuan.yu.bean.PhoneNumber; /** * Created by yukuo on 2016/4/12. * 这是一个获取手机联系人等信息的工具类 */ public class GetPhoneData { public interface OnLoadSuccessListener { void onSuccess(List<PhoneNumber> list); void onFailure(); } /** * 这是一个返回一个联系人信息列表集合的方法 * * @param context 上下文 * @return */ public static void getPhoneNumberData(final Context context, final OnLoadSuccessListener onLoadSuccessListener) { new Thread() { @Override public void run() { List<PhoneNumber> list = new ArrayList<PhoneNumber>(); ContentResolver cr = context.getContentResolver(); Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null); if (cursor != null) { while (cursor.moveToNext()) { int PhoneName = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); int phoneNumbe = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER); PhoneNumber phoneNumber = new PhoneNumber(); //电话号码 phoneNumber.setNumber(cursor.getString(phoneNumbe)); L.i("手机号码", cursor.getString(phoneNumbe)); //名字 phoneNumber.setName(cursor.getString(PhoneName)); L.i("名字", cursor.getString(PhoneName)); list.add(phoneNumber); } if (onLoadSuccessListener != null) { onLoadSuccessListener.onSuccess(list); } } else { if (onLoadSuccessListener != null) { onLoadSuccessListener.onFailure(); } } } }.start(); } }实体
package cn.yuan.yu.bean; import net.sourceforge.pinyin4j.PinyinHelper; /** * Created by yukuo on 2016/4/12. * 这是一个联系人的实体类 */ public class PhoneNumber { private String number; private String name; private String email; /** * 这是一个存储每个名字首字母的变量 */ private String pinyin; public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public String getName() { return name; } public void setName(String name) { this.name = name; this.pinyin = getHeadChar(name); } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPinyin() { return pinyin; } public void setPinyin(String pinyin) { this.pinyin = pinyin; } /** * 得到首字母 * * @param str * @return */ public String getHeadChar(String str) { String convert = ""; char word = str.charAt(0); String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word); if (pinyinArray != null) { convert += pinyinArray[0].charAt(0); } else { convert += word; } return convert.toUpperCase(); } }最后的效果图
ok祝小伙伴成功吧