android之带右侧字母(拼音)索引的列表

阅读更多


 在开发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;i 0 && 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 List sortList(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 List stations;
	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 Map selector;
	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建立完成。。

 

你可能感兴趣的:(ListView,右侧索引,拼音)