在我们的智能手机使用中,经常会见到如联系人列表、城市名列表,需要寻找时,常见有两种方式:1、搜索,2、字母索引。今天我就分享下自己学习使用字母索引功能。Demo效果如下:
字母索引大体上实现原理为:
1)创建一个ListView(或者扩展ListV),展示联系人或城市、省份名;
2)在屏幕右边实现一个ListView,显示用作索引的字母;
3)当用户按下索引字母时,查找联系人或城市列表,找出第一个与之匹配的项,使listView跳转到该项。
代码实现如下:
1)显示城市名称
listView = (ListView) findViewById(R.id.listView);
adapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1, android.R.id.text1,
Cities.mCitiesStrings);
listView.setAdapter(adapter);
listView.setOnItemClickListener(itemClickListener);
2)显示索引字母,这一段是动态添加的列表内容,包含点击某个字母,城市列表跳转到索引字母开始的城市
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
for(final char letter:Letters){
TextView tv = new TextView(context);
tv.setText(String.valueOf(letter));
tv.setGravity(Gravity.CENTER);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String index = ((TextView) v).getText().toString();
Log.d(TAG, "onClick.letter = " + index);
listView.setSelection(getStartIndex(index));
}
});
layout.addView(tv);
}
3)根据字母查找索引字母开始的城市,因为保存的城市名称是汉字,所以此次需要进行转换,把汉字名称转换为拼音,使用了pinyin4j开源库,城市名字在我另一篇博客里有分享,几乎包含了中国所有的城市名
private int getStartIndex(String letter){
int returnInt = 0;
char index = 0;
for(int i=0;i<Letters.length;i++){
if(letter.equals(String.valueOf(Letters[i]))){
index = Letters[i];
break;
}
}
for(int j = 0; j < Cities.mCitiesStrings.length; j++){
String cityName = getPinYin(Cities.mCitiesStrings[j]);
Log.d(TAG, "getStartIndex.cityName = " + cityName);
if((cityName.toCharArray())[0] == index) {
returnInt = j;
break;
}
}
return returnInt;
}
4)调用pinyin4j开源库,将城市名称转换成拼音
private String getPinYin(String inputString){
StringBuffer output = new StringBuffer("");
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
format.setVCharType(HanyuPinyinVCharType.WITH_V);
char[] input = inputString.trim().toCharArray();
try {
for(int i = 0; i < input.length; i++){
if (Character.toString(input[i]).matches("[\u4E00-\u9FA5]+")) {
String[] temp = new String[0];
temp = PinyinHelper.toHanyuPinyinStringArray(input[i], format);
output.append(temp[0]);
output.append(" ");
} else
output.append(Character.toString(input[i]));
}
} catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
badHanyuPinyinOutputFormatCombination.printStackTrace();
}
return output.toString();
}
布局文件如下(部分可忽略):
<LinearLayout 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" android:orientation="vertical" android:background="@color/light" tools:context="com.huiyu.firstrankgas.ui.CityActivity"> <include layout="@layout/topbar_view"/> <!-- 搜索栏--> <LinearLayout android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:padding="5dp" android:background="@drawable/search_edit_bg" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="40dp"> <ImageView android:src="@drawable/search_icon" android:background="@color/light" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:layout_gravity="center" android:background="@null" android:layout_width="match_parent" android:layout_height="match_parent" android:hint="@string/search_hint" android:textSize="@dimen/text_size_middle_18"/> </LinearLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:background="@color/white" android:layout_width="match_parent" android:layout_height="40dp"> <TextView android:id="@+id/city" style="@style/text_style2" android:text="北京" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="30dp"/> <ListView android:id="@+id/listView" android:background="@color/white" android:dividerHeight="1dp" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> <LinearLayout android:id="@+id/letter_index" android:layout_gravity="right" android:orientation="vertical" android:layout_width="30dp" android:layout_height="match_parent"> </LinearLayout> </FrameLayout> </LinearLayout>
实现代码如下:
public class CityActivity extends Activity {
private static final String TAG = "CityActivity";
private char[] Letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
private Context context;
private ListView listView;
private ArrayAdapter adapter;
private LinearLayout layout;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_city);
initView();
}
private void initView(){
context = CityActivity.this;
textView = (TextView) findViewById(R.id.city);
listView = (ListView) findViewById(R.id.listView);
adapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1, android.R.id.text1,
Cities.mCitiesStrings);
listView.setAdapter(adapter);
listView.setOnItemClickListener(itemClickListener);
layout = (LinearLayout) findViewById(R.id.letter_index);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
for(final char letter:Letters){
TextView tv = new TextView(context);
tv.setText(String.valueOf(letter));
tv.setGravity(Gravity.CENTER);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String index = ((TextView) v).getText().toString();
Log.d(TAG, "onClick.letter = " + index);
listView.setSelection(getStartIndex(index));
}
});
layout.addView(tv);
}
}
private int getStartIndex(String letter){
int returnInt = 0;
char index = 0;
for(int i=0;i<Letters.length;i++){
if(letter.equals(String.valueOf(Letters[i]))){
index = Letters[i];
break;
}
}
for(int j = 0; j < Cities.mCitiesStrings.length; j++){
String cityName = getPinYin(Cities.mCitiesStrings[j]);
Log.d(TAG, "getStartIndex.cityName = " + cityName);
if((cityName.toCharArray())[0] == index) {
returnInt = j;
break;
}
}
return returnInt;
}
AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, "onItemClick() called with " + "parent = [" + parent + "], view = [" + view + "], position = [" + position + "], id = [" + id + "]");
String choice = Cities.mCitiesStrings[position];
Log.d(TAG, "onItemClick.choice = " + choice);
textView.setText(choice);
}
};
private String getPinYin(String inputString){
StringBuffer output = new StringBuffer("");
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
format.setVCharType(HanyuPinyinVCharType.WITH_V);
char[] input = inputString.trim().toCharArray();
try {
for(int i = 0; i < input.length; i++){
if (Character.toString(input[i]).matches("[\u4E00-\u9FA5]+")) {
String[] temp = new String[0];
temp = PinyinHelper.toHanyuPinyinStringArray(input[i], format);
output.append(temp[0]);
output.append(" ");
} else
output.append(Character.toString(input[i]));
}
} catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
badHanyuPinyinOutputFormatCombination.printStackTrace();
}
return output.toString();
}
}
参考文章: