先见效果图如下:
本示例中使用Hashtable记录了中国大部分城市与地区的数据。其结构如下:
Hashtable(Head)
↑
↑←←←←←←←←←←←←(key,Hashtable<key,String[]>)
↑
↑←←←←←←←←←←←←("福建省",Hashtable<"福州市",{"仓山区"、"晋安区"... ...}>)
这个数据结构封装在了ChinaCityUtil工具类中。该类中定义了三种行政区类型,分别为:
TYPE_PROVINCE 省、直辖市、自治区级别
TYPE_CITY 城市
TYPE_REGION 城区
TYPE_PROVINCE级别的名称都是Hashtable(Head)的Key值集合,TYPE_CITY级别的名称是子Hashtable的Key值集合,TYPE_REGION级别的名称则直接就是String数组了。则很明确,为了获取Hashtable中Key值的集合,此处实现了一个方法getKeyArrayByTable(Hashtable<String, ? extends Object>)。
ChinaCityUtil中实现的另一个重要方法为findAreaStringArr(Hashtable<String, Hashtable<String, String[]>> table,
int type, String... args),该方法的最后一个参数args为指定想要获取的地区。如想获取"福建省"或"福建省"下"福州市"的所有区级别地区名称,则执行:
String[] arrCity = findAreaStringArr(hashtableHead,TYPE_REGION,"福建省");
String[] arrRegion = findAreaStringArr(hashtableHead,TYPE_REGION,"福建省","福州市");
由于Hashtable取key值时是无序的,为了方便用户选择地区,还需要对取得的数组进行按拼音排序。Java中,Collator可实现此功能。Collator在Comparator实例化后,通过ArrayAdapter.sort(comparator)与显示地区数组的适配器结合起来进行排序。
在开发过程中,会发现“重庆市”竟然排在了最后,究其原因为“重”在程序中被以拼音“zhong”的第四音进行排序了。为让以"chong"第二音进行排序,则在Comparator.compare(Strin obj1,String obj2)方法中在其进行比较顺序之前执行如下代码:
String obj1 = obj1.replace("重庆", "崇庆");
String obj2 = obj2.replace("重庆", "崇庆");
以同样为"chong"第四音的"崇"字进行排序即可。
完整代码如下:
ChinaCityAct.java
package lab.sodino.chinacity;
import java.util.Hashtable;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
/**
* @author Sodino E-mail:sodinoopen@hotmail.com
* @version Time:2011-8-20 下午08:41:25
*/
public class ChinaCityAct extends Activity implements AdapterView.OnItemSelectedListener {
private ChinaAlphabetComparator comparator;
private Spinner spinnerProvince;
private Spinner spinnerCity;
private Spinner spinnerRegion;
private TextView txtInfo;
private Hashtable<String, Hashtable<String, String[]>> hashtable;
private String[] arrProvince, arrCity, arrRegion;
private String province, city, region;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
comparator = new ChinaAlphabetComparator();
hashtable = ChinaCityUtil.initChinaCitysHashtable();
arrProvince = ChinaCityUtil.findAreaStringArr(hashtable, ChinaCityUtil.TYPE_PROVINCE);
ArrayAdapter<String> adapterProvince = getArrayAdapter(arrProvince);
spinnerProvince = (Spinner) findViewById(R.id.spinnerProvince);
spinnerProvince.setAdapter(adapterProvince);
spinnerProvince.setOnItemSelectedListener(this);
spinnerCity = (Spinner) findViewById(R.id.spinnerCity);
spinnerCity.setOnItemSelectedListener(this);
spinnerRegion = (Spinner) findViewById(R.id.spinnerRegion);
spinnerRegion.setOnItemSelectedListener(this);
txtInfo = (TextView) findViewById(R.id.txtInfo);
}
private ArrayAdapter<String> getArrayAdapter(String[] arr) {
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, arr);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
adapter.sort(comparator);
return adapter;
}
private void modifyCity(String province) {
arrCity = ChinaCityUtil.findAreaStringArr(hashtable, ChinaCityUtil.TYPE_CITY, province);
ArrayAdapter<String> adapterCity = getArrayAdapter(arrCity);
spinnerCity.setAdapter(adapterCity);
}
private void modifyRegion(String province, String city) {
arrRegion = ChinaCityUtil.findAreaStringArr(hashtable, ChinaCityUtil.TYPE_REGION, province,
city);
ArrayAdapter<String> adapterRegion = getArrayAdapter(arrRegion);
spinnerRegion.setAdapter(adapterRegion);
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (parent == spinnerProvince) {
province = arrProvince[position];
modifyCity(province);
} else if (parent == spinnerCity) {
city = arrCity[position];
modifyRegion(province, city);
} else if (parent == spinnerRegion) {
region = arrRegion[position];
txtInfo.setText(province + " " + city + " " + region);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
ChinaAlphabetComparator.java
package lab.sodino.chinacity;
import java.text.CollationKey;
import java.text.Collator;
import java.text.RuleBasedCollator;
import java.util.Comparator;
/**
* @author Sodino E-mail:sodinoopen@hotmail.com
* @version Time:2011-8-20 下午08:41:25
*/
public class ChinaAlphabetComparator implements Comparator<String> {
private RuleBasedCollator collator;
public ChinaAlphabetComparator() {
collator = (RuleBasedCollator) Collator.getInstance(java.util.Locale.CHINA);
}
@Override
public int compare(String obj1, String obj2) {
obj1 = obj1.replace("重庆", "崇庆");
obj2 = obj2.replace("重庆", "崇庆");
CollationKey c1 = collator.getCollationKey(obj1);
CollationKey c2 = collator.getCollationKey(obj2);
// When sorting a list of Strings however, it is generally necessary to
// compare each String multiple times. In this case, CollationKeys
// provide better performance. The CollationKey class converts a String
// to a series of bits that can be compared bitwise against other
// CollationKeys. A CollationKey is created by a Collator object for a
// given String.
return c1.compareTo(c2);
// return collator.compare(c1.getSourceString(), c2.getSourceString());
}
}
ChinaCityUtil.java
package lab.sodino.chinacity;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* @author Sodino E-mail:sodinoopen@hotmail.com
* @version Time:2011-8-20 下午08:41:25
*/
public class ChinaCityUtil {
public static final String CHINA = "中国";
public static final int TYPE_PROVINCE = 1;
public static final int TYPE_CITY = 2;
public static final int TYPE_REGION = 3;
public static Hashtable<String, Hashtable<String, String[]>> initChinaCitysHashtable() {
Hashtable<String, Hashtable<String, String[]>> tmpProvince = new Hashtable<String, Hashtable<String, String[]>>();
// 从小地区开始构建
Hashtable<String, String[]> tmpCity = null;
// 北京市
tmpCity = new Hashtable<String, String[]>();
tmpCity.put("北京市", new String[] { "昌平区", "朝阳区", "崇文区", "大兴区", "东城区", "房山区", "丰台区", "海淀区",
"怀柔区", "门头沟", "