在开发app的过程中,如果用到通讯录或者类似的列表,需要快速在其中定位,可以根据列表项的拼音首字母来定位,这时候就需要用到右侧字母索引了。必如现在的微信通讯录界面就是如此。在实现这种功能的过程中,还是挺复杂的,很难我觉得。在网上各种查找资料,困难重重,好在最后终于捯饬出来了,伤不起。。。。特此记录一下写的过程。
1、创建自定的view,用作右侧列表索引。
public class RulerWidget extends View { public static String[] indexStr = { "#", "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 static int INDEX_LENGTH = indexStr.length; OnTouchingLetterChangedListener onTouchingLetterChangedListener; Paint mPaint = new Paint(); boolean showBkg = false; int choose = -1; public RulerWidget(Context context) { super(context); } public RulerWidget(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public RulerWidget(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // if(showBkg){ canvas.drawColor(Color.parseColor("#40000000")); // } int height = getHeight(); int width = getWidth(); int singleHeight = height / indexStr.length; for(int i=0;i0 && c< indexStr.length){ listener.onTouchingLetterChanged(indexStr[c]); choose = c; invalidate(); } } break; case MotionEvent.ACTION_MOVE: if(oldChoose != c && listener != null){ if(c > 0 && c< indexStr.length){ listener.onTouchingLetterChanged(indexStr[c]); choose = c; invalidate(); } } break; case MotionEvent.ACTION_UP: // showBkg = false; choose = -1; invalidate(); break; } return true; } @Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); } public void setOnTouchingLetterChangedListener( OnTouchingLetterChangedListener onTouchingLetterChangedListener) { this.onTouchingLetterChangedListener = onTouchingLetterChangedListener; } }
对应的回调接口定义:
/** * @date 2014-9-3 * @Description: ruler触摸回调 */ public interface OnTouchingLetterChangedListener{ public void onTouchingLetterChanged(String s); }
2、创建fragment片段对应的布局文件:
3、引入pinyin4j.jar包(版本建议使用最新),写一个工具类,包含获取中文字符串拼音首字母,获取中文拼音等方法。
public class StringHelper { public static String getPingYin(String src) { char[] t = src.toCharArray(); String[] strs = new String[t.length]; HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); format.setCaseType(HanyuPinyinCaseType.LOWERCASE); format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); format.setVCharType(HanyuPinyinVCharType.WITH_V); String str = ""; try{ for(int i=0; i
4、建立一个工具类,用于根据首字母排序,获取大些字母及对应的中文字符串(如A 阿尔法 B 北京 C 长沙 长春 常州等):
public class SortUtil { public static ListsortList(String[] srcNames, List list) { List newList = new ArrayList (); for(int i=0; i stations) { TreeSet set = new TreeSet (); // 获取初始化数据源中的首字母,添加到set中 for (Station station : stations) { set.add(StringHelper.getPinYinHeaderChar(station.getName()).substring( 0, 1)); } // 新数组的长度为原数据加上set的大小 String[] names = new String[stations.size() + set.size()]; int i = 0; for (String string : set) { names[i] = string; i++; } String[] pinYinNames = new String[stations.size()]; for (int j = 0; j < stations.size(); j++) { stations.get(j).setPinYinName( StringHelper .getPingYin(stations.get(j).getName().toString())); pinYinNames[j] = StringHelper.getPingYin(stations.get(j).getName() .toString()); } // 将原数据拷贝到新数据中 System.arraycopy(pinYinNames, 0, names, set.size(), pinYinNames.length); // 自动按照首字母排序 Arrays.sort(names, String.CASE_INSENSITIVE_ORDER); return names; } }
listViewAdapter,填充ListView的适配器:
public class ListViewAdapter extends BaseAdapter { private Context context; private Liststations; private ViewHolder viewHolder; public ListViewAdapter(Context context, List stations) { this.context = context; this.stations = stations; } @Override public int getCount() { return stations.size(); } @Override public Object getItem(int position) { return stations.get(position); } @Override public long getItemId(int position) { return position; } @Override public boolean isEnabled(int position) { if (stations.get(position).getName().length() == 1)// 如果是字母索引 return false;// 表示不能点击 return super.isEnabled(position); } @Override public View getView(int position, View convertView, ViewGroup parent) { String item = stations.get(position).getName(); viewHolder = new ViewHolder(); if(item.length() == 1) { convertView = LayoutInflater.from(context).inflate(R.layout.index, null); TextView indexTV = (TextView) convertView.findViewById(R.id.indexTV); indexTV.setText(stations.get(position).getName()); viewHolder.indexTV = indexTV; }else{ convertView = LayoutInflater.from(context).inflate(R.layout.item, null); TextView itemTV = (TextView) convertView.findViewById(R.id.itemTV); itemTV.setText(stations.get(position).getName()); viewHolder.itemTV = itemTV; } return convertView; } //内部类 private class ViewHolder { private TextView itemTV; private TextView indexTV; } }
5、最后一步,建立布局文件对应的fragment片段(或Activity,这里使用的是fragment):
public class ListStation extends Fragment { private Mapselector; private LinearLayout layoutIndex; private ListView listView; private TextView textView; private ListViewAdapter adapter; private String[] sections = { "#", "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 List stations; private List newStations; private int height; private boolean flag = false; private LinearLayout layout; private RulerWidget ruler; private Handler handler; private OverlayThread overlayThread; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.station_list, container, false); listView = (ListView) view.findViewById(R.id.listView); textView = (TextView) view.findViewById(R.id.tv); ruler = (RulerWidget) view.findViewById(R.id.sidrbar); ruler.setOnTouchingLetterChangedListener(new LetterListViewListener()); initOverlay(); return view; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onCreate(savedInstanceState); stations = StationService.getAllStation(); String[] allNames = SortUtil.sortIndex(stations); newStations = SortUtil.sortList(allNames, stations); //这个map是建立大写字母对应位于listView位置的索引 selector = new HashMap (); for(int i=0; i
这样,带拼音索引的listView建立完成。。