├── .gitignore ├── CityList ├── .classpath ├── .project ├── .settings │ └── org.eclipse.core.resources.prefs ├── AndroidManifest.xml ├── bin │ ├── AndroidManifest.xml │ ├── CityList.apk │ ├── classes.dex │ ├── classes │ │ └── com │ │ │ └── liucanwen │ │ │ └── citylist │ │ │ ├── BuildConfig.class │ │ │ ├── MainActivity$1.class │ │ │ ├── MainActivity$SearchListTask.class │ │ │ ├── MainActivity.class │ │ │ ├── R$attr.class │ │ │ ├── R$color.class │ │ │ ├── R$dimen.class │ │ │ ├── R$drawable.class │ │ │ ├── R$id.class │ │ │ ├── R$layout.class │ │ │ ├── R$menu.class │ │ │ ├── R$string.class │ │ │ ├── R$style.class │ │ │ ├── R.class │ │ │ ├── adapter │ │ │ └── CityAdapter.class │ │ │ ├── data │ │ │ └── CityData.class │ │ │ ├── model │ │ │ └── CityItem.class │ │ │ └── widget │ │ │ ├── ContactItemComparator.class │ │ │ ├── ContactItemException.class │ │ │ ├── ContactItemInterface.class │ │ │ ├── ContactListAdapter.class │ │ │ ├── ContactListView$1.class │ │ │ ├── ContactListView.class │ │ │ ├── ContactListViewImpl.class │ │ │ ├── ContactsSectionIndexer.class │ │ │ ├── IndexScroller$1.class │ │ │ ├── IndexScroller.class │ │ │ └── pinyin │ │ │ ├── HanziToPinyin3$Token.class │ │ │ ├── HanziToPinyin3.class │ │ │ └── PinYin.class │ ├── dexedLibs │ │ └── android-support-v4-067dccf2020c5ee1f85b6c06df5b91ca.jar │ ├── res │ │ ├── drawable-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── icon_search.png │ │ │ ├── line.9.png │ │ │ ├── search_bg.9.png │ │ │ └── search_puin.9.png │ │ ├── drawable-mdpi │ │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ │ └── ic_launcher.png │ │ └── drawable-xxhdpi │ │ │ └── ic_launcher.png │ └── resources.ap_ ├── gen │ └── com │ │ └── liucanwen │ │ └── citylist │ │ ├── BuildConfig.java │ │ └── R.java ├── ic_launcher-web.png ├── libs │ └── android-support-v4.jar ├── proguard-project.txt ├── project.properties ├── res │ ├── drawable-hdpi │ │ ├── ic_launcher.png │ │ ├── icon_search.png │ │ ├── line.9.png │ │ ├── listitem_selector.xml │ │ ├── search_bg.9.png │ │ └── search_puin.9.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ ├── layout │ │ ├── activity_main.xml │ │ └── city_item.xml │ ├── menu │ │ └── main.xml │ ├── values-sw600dp │ │ └── dimens.xml │ ├── values-sw720dp-land │ │ └── dimens.xml │ ├── values-v11 │ │ └── styles.xml │ ├── values-v14 │ │ └── styles.xml │ └── values │ │ ├── color.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml └── src │ └── com │ └── liucanwen │ └── citylist │ ├── MainActivity.java │ ├── adapter │ └── CityAdapter.java │ ├── data │ └── CityData.java │ ├── model │ └── CityItem.java │ └── widget │ ├── ContactItemComparator.java │ ├── ContactItemException.java │ ├── ContactItemInterface.java │ ├── ContactListAdapter.java │ ├── ContactListView.java │ ├── ContactListViewImpl.java │ ├── ContactsSectionIndexer.java │ ├── IndexScroller.java │ └── pinyin │ ├── HanziToPinyin3.java │ └── PinYin.java ├── README.md ├── all_screenshot.jpg ├── screenshot1.png ├── screenshot2.png └── screenshot3.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | -------------------------------------------------------------------------------- /CityList/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CityList/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | CityList 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /CityList/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/com/liucanwen/citylist/widget/pinyin/HanziToPinyin3.java=UTF-8 3 | encoding//src/com/liucanwen/citylist/widget/pinyin/PinYin.java=UTF-8 4 | -------------------------------------------------------------------------------- /CityList/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /CityList/bin/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /CityList/bin/CityList.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/CityList.apk -------------------------------------------------------------------------------- /CityList/bin/classes.dex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes.dex -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/BuildConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/BuildConfig.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/MainActivity$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/MainActivity$1.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/MainActivity$SearchListTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/MainActivity$SearchListTask.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/MainActivity.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/MainActivity.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/R$attr.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/R$attr.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/R$color.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/R$color.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/R$dimen.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/R$dimen.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/R$drawable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/R$drawable.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/R$id.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/R$id.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/R$layout.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/R$layout.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/R$menu.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/R$menu.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/R$string.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/R$string.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/R$style.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/R$style.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/R.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/R.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/adapter/CityAdapter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/adapter/CityAdapter.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/data/CityData.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/data/CityData.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/model/CityItem.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/model/CityItem.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/ContactItemComparator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/ContactItemComparator.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/ContactItemException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/ContactItemException.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/ContactItemInterface.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/ContactItemInterface.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/ContactListAdapter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/ContactListAdapter.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/ContactListView$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/ContactListView$1.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/ContactListView.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/ContactListView.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/ContactListViewImpl.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/ContactListViewImpl.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/ContactsSectionIndexer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/ContactsSectionIndexer.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/IndexScroller$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/IndexScroller$1.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/IndexScroller.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/IndexScroller.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/pinyin/HanziToPinyin3$Token.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/pinyin/HanziToPinyin3$Token.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/pinyin/HanziToPinyin3.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/pinyin/HanziToPinyin3.class -------------------------------------------------------------------------------- /CityList/bin/classes/com/liucanwen/citylist/widget/pinyin/PinYin.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/classes/com/liucanwen/citylist/widget/pinyin/PinYin.class -------------------------------------------------------------------------------- /CityList/bin/dexedLibs/android-support-v4-067dccf2020c5ee1f85b6c06df5b91ca.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/dexedLibs/android-support-v4-067dccf2020c5ee1f85b6c06df5b91ca.jar -------------------------------------------------------------------------------- /CityList/bin/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /CityList/bin/res/drawable-hdpi/icon_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/res/drawable-hdpi/icon_search.png -------------------------------------------------------------------------------- /CityList/bin/res/drawable-hdpi/line.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/res/drawable-hdpi/line.9.png -------------------------------------------------------------------------------- /CityList/bin/res/drawable-hdpi/search_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/res/drawable-hdpi/search_bg.9.png -------------------------------------------------------------------------------- /CityList/bin/res/drawable-hdpi/search_puin.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/res/drawable-hdpi/search_puin.9.png -------------------------------------------------------------------------------- /CityList/bin/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /CityList/bin/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /CityList/bin/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /CityList/bin/resources.ap_: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/bin/resources.ap_ -------------------------------------------------------------------------------- /CityList/gen/com/liucanwen/citylist/BuildConfig.java: -------------------------------------------------------------------------------- 1 | /** Automatically generated file. DO NOT MODIFY */ 2 | package com.liucanwen.citylist; 3 | 4 | public final class BuildConfig { 5 | public final static boolean DEBUG = true; 6 | } -------------------------------------------------------------------------------- /CityList/gen/com/liucanwen/citylist/R.java: -------------------------------------------------------------------------------- 1 | /* AUTO-GENERATED FILE. DO NOT MODIFY. 2 | * 3 | * This class was automatically generated by the 4 | * aapt tool from the resource data it found. It 5 | * should not be modified by hand. 6 | */ 7 | 8 | package com.liucanwen.citylist; 9 | 10 | public final class R { 11 | public static final class attr { 12 | } 13 | public static final class color { 14 | public static final int background=0x7f040000; 15 | public static final int black=0x7f040001; 16 | public static final int bulegray=0x7f040006; 17 | public static final int divider_line=0x7f040012; 18 | public static final int font_focus=0x7f04000f; 19 | public static final int gold=0x7f04000b; 20 | public static final int gold_player=0x7f040010; 21 | public static final int gray=0x7f040007; 22 | public static final int graylight=0x7f040008; 23 | public static final int listview_item_normal=0x7f040013; 24 | public static final int listview_item_pressed=0x7f040014; 25 | public static final int message_checked=0x7f040015; 26 | public static final int message_no_check=0x7f040016; 27 | public static final int nearly_hard=0x7f04000e; 28 | public static final int orange=0x7f040009; 29 | public static final int orange_light=0x7f04000a; 30 | public static final int pink_red=0x7f040004; 31 | public static final int red=0x7f040005; 32 | public static final int semitransparent=0x7f04000d; 33 | public static final int stick_color_bg=0x7f040017; 34 | public static final int transparent=0x7f04000c; 35 | public static final int white=0x7f040002; 36 | public static final int whitetran=0x7f040011; 37 | public static final int yellow=0x7f040003; 38 | } 39 | public static final class dimen { 40 | /** Default screen margins, per the Android Design guidelines. 41 | 42 | Customize dimensions originally defined in res/values/dimens.xml (such as 43 | screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here. 44 | 45 | */ 46 | public static final int activity_horizontal_margin=0x7f050000; 47 | public static final int activity_vertical_margin=0x7f050001; 48 | } 49 | public static final class drawable { 50 | public static final int ic_launcher=0x7f020000; 51 | public static final int icon_search=0x7f020001; 52 | public static final int line=0x7f020002; 53 | public static final int listitem_selector=0x7f020003; 54 | public static final int search_bg=0x7f020004; 55 | public static final int search_puin=0x7f020005; 56 | } 57 | public static final class id { 58 | public static final int action_settings=0x7f090007; 59 | public static final int button_search=0x7f090002; 60 | public static final int cityName=0x7f090006; 61 | public static final int infoRowContainer=0x7f090005; 62 | public static final int input_search_query=0x7f090001; 63 | public static final int listview=0x7f090003; 64 | public static final int searchBarContainer=0x7f090000; 65 | public static final int sectionTextView=0x7f090004; 66 | } 67 | public static final class layout { 68 | public static final int activity_main=0x7f030000; 69 | public static final int city_item=0x7f030001; 70 | } 71 | public static final class menu { 72 | public static final int main=0x7f080000; 73 | } 74 | public static final class string { 75 | public static final int action_settings=0x7f060001; 76 | public static final int app_name=0x7f060000; 77 | public static final int hello_world=0x7f060002; 78 | } 79 | public static final class style { 80 | /** 81 | Base application theme, dependent on API level. This theme is replaced 82 | by AppBaseTheme from res/values-vXX/styles.xml on newer devices. 83 | 84 | 85 | Theme customizations available in newer API levels can go in 86 | res/values-vXX/styles.xml, while customizations related to 87 | backward-compatibility can go here. 88 | 89 | 90 | Base application theme for API 11+. This theme completely replaces 91 | AppBaseTheme from res/values/styles.xml on API 11+ devices. 92 | 93 | API 11 theme customizations can go here. 94 | 95 | Base application theme for API 14+. This theme completely replaces 96 | AppBaseTheme from BOTH res/values/styles.xml and 97 | res/values-v11/styles.xml on API 14+ devices. 98 | 99 | API 14 theme customizations can go here. 100 | */ 101 | public static final int AppBaseTheme=0x7f070000; 102 | /** Application theme. 103 | All customizations that are NOT specific to a particular API-level can go here. 104 | */ 105 | public static final int AppTheme=0x7f070001; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /CityList/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/ic_launcher-web.png -------------------------------------------------------------------------------- /CityList/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/libs/android-support-v4.jar -------------------------------------------------------------------------------- /CityList/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /CityList/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-17 15 | -------------------------------------------------------------------------------- /CityList/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /CityList/res/drawable-hdpi/icon_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/res/drawable-hdpi/icon_search.png -------------------------------------------------------------------------------- /CityList/res/drawable-hdpi/line.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/res/drawable-hdpi/line.9.png -------------------------------------------------------------------------------- /CityList/res/drawable-hdpi/listitem_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /CityList/res/drawable-hdpi/search_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/res/drawable-hdpi/search_bg.9.png -------------------------------------------------------------------------------- /CityList/res/drawable-hdpi/search_puin.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/res/drawable-hdpi/search_puin.9.png -------------------------------------------------------------------------------- /CityList/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /CityList/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /CityList/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /CityList/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 28 | 29 | 40 | 41 | 42 | 46 | 47 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /CityList/res/layout/city_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 19 | 20 | 27 | 28 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /CityList/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /CityList/res/values-sw600dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /CityList/res/values-sw720dp-land/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 128dp 8 | 9 | -------------------------------------------------------------------------------- /CityList/res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /CityList/res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /CityList/res/values/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #FF000000 5 | #FF000000 6 | #FFFFFFFF 7 | #FFFFE400 8 | #F63E2A 9 | #FF0000 10 | #f0f0f0 11 | #828282 12 | #cccccc 13 | #FF6600 14 | #fdaa0b 15 | #ffd700 16 | #00000000 17 | #90000000 18 | #97000000 19 | #D7F679 20 | #F7F466 21 | #87FFFFFF 22 | #FF575757 23 | 24 | #eef0ed 25 | #d4d4d4 26 | 27 | #90918f 28 | #323232 29 | 30 | #e2e2e2 31 | 32 | 33 | -------------------------------------------------------------------------------- /CityList/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /CityList/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CityList 5 | Settings 6 | Hello world! 7 | 8 | -------------------------------------------------------------------------------- /CityList/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.liucanwen.citylist; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import android.app.Activity; 7 | import android.content.Context; 8 | import android.os.AsyncTask; 9 | import android.os.Bundle; 10 | import android.text.Editable; 11 | import android.text.TextWatcher; 12 | import android.util.Log; 13 | import android.view.View; 14 | import android.widget.AdapterView; 15 | import android.widget.EditText; 16 | import android.widget.Toast; 17 | 18 | import com.liucanwen.citylist.adapter.CityAdapter; 19 | import com.liucanwen.citylist.data.CityData; 20 | import com.liucanwen.citylist.model.CityItem; 21 | import com.liucanwen.citylist.widget.ContactItemInterface; 22 | import com.liucanwen.citylist.widget.ContactListViewImpl; 23 | 24 | public class MainActivity extends Activity implements TextWatcher 25 | { 26 | private Context context_ = MainActivity.this; 27 | 28 | private ContactListViewImpl listview; 29 | 30 | private EditText searchBox; 31 | private String searchString; 32 | 33 | private Object searchLock = new Object(); 34 | boolean inSearchMode = false; 35 | 36 | private final static String TAG = "MainActivity2"; 37 | 38 | List contactList; 39 | List filterList; 40 | private SearchListTask curSearchTask = null; 41 | 42 | @Override 43 | public void onCreate(Bundle savedInstanceState) 44 | { 45 | super.onCreate(savedInstanceState); 46 | setContentView(R.layout.activity_main); 47 | 48 | filterList = new ArrayList(); 49 | contactList = CityData.getSampleContactList(); 50 | 51 | CityAdapter adapter = new CityAdapter(this, 52 | R.layout.city_item, contactList); 53 | 54 | listview = (ContactListViewImpl) this.findViewById(R.id.listview); 55 | listview.setFastScrollEnabled(true); 56 | listview.setAdapter(adapter); 57 | 58 | listview.setOnItemClickListener(new AdapterView.OnItemClickListener() 59 | { 60 | @Override 61 | public void onItemClick(AdapterView parent, View v, int position, 62 | long id) 63 | { 64 | List searchList = inSearchMode ? filterList 65 | : contactList; 66 | 67 | Toast.makeText(context_, 68 | searchList.get(position).getDisplayInfo(), 69 | Toast.LENGTH_SHORT).show(); 70 | } 71 | }); 72 | 73 | searchBox = (EditText) findViewById(R.id.input_search_query); 74 | searchBox.addTextChangedListener(this); 75 | } 76 | 77 | @Override 78 | public void afterTextChanged(Editable s) 79 | { 80 | searchString = searchBox.getText().toString().trim().toUpperCase(); 81 | 82 | if (curSearchTask != null 83 | && curSearchTask.getStatus() != AsyncTask.Status.FINISHED) 84 | { 85 | try 86 | { 87 | curSearchTask.cancel(true); 88 | } catch (Exception e) 89 | { 90 | Log.i(TAG, "Fail to cancel running search task"); 91 | } 92 | 93 | } 94 | curSearchTask = new SearchListTask(); 95 | curSearchTask.execute(searchString); 96 | } 97 | 98 | @Override 99 | public void beforeTextChanged(CharSequence s, int start, int count, 100 | int after) 101 | { 102 | } 103 | 104 | @Override 105 | public void onTextChanged(CharSequence s, int start, int before, int count) 106 | { 107 | // do nothing 108 | } 109 | 110 | private class SearchListTask extends AsyncTask 111 | { 112 | 113 | @Override 114 | protected String doInBackground(String... params) 115 | { 116 | filterList.clear(); 117 | 118 | String keyword = params[0]; 119 | 120 | inSearchMode = (keyword.length() > 0); 121 | 122 | if (inSearchMode) 123 | { 124 | // get all the items matching this 125 | for (ContactItemInterface item : contactList) 126 | { 127 | CityItem contact = (CityItem) item; 128 | 129 | boolean isPinyin = contact.getFullName().toUpperCase() 130 | .indexOf(keyword) > -1; 131 | boolean isChinese = contact.getNickName().indexOf(keyword) > -1; 132 | 133 | if (isPinyin || isChinese) 134 | { 135 | filterList.add(item); 136 | } 137 | 138 | } 139 | 140 | } 141 | return null; 142 | } 143 | 144 | protected void onPostExecute(String result) 145 | { 146 | 147 | synchronized (searchLock) 148 | { 149 | 150 | if (inSearchMode) 151 | { 152 | 153 | CityAdapter adapter = new CityAdapter(context_, 154 | R.layout.city_item, filterList); 155 | adapter.setInSearchMode(true); 156 | listview.setInSearchMode(true); 157 | listview.setAdapter(adapter); 158 | } else 159 | { 160 | CityAdapter adapter = new CityAdapter(context_, 161 | R.layout.city_item, contactList); 162 | adapter.setInSearchMode(false); 163 | listview.setInSearchMode(false); 164 | listview.setAdapter(adapter); 165 | } 166 | } 167 | 168 | } 169 | } 170 | 171 | } 172 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/adapter/CityAdapter.java: -------------------------------------------------------------------------------- 1 | package com.liucanwen.citylist.adapter; 2 | 3 | import java.util.List; 4 | 5 | import android.content.Context; 6 | import android.view.View; 7 | import android.widget.TextView; 8 | 9 | import com.liucanwen.citylist.R; 10 | import com.liucanwen.citylist.widget.ContactItemInterface; 11 | import com.liucanwen.citylist.widget.ContactListAdapter; 12 | 13 | public class CityAdapter extends ContactListAdapter 14 | { 15 | 16 | public CityAdapter(Context _context, int _resource, 17 | List _items) 18 | { 19 | super(_context, _resource, _items); 20 | } 21 | 22 | public void populateDataForRow(View parentView, ContactItemInterface item, 23 | int position) 24 | { 25 | View infoView = parentView.findViewById(R.id.infoRowContainer); 26 | TextView nicknameView = (TextView) infoView 27 | .findViewById(R.id.cityName); 28 | 29 | nicknameView.setText(item.getDisplayInfo()); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/data/CityData.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/src/com/liucanwen/citylist/data/CityData.java -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/model/CityItem.java: -------------------------------------------------------------------------------- 1 | package com.liucanwen.citylist.model; 2 | 3 | import com.liucanwen.citylist.widget.ContactItemInterface; 4 | 5 | public class CityItem implements ContactItemInterface 6 | { 7 | private String nickName; 8 | private String fullName; 9 | 10 | public CityItem(String nickName, String fullName) 11 | { 12 | super(); 13 | this.nickName = nickName; 14 | this.setFullName(fullName); 15 | } 16 | 17 | @Override 18 | public String getItemForIndex() 19 | { 20 | return fullName; 21 | } 22 | 23 | @Override 24 | public String getDisplayInfo() 25 | { 26 | return nickName; 27 | } 28 | 29 | public String getNickName() 30 | { 31 | return nickName; 32 | } 33 | 34 | public void setNickName(String nickName) 35 | { 36 | this.nickName = nickName; 37 | } 38 | 39 | public String getFullName() 40 | { 41 | return fullName; 42 | } 43 | 44 | public void setFullName(String fullName) 45 | { 46 | this.fullName = fullName; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/widget/ContactItemComparator.java: -------------------------------------------------------------------------------- 1 | package com.liucanwen.citylist.widget; 2 | 3 | import java.util.Comparator; 4 | 5 | public class ContactItemComparator implements Comparator 6 | { 7 | 8 | @Override 9 | public int compare(ContactItemInterface lhs, ContactItemInterface rhs) 10 | { 11 | if (lhs.getItemForIndex() == null || rhs.getItemForIndex() == null) 12 | return -1; 13 | 14 | return (lhs.getItemForIndex().compareTo(rhs.getItemForIndex())); 15 | 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/widget/ContactItemException.java: -------------------------------------------------------------------------------- 1 | package com.liucanwen.citylist.widget; 2 | 3 | public class ContactItemException extends Exception 4 | { 5 | 6 | public ContactItemException() 7 | { 8 | } 9 | 10 | public ContactItemException(String msg) 11 | { 12 | super(msg); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/widget/ContactItemInterface.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/CityList/src/com/liucanwen/citylist/widget/ContactItemInterface.java -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/widget/ContactListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.liucanwen.citylist.widget; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import android.content.Context; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ArrayAdapter; 11 | import android.widget.LinearLayout; 12 | import android.widget.TextView; 13 | 14 | import com.liucanwen.citylist.R; 15 | 16 | public class ContactListAdapter extends ArrayAdapter 17 | { 18 | 19 | private int resource; // store the resource layout id for 1 row 20 | private boolean inSearchMode = false; 21 | 22 | private ContactsSectionIndexer indexer = null; 23 | 24 | public ContactListAdapter(Context _context, int _resource, 25 | List _items) 26 | { 27 | super(_context, _resource, _items); 28 | resource = _resource; 29 | 30 | // need to sort the items array first, then pass it to the indexer 31 | Collections.sort(_items, new ContactItemComparator()); 32 | 33 | setIndexer(new ContactsSectionIndexer(_items)); 34 | 35 | } 36 | 37 | // get the section textview from row view 38 | // the section view will only be shown for the first item 39 | public TextView getSectionTextView(View rowView) 40 | { 41 | TextView sectionTextView = (TextView) rowView 42 | .findViewById(R.id.sectionTextView); 43 | return sectionTextView; 44 | } 45 | 46 | public void showSectionViewIfFirstItem(View rowView, 47 | ContactItemInterface item, int position) 48 | { 49 | TextView sectionTextView = getSectionTextView(rowView); 50 | 51 | // if in search mode then dun show the section header 52 | if (inSearchMode) 53 | { 54 | sectionTextView.setVisibility(View.GONE); 55 | } else 56 | { 57 | // if first item then show the header 58 | 59 | if (indexer.isFirstItemInSection(position)) 60 | { 61 | 62 | String sectionTitle = indexer.getSectionTitle(item 63 | .getItemForIndex()); 64 | sectionTextView.setText(sectionTitle); 65 | sectionTextView.setVisibility(View.VISIBLE); 66 | 67 | } else 68 | sectionTextView.setVisibility(View.GONE); 69 | } 70 | } 71 | 72 | // do all the data population for the row here 73 | // subclass overwrite this to draw more items 74 | public void populateDataForRow(View parentView, ContactItemInterface item, 75 | int position) 76 | { 77 | // default just draw the item only 78 | View infoView = parentView.findViewById(R.id.infoRowContainer); 79 | TextView nameView = (TextView) infoView.findViewById(R.id.cityName); 80 | nameView.setText(item.getItemForIndex()); 81 | } 82 | 83 | // this should be override by subclass if necessary 84 | @Override 85 | public View getView(int position, View convertView, ViewGroup parent) 86 | { 87 | ViewGroup parentView; 88 | 89 | ContactItemInterface item = getItem(position); 90 | 91 | if (convertView == null) 92 | { 93 | parentView = new LinearLayout(getContext()); 94 | String inflater = Context.LAYOUT_INFLATER_SERVICE; 95 | LayoutInflater vi = (LayoutInflater) getContext().getSystemService( 96 | inflater); 97 | vi.inflate(resource, parentView, true); 98 | } else 99 | { 100 | parentView = (LinearLayout) convertView; 101 | } 102 | 103 | showSectionViewIfFirstItem(parentView, item, position); 104 | 105 | populateDataForRow(parentView, item, position); 106 | 107 | return parentView; 108 | 109 | } 110 | 111 | public boolean isInSearchMode() 112 | { 113 | return inSearchMode; 114 | } 115 | 116 | public void setInSearchMode(boolean inSearchMode) 117 | { 118 | this.inSearchMode = inSearchMode; 119 | } 120 | 121 | public ContactsSectionIndexer getIndexer() 122 | { 123 | return indexer; 124 | } 125 | 126 | public void setIndexer(ContactsSectionIndexer indexer) 127 | { 128 | this.indexer = indexer; 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/widget/ContactListView.java: -------------------------------------------------------------------------------- 1 | package com.liucanwen.citylist.widget; 2 | 3 | import android.widget.ListView; 4 | import android.content.Context; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.util.AttributeSet; 8 | import android.view.GestureDetector; 9 | import android.view.MotionEvent; 10 | import android.widget.ListAdapter; 11 | 12 | public class ContactListView extends ListView 13 | { 14 | 15 | protected boolean mIsFastScrollEnabled = false; 16 | protected IndexScroller mScroller = null; 17 | protected GestureDetector mGestureDetector = null; 18 | 19 | // additional customization 20 | protected boolean inSearchMode = false; // whether is in search mode 21 | protected boolean autoHide = false; // alway show the scroller 22 | 23 | public ContactListView(Context context, AttributeSet attrs) 24 | { 25 | super(context, attrs); 26 | } 27 | 28 | public ContactListView(Context context, AttributeSet attrs, int defStyle) 29 | { 30 | super(context, attrs, defStyle); 31 | } 32 | 33 | public IndexScroller getScroller() 34 | { 35 | return mScroller; 36 | } 37 | 38 | @Override 39 | public boolean isFastScrollEnabled() 40 | { 41 | return mIsFastScrollEnabled; 42 | } 43 | 44 | // override this if necessary for custom scroller 45 | public void createScroller() 46 | { 47 | mScroller = new IndexScroller(getContext(), this); 48 | mScroller.setAutoHide(autoHide); 49 | mScroller.setShowIndexContainer(true); 50 | 51 | if (autoHide) 52 | mScroller.hide(); 53 | else 54 | mScroller.show(); 55 | } 56 | 57 | @Override 58 | public void setFastScrollEnabled(boolean enabled) 59 | { 60 | mIsFastScrollEnabled = enabled; 61 | if (mIsFastScrollEnabled) 62 | { 63 | if (mScroller == null) 64 | { 65 | createScroller(); 66 | } 67 | } else 68 | { 69 | if (mScroller != null) 70 | { 71 | mScroller.hide(); 72 | mScroller = null; 73 | } 74 | } 75 | } 76 | 77 | @Override 78 | public void draw(Canvas canvas) 79 | { 80 | super.draw(canvas); 81 | 82 | // Overlay index bar 83 | if (!inSearchMode) // dun draw the scroller if not in search mode 84 | { 85 | if (mScroller != null) 86 | mScroller.draw(canvas); 87 | } 88 | 89 | } 90 | 91 | @Override 92 | public boolean onTouchEvent(MotionEvent ev) 93 | { 94 | // Intercept ListView's touch event 95 | if (mScroller != null && mScroller.onTouchEvent(ev)) 96 | return true; 97 | 98 | if (mGestureDetector == null) 99 | { 100 | mGestureDetector = new GestureDetector(getContext(), 101 | new GestureDetector.SimpleOnGestureListener() 102 | { 103 | 104 | @Override 105 | public boolean onFling(MotionEvent e1, MotionEvent e2, 106 | float velocityX, float velocityY) 107 | { 108 | // If fling happens, index bar shows 109 | mScroller.show(); 110 | return super.onFling(e1, e2, velocityX, velocityY); 111 | } 112 | 113 | }); 114 | } 115 | mGestureDetector.onTouchEvent(ev); 116 | 117 | return super.onTouchEvent(ev); 118 | } 119 | 120 | @Override 121 | public boolean onInterceptTouchEvent(MotionEvent ev) 122 | { 123 | return true; 124 | } 125 | 126 | @Override 127 | public void setAdapter(ListAdapter adapter) 128 | { 129 | super.setAdapter(adapter); 130 | if (mScroller != null) 131 | mScroller.setAdapter(adapter); 132 | } 133 | 134 | @Override 135 | protected void onSizeChanged(int w, int h, int oldw, int oldh) 136 | { 137 | super.onSizeChanged(w, h, oldw, oldh); 138 | if (mScroller != null) 139 | mScroller.onSizeChanged(w, h, oldw, oldh); 140 | } 141 | 142 | public boolean isInSearchMode() 143 | { 144 | return inSearchMode; 145 | } 146 | 147 | public void setInSearchMode(boolean inSearchMode) 148 | { 149 | this.inSearchMode = inSearchMode; 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/widget/ContactListViewImpl.java: -------------------------------------------------------------------------------- 1 | package com.liucanwen.citylist.widget; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.util.AttributeSet; 6 | 7 | public class ContactListViewImpl extends ContactListView 8 | { 9 | 10 | public ContactListViewImpl(Context context, AttributeSet attrs) 11 | { 12 | super(context, attrs); 13 | } 14 | 15 | public void createScroller() 16 | { 17 | 18 | mScroller = new IndexScroller(getContext(), this); 19 | 20 | mScroller.setAutoHide(autoHide); 21 | 22 | // style 1 23 | // mScroller.setShowIndexContainer(false); 24 | // mScroller.setIndexPaintColor(Color.argb(255, 49, 64, 91)); 25 | 26 | // style 2 27 | mScroller.setShowIndexContainer(true); 28 | mScroller.setIndexPaintColor(Color.WHITE); 29 | 30 | if (autoHide) 31 | mScroller.hide(); 32 | else 33 | mScroller.show(); 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/widget/ContactsSectionIndexer.java: -------------------------------------------------------------------------------- 1 | package com.liucanwen.citylist.widget; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.SectionIndexer; 9 | 10 | public class ContactsSectionIndexer implements SectionIndexer 11 | { 12 | 13 | private static String OTHER = "#"; 14 | private static String[] mSections = { OTHER, "A", "B", "C", "D", "E", "F", 15 | "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", 16 | "T", "U", "V", "W", "X", "Y", "Z" }; 17 | 18 | private static int OTHER_INDEX = 0; // index of other in the mSections array 19 | 20 | private int[] mPositions; // store the list of starting position index for 21 | // each section 22 | // e.g. A start at index 0, B start at index 20, 23 | // C start at index 41 and so on 24 | 25 | private int mCount; // this is the count for total number of contacts 26 | 27 | // Assumption: the contacts array has been sorted 28 | public ContactsSectionIndexer(List contacts) 29 | { 30 | mCount = contacts.size(); 31 | 32 | initPositions(contacts); 33 | 34 | } 35 | 36 | public String getSectionTitle(String indexableItem) 37 | { 38 | int sectionIndex = getSectionIndex(indexableItem); 39 | return mSections[sectionIndex]; 40 | } 41 | 42 | // return which section this item belong to 43 | public int getSectionIndex(String indexableItem) 44 | { 45 | if (indexableItem == null) 46 | { 47 | return OTHER_INDEX; 48 | } 49 | 50 | indexableItem = indexableItem.trim(); 51 | String firstLetter = OTHER; 52 | 53 | if (indexableItem.length() == 0) 54 | { 55 | return OTHER_INDEX; 56 | } else 57 | { 58 | // get the first letter 59 | firstLetter = String.valueOf(indexableItem.charAt(0)).toUpperCase(); 60 | } 61 | 62 | int sectionCount = mSections.length; 63 | for (int i = 0; i < sectionCount; i++) 64 | { 65 | if (mSections[i].equals(firstLetter)) 66 | { 67 | return i; 68 | } 69 | } 70 | 71 | return OTHER_INDEX; 72 | 73 | } 74 | 75 | // initialize the position index 76 | public void initPositions(List contacts) 77 | { 78 | 79 | int sectionCount = mSections.length; 80 | mPositions = new int[sectionCount]; 81 | 82 | Arrays.fill(mPositions, -1); // initialize everything to -1 83 | 84 | // Assumption: list of items have already been sorted by the prefer 85 | // names 86 | int itemIndex = 0; 87 | 88 | for (ContactItemInterface contact : contacts) 89 | { 90 | 91 | String indexableItem = contact.getItemForIndex(); 92 | int sectionIndex = getSectionIndex(indexableItem); // find out which 93 | // section this 94 | // item belong 95 | // to 96 | 97 | if (mPositions[sectionIndex] == -1) // if not set before, then do 98 | // this, otherwise just ignore 99 | mPositions[sectionIndex] = itemIndex; 100 | 101 | itemIndex++; 102 | 103 | } 104 | 105 | int lastPos = -1; 106 | 107 | // now loop through, for all the ones not found, set position to the one 108 | // before them 109 | // this is to make sure the array is sorted for binary search to work 110 | for (int i = 0; i < sectionCount; i++) 111 | { 112 | if (mPositions[i] == -1) 113 | mPositions[i] = lastPos; 114 | 115 | lastPos = mPositions[i]; 116 | 117 | } 118 | 119 | } 120 | 121 | @Override 122 | public int getPositionForSection(int section) 123 | { 124 | if (section < 0 || section >= mSections.length) 125 | { 126 | return -1; 127 | } 128 | 129 | return mPositions[section]; 130 | } 131 | 132 | @Override 133 | public int getSectionForPosition(int position) 134 | { 135 | if (position < 0 || position >= mCount) 136 | { 137 | return -1; 138 | } 139 | 140 | int index = Arrays.binarySearch(mPositions, position); 141 | 142 | /* 143 | * Consider this example: section positions are 0, 3, 5; the supplied 144 | * position is 4. The section corresponding to position 4 starts at 145 | * position 3, so the expected return value is 1. Binary search will not 146 | * find 4 in the array and thus will return -insertPosition-1, i.e. -3. 147 | * To get from that number to the expected value of 1 we need to negate 148 | * and subtract 2. 149 | */ 150 | return index >= 0 ? index : -index - 2; 151 | } 152 | 153 | @Override 154 | public Object[] getSections() 155 | { 156 | return mSections; 157 | } 158 | 159 | // if first item in section, then return the section 160 | // otherwise return -1 161 | public boolean isFirstItemInSection(int position) 162 | { // check whether this item is the first item in section 163 | int section = Arrays.binarySearch(mPositions, position); 164 | return (section > -1); 165 | 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/widget/IndexScroller.java: -------------------------------------------------------------------------------- 1 | package com.liucanwen.citylist.widget; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.RectF; 8 | import android.os.Handler; 9 | import android.os.Message; 10 | import android.os.SystemClock; 11 | import android.util.Log; 12 | import android.view.MotionEvent; 13 | import android.widget.Adapter; 14 | import android.widget.ListView; 15 | import android.widget.SectionIndexer; 16 | 17 | // taken from https://github.com/woozzu/indexableListView IndexScroller 18 | // rewrite some sections to make it more customizable 19 | public class IndexScroller 20 | { 21 | 22 | /** 23 | * Add additional properties for customization 24 | * 25 | */ 26 | // Hung - store the last touch down eventX and eventY so that we can detect 27 | // where user click on list view 28 | // indexscroller will override touch event of listview, so onclicklistener 29 | // will not work 30 | private float lastTouchDownEventX = -1; 31 | private float lastTouchDownEventY = -1; 32 | 33 | // whether to autohide the scroller 34 | // false will always show the index bar 35 | // true will hide the scrollbar at first, but slowly show it later 36 | private boolean autoHide = false; 37 | 38 | // minor optimizations 39 | private Paint indexbarContainerPaint = new Paint(); // paint for indexbar 40 | // container 41 | private Paint indexPaint = new Paint(); 42 | 43 | private boolean showIndexContainer = false; // whether to show the outer 44 | // index container 45 | private int indexbarContainerBgColor = Color.BLACK; 46 | private int indexPaintColor = Color.WHITE; // color for section title 47 | 48 | // / end additional properties 49 | 50 | private float mIndexbarWidth; 51 | private float mIndexbarMargin; 52 | private float mPreviewPadding; 53 | private float mDensity; 54 | private float mScaledDensity; 55 | private float mAlphaRate; 56 | private int mState = STATE_HIDDEN; 57 | private int mListViewWidth; 58 | private int mListViewHeight; 59 | private int mCurrentSection = -1; 60 | private boolean mIsIndexing = false; 61 | private ListView mListView = null; 62 | private SectionIndexer mIndexer = null; 63 | private String[] mSections = null; 64 | private RectF mIndexbarRect; 65 | 66 | private static final int STATE_HIDDEN = 0; 67 | private static final int STATE_SHOWING = 1; 68 | private static final int STATE_SHOWN = 2; 69 | private static final int STATE_HIDING = 3; 70 | 71 | public IndexScroller(Context context, ListView lv) 72 | { 73 | mDensity = context.getResources().getDisplayMetrics().density; 74 | mScaledDensity = context.getResources().getDisplayMetrics().scaledDensity; 75 | mListView = lv; 76 | 77 | setAdapter(mListView.getAdapter()); 78 | 79 | mIndexbarWidth = 30 * mDensity; 80 | mIndexbarMargin = 0 * mDensity; 81 | mPreviewPadding = 5 * mDensity; 82 | 83 | // customization of paint colors 84 | // outer container 85 | indexbarContainerPaint.setAntiAlias(true); 86 | 87 | // letter in section 88 | indexPaint.setAntiAlias(true); 89 | indexPaint.setTextSize(12 * mScaledDensity); 90 | } 91 | 92 | public IndexScroller(Context context, ListView lv, SectionIndexer indexer) 93 | { 94 | this(context, lv); 95 | 96 | mIndexer = indexer; 97 | 98 | } 99 | 100 | // draw the outer rounded container 101 | public void drawIndexBarContainer(Canvas canvas) 102 | { 103 | indexbarContainerPaint.setColor(indexbarContainerBgColor); 104 | indexbarContainerPaint.setAlpha((int) (64 * mAlphaRate)); // opacity 105 | canvas.drawRoundRect(mIndexbarRect, 5 * mDensity, 5 * mDensity, 106 | indexbarContainerPaint); 107 | } 108 | 109 | public void drawSections(Canvas canvas) 110 | { 111 | indexPaint.setColor(indexPaintColor); 112 | indexPaint.setAlpha((int) (255 * mAlphaRate)); 113 | 114 | float sectionHeight = (mIndexbarRect.height() - 2 * mIndexbarMargin) 115 | / mSections.length; 116 | float paddingTop = (sectionHeight - (indexPaint.descent() - indexPaint 117 | .ascent())) / 2; 118 | 119 | // draw the section letters 120 | for (int i = 0; i < mSections.length; i++) 121 | { 122 | float paddingLeft = (mIndexbarWidth - indexPaint 123 | .measureText(mSections[i])) / 2; 124 | canvas.drawText(mSections[i], mIndexbarRect.left + paddingLeft, 125 | mIndexbarRect.top + mIndexbarMargin + sectionHeight * i 126 | + paddingTop - indexPaint.ascent(), indexPaint); 127 | } 128 | } 129 | 130 | public void drawCurrentSection(Canvas canvas) 131 | { 132 | if (mCurrentSection >= 0) 133 | { 134 | 135 | // Log.i("IndexScroller", "current section: " + mCurrentSection); 136 | 137 | // Preview is shown when mCurrentSection is set 138 | // mCurrentSection is the letter that is being pressed 139 | // this will draw the big preview text on top of the listview 140 | Paint previewPaint = new Paint(); 141 | previewPaint.setColor(Color.BLACK); 142 | previewPaint.setAlpha(96); 143 | previewPaint.setAntiAlias(true); 144 | previewPaint.setShadowLayer(3, 0, 0, Color.argb(64, 0, 0, 0)); 145 | 146 | Paint previewTextPaint = new Paint(); 147 | previewTextPaint.setColor(Color.WHITE); 148 | previewTextPaint.setAntiAlias(true); 149 | previewTextPaint.setTextSize(50 * mScaledDensity); 150 | 151 | float previewTextWidth = previewTextPaint 152 | .measureText(mSections[mCurrentSection]); 153 | float previewSize = 2 * mPreviewPadding 154 | + previewTextPaint.descent() - previewTextPaint.ascent(); 155 | RectF previewRect = new RectF((mListViewWidth - previewSize) / 2, 156 | (mListViewHeight - previewSize) / 2, 157 | (mListViewWidth - previewSize) / 2 + previewSize, 158 | (mListViewHeight - previewSize) / 2 + previewSize); 159 | 160 | canvas.drawRoundRect(previewRect, 5 * mDensity, 5 * mDensity, 161 | previewPaint); 162 | canvas.drawText(mSections[mCurrentSection], previewRect.left 163 | + (previewSize - previewTextWidth) / 2 - 1, previewRect.top 164 | + mPreviewPadding - previewTextPaint.ascent() + 1, 165 | previewTextPaint); 166 | } 167 | } 168 | 169 | public void draw(Canvas canvas) 170 | { 171 | if (mState == STATE_HIDDEN) 172 | return; 173 | 174 | if (showIndexContainer) 175 | drawIndexBarContainer(canvas); 176 | 177 | if (mSections != null && mSections.length > 0) 178 | { 179 | 180 | drawCurrentSection(canvas); 181 | drawSections(canvas); 182 | } 183 | } 184 | 185 | public boolean onTouchEvent(MotionEvent ev) 186 | { 187 | switch (ev.getAction()) 188 | { 189 | case MotionEvent.ACTION_DOWN: 190 | lastTouchDownEventX = ev.getX(); // Hung capture the event for later 191 | // use in listview item click 192 | lastTouchDownEventY = ev.getY(); 193 | 194 | // If down event occurs inside index bar region, start indexing 195 | if (mState != STATE_HIDDEN && contains(ev.getX(), ev.getY())) 196 | { 197 | setState(STATE_SHOWN); 198 | 199 | // It demonstrates that the motion event started from index bar 200 | mIsIndexing = true; 201 | // Determine which section the point is in, and move the list to 202 | // that section 203 | mCurrentSection = getSectionByPoint(ev.getY()); 204 | mListView.setSelection(mIndexer 205 | .getPositionForSection(mCurrentSection)); 206 | return true; 207 | } 208 | break; 209 | case MotionEvent.ACTION_MOVE: 210 | if (mIsIndexing) 211 | { 212 | // If this event moves inside index bar 213 | if (contains(ev.getX(), ev.getY())) 214 | { 215 | // Determine which section the point is in, and move the 216 | // list to that section 217 | mCurrentSection = getSectionByPoint(ev.getY()); 218 | mListView.setSelection(mIndexer 219 | .getPositionForSection(mCurrentSection)); 220 | } 221 | return true; 222 | } 223 | break; 224 | case MotionEvent.ACTION_UP: 225 | if (mIsIndexing) 226 | { 227 | mIsIndexing = false; 228 | mCurrentSection = -1; 229 | } 230 | // only hide if state is auto hiding 231 | if (autoHide) 232 | { 233 | if (mState == STATE_SHOWN) 234 | setState(STATE_HIDING); 235 | } 236 | break; 237 | } 238 | return false; 239 | } 240 | 241 | public void onSizeChanged(int w, int h, int oldw, int oldh) 242 | { 243 | mListViewWidth = w; 244 | mListViewHeight = h; 245 | mIndexbarRect = new RectF(w - mIndexbarMargin - mIndexbarWidth, 246 | mIndexbarMargin, w - mIndexbarMargin, h - mIndexbarMargin); 247 | } 248 | 249 | public void show() 250 | { 251 | if (mState == STATE_HIDDEN) 252 | setState(STATE_SHOWING); 253 | else if (mState == STATE_HIDING) 254 | setState(STATE_HIDING); 255 | } 256 | 257 | public void hide() 258 | { 259 | if (mState == STATE_SHOWN) 260 | setState(STATE_HIDING); 261 | } 262 | 263 | public void setAdapter(Adapter adapter) 264 | { 265 | if (adapter instanceof SectionIndexer) 266 | { 267 | mIndexer = (SectionIndexer) adapter; 268 | mSections = (String[]) mIndexer.getSections(); 269 | } else if (adapter instanceof ContactListAdapter) 270 | { 271 | ContactListAdapter c = (ContactListAdapter) adapter; 272 | mIndexer = c.getIndexer(); 273 | mSections = (String[]) mIndexer.getSections(); 274 | } 275 | } 276 | 277 | private void setState(int state) 278 | { 279 | if (state < STATE_HIDDEN || state > STATE_HIDING) 280 | return; 281 | 282 | mState = state; 283 | switch (mState) 284 | { 285 | case STATE_HIDDEN: 286 | // Cancel any fade effect 287 | mHandler.removeMessages(0); 288 | break; 289 | case STATE_SHOWING: 290 | // Start to fade in 291 | mAlphaRate = 0; 292 | fade(0); 293 | break; 294 | case STATE_SHOWN: 295 | // Cancel any fade effect 296 | mHandler.removeMessages(0); 297 | break; 298 | case STATE_HIDING: 299 | // Start to fade out after three seconds 300 | mAlphaRate = 1; 301 | fade(3000); 302 | break; 303 | } 304 | } 305 | 306 | private boolean contains(float x, float y) 307 | { 308 | // Determine if the point is in index bar region, which includes the 309 | // right margin of the bar 310 | return (x >= mIndexbarRect.left && y >= mIndexbarRect.top && y <= mIndexbarRect.top 311 | + mIndexbarRect.height()); 312 | } 313 | 314 | private int getSectionByPoint(float y) 315 | { 316 | if (mSections == null || mSections.length == 0) 317 | return 0; 318 | if (y < mIndexbarRect.top + mIndexbarMargin) 319 | return 0; 320 | if (y >= mIndexbarRect.top + mIndexbarRect.height() - mIndexbarMargin) 321 | return mSections.length - 1; 322 | return (int) ((y - mIndexbarRect.top - mIndexbarMargin) / ((mIndexbarRect 323 | .height() - 2 * mIndexbarMargin) / mSections.length)); 324 | } 325 | 326 | private void fade(long delay) 327 | { 328 | mHandler.removeMessages(0); 329 | mHandler.sendEmptyMessageAtTime(0, SystemClock.uptimeMillis() + delay); 330 | } 331 | 332 | private Handler mHandler = new Handler() 333 | { 334 | 335 | @Override 336 | public void handleMessage(Message msg) 337 | { 338 | super.handleMessage(msg); 339 | 340 | switch (mState) 341 | { 342 | case STATE_SHOWING: 343 | // Fade in effect 344 | mAlphaRate += (1 - mAlphaRate) * 0.2; 345 | if (mAlphaRate > 0.9) 346 | { 347 | mAlphaRate = 1; 348 | setState(STATE_SHOWN); 349 | } 350 | 351 | mListView.invalidate(); 352 | fade(10); 353 | break; 354 | case STATE_SHOWN: 355 | // If no action, hide automatically 356 | // Hung - comment out this to disable hiding 357 | if (autoHide) 358 | { 359 | setState(STATE_HIDING); 360 | } 361 | break; 362 | case STATE_HIDING: 363 | // Fade out effect 364 | mAlphaRate -= mAlphaRate * 0.2; 365 | if (mAlphaRate < 0.1) 366 | { 367 | mAlphaRate = 0; 368 | setState(STATE_HIDDEN); 369 | } 370 | 371 | mListView.invalidate(); 372 | fade(10); 373 | break; 374 | } 375 | } 376 | 377 | }; 378 | 379 | public float getLastTouchDownEventX() 380 | { 381 | return lastTouchDownEventX; 382 | } 383 | 384 | public void setLastTouchDownEventX(float lastTouchDownEventX) 385 | { 386 | this.lastTouchDownEventX = lastTouchDownEventX; 387 | } 388 | 389 | public float getLastTouchDownEventY() 390 | { 391 | return lastTouchDownEventY; 392 | } 393 | 394 | public void setLastTouchDownEventY(float lastTouchDownEventY) 395 | { 396 | this.lastTouchDownEventY = lastTouchDownEventY; 397 | } 398 | 399 | public boolean isAutoHide() 400 | { 401 | return autoHide; 402 | } 403 | 404 | public void setAutoHide(boolean autoHide) 405 | { 406 | this.autoHide = autoHide; 407 | } 408 | 409 | public boolean isShowIndexContainer() 410 | { 411 | return showIndexContainer; 412 | } 413 | 414 | public void setShowIndexContainer(boolean showIndexContainer) 415 | { 416 | this.showIndexContainer = showIndexContainer; 417 | } 418 | 419 | public int getIndexbarContainerBgColor() 420 | { 421 | return indexbarContainerBgColor; 422 | } 423 | 424 | public void setIndexbarContainerBgColor(int indexbarContainerBgColor) 425 | { 426 | this.indexbarContainerBgColor = indexbarContainerBgColor; 427 | } 428 | 429 | public int getIndexPaintColor() 430 | { 431 | return indexPaintColor; 432 | } 433 | 434 | public void setIndexPaintColor(int indexPaintColor) 435 | { 436 | this.indexPaintColor = indexPaintColor; 437 | } 438 | 439 | } 440 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/widget/pinyin/HanziToPinyin3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.liucanwen.citylist.widget.pinyin; 18 | 19 | import java.text.Collator; 20 | import java.util.ArrayList; 21 | import java.util.Locale; 22 | 23 | import android.text.TextUtils; 24 | import android.util.Log; 25 | 26 | /** 27 | * An object to convert Chinese character to its corresponding pinyin string. For characters with 28 | * multiple possible pinyin string, only one is selected according to collator. Polyphone is not 29 | * supported in this implementation. This class is implemented to achieve the best runtime 30 | * performance and minimum runtime resources with tolerable sacrifice of accuracy. This 31 | * implementation highly depends on zh_CN ICU collation data and must be always synchronized with 32 | * ICU. 33 | * 34 | * Currently this file is aligned to zh.txt in ICU 4.6 35 | * 来自android4.2源码 36 | */ 37 | public class HanziToPinyin3 { 38 | private static final String TAG = "HanziToPinyin"; 39 | 40 | // Turn on this flag when we want to check internal data structure. 41 | private static final boolean DEBUG = false; 42 | 43 | /** 44 | * Unihans array. 45 | * 46 | * Each unihans is the first one within same pinyin when collator is zh_CN. 47 | */ 48 | public static final char[] UNIHANS = { 49 | '\u963f', '\u54ce', '\u5b89', '\u80ae', '\u51f9', '\u516b', 50 | '\u6300', '\u6273', '\u90a6', '\u52f9', '\u9642', '\u5954', 51 | '\u4f3b', '\u5c44', '\u8fb9', '\u706c', '\u618b', '\u6c43', 52 | '\u51ab', '\u7676', '\u5cec', '\u5693', '\u5072', '\u53c2', 53 | '\u4ed3', '\u64a1', '\u518a', '\u5d7e', '\u66fd', '\u66fe', 54 | '\u5c64', '\u53c9', '\u8286', '\u8fbf', '\u4f25', '\u6284', 55 | '\u8f66', '\u62bb', '\u6c88', '\u6c89', '\u9637', '\u5403', 56 | '\u5145', '\u62bd', '\u51fa', '\u6b3b', '\u63e3', '\u5ddb', 57 | '\u5205', '\u5439', '\u65fe', '\u9034', '\u5472', '\u5306', 58 | '\u51d1', '\u7c97', '\u6c46', '\u5d14', '\u90a8', '\u6413', 59 | '\u5491', '\u5446', '\u4e39', '\u5f53', '\u5200', '\u561a', 60 | '\u6265', '\u706f', '\u6c10', '\u55f2', '\u7538', '\u5201', 61 | '\u7239', '\u4e01', '\u4e1f', '\u4e1c', '\u543a', '\u53be', 62 | '\u8011', '\u8968', '\u5428', '\u591a', '\u59b8', '\u8bf6', 63 | '\u5940', '\u97a5', '\u513f', '\u53d1', '\u5e06', '\u531a', 64 | '\u98de', '\u5206', '\u4e30', '\u8985', '\u4ecf', '\u7d11', 65 | '\u4f15', '\u65ee', '\u4f85', '\u7518', '\u5188', '\u768b', 66 | '\u6208', '\u7ed9', '\u6839', '\u522f', '\u5de5', '\u52fe', 67 | '\u4f30', '\u74dc', '\u4e56', '\u5173', '\u5149', '\u5f52', 68 | '\u4e28', '\u5459', '\u54c8', '\u548d', '\u4f44', '\u592f', 69 | '\u8320', '\u8bc3', '\u9ed2', '\u62eb', '\u4ea8', '\u5677', 70 | '\u53ff', '\u9f41', '\u4e6f', '\u82b1', '\u6000', '\u72bf', 71 | '\u5ddf', '\u7070', '\u660f', '\u5419', '\u4e0c', '\u52a0', 72 | '\u620b', '\u6c5f', '\u827d', '\u9636', '\u5dfe', '\u5755', 73 | '\u5182', '\u4e29', '\u51e5', '\u59e2', '\u5658', '\u519b', 74 | '\u5494', '\u5f00', '\u520a', '\u5ffc', '\u5c3b', '\u533c', 75 | '\u808e', '\u52a5', '\u7a7a', '\u62a0', '\u625d', '\u5938', 76 | '\u84af', '\u5bbd', '\u5321', '\u4e8f', '\u5764', '\u6269', 77 | '\u5783', '\u6765', '\u5170', '\u5577', '\u635e', '\u808b', 78 | '\u52d2', '\u5d1a', '\u5215', '\u4fe9', '\u5941', '\u826f', 79 | '\u64a9', '\u5217', '\u62ce', '\u5222', '\u6e9c', '\u56d6', 80 | '\u9f99', '\u779c', '\u565c', '\u5a08', '\u7567', '\u62a1', 81 | '\u7f57', '\u5463', '\u5988', '\u57cb', '\u5ada', '\u7264', 82 | '\u732b', '\u4e48', '\u5445', '\u95e8', '\u753f', '\u54aa', 83 | '\u5b80', '\u55b5', '\u4e5c', '\u6c11', '\u540d', '\u8c2c', 84 | '\u6478', '\u54de', '\u6bea', '\u55ef', '\u62cf', '\u8149', 85 | '\u56e1', '\u56d4', '\u5b6c', '\u7592', '\u5a1e', '\u6041', 86 | '\u80fd', '\u59ae', '\u62c8', '\u5b22', '\u9e1f', '\u634f', 87 | '\u56dc', '\u5b81', '\u599e', '\u519c', '\u7fba', '\u5974', 88 | '\u597b', '\u759f', '\u9ec1', '\u90cd', '\u5594', '\u8bb4', 89 | '\u5991', '\u62cd', '\u7705', '\u4e53', '\u629b', '\u5478', 90 | '\u55b7', '\u5309', '\u4e15', '\u56e8', '\u527d', '\u6c15', 91 | '\u59d8', '\u4e52', '\u948b', '\u5256', '\u4ec6', '\u4e03', 92 | '\u6390', '\u5343', '\u545b', '\u6084', '\u767f', '\u4eb2', 93 | '\u72c5', '\u828e', '\u4e18', '\u533a', '\u5cd1', '\u7f3a', 94 | '\u590b', '\u5465', '\u7a63', '\u5a06', '\u60f9', '\u4eba', 95 | '\u6254', '\u65e5', '\u8338', '\u53b9', '\u909a', '\u633c', 96 | '\u5827', '\u5a51', '\u77a4', '\u637c', '\u4ee8', '\u6be2', 97 | '\u4e09', '\u6852', '\u63bb', '\u95aa', '\u68ee', '\u50e7', 98 | '\u6740', '\u7b5b', '\u5c71', '\u4f24', '\u5f30', '\u5962', 99 | '\u7533', '\u8398', '\u6552', '\u5347', '\u5c38', '\u53ce', 100 | '\u4e66', '\u5237', '\u8870', '\u95e9', '\u53cc', '\u8c01', 101 | '\u542e', '\u8bf4', '\u53b6', '\u5fea', '\u635c', '\u82cf', 102 | '\u72fb', '\u590a', '\u5b59', '\u5506', '\u4ed6', '\u56fc', 103 | '\u574d', '\u6c64', '\u5932', '\u5fd1', '\u71a5', '\u5254', 104 | '\u5929', '\u65eb', '\u5e16', '\u5385', '\u56f2', '\u5077', 105 | '\u51f8', '\u6e4d', '\u63a8', '\u541e', '\u4e47', '\u7a75', 106 | '\u6b6a', '\u5f2f', '\u5c23', '\u5371', '\u6637', '\u7fc1', 107 | '\u631d', '\u4e4c', '\u5915', '\u8672', '\u4eda', '\u4e61', 108 | '\u7071', '\u4e9b', '\u5fc3', '\u661f', '\u51f6', '\u4f11', 109 | '\u5401', '\u5405', '\u524a', '\u5743', '\u4e2b', '\u6079', 110 | '\u592e', '\u5e7a', '\u503b', '\u4e00', '\u56d9', '\u5e94', 111 | '\u54df', '\u4f63', '\u4f18', '\u625c', '\u56e6', '\u66f0', 112 | '\u6655', '\u7b60', '\u7b7c', '\u5e00', '\u707d', '\u5142', 113 | '\u5328', '\u50ae', '\u5219', '\u8d3c', '\u600e', '\u5897', 114 | '\u624e', '\u635a', '\u6cbe', '\u5f20', '\u957f', '\u9577', 115 | '\u4f4b', '\u8707', '\u8d1e', '\u4e89', '\u4e4b', '\u5cd9', 116 | '\u5ea2', '\u4e2d', '\u5dde', '\u6731', '\u6293', '\u62fd', 117 | '\u4e13', '\u5986', '\u96b9', '\u5b92', '\u5353', '\u4e72', 118 | '\u5b97', '\u90b9', '\u79df', '\u94bb', '\u539c', '\u5c0a', 119 | '\u6628', '\u5159', '\u9fc3', '\u9fc4', }; 120 | 121 | /** 122 | * Pinyin array. 123 | * 124 | * Each pinyin is corresponding to unihans of same 125 | * offset in the unihans array. 126 | */ 127 | public static final byte[][] PINYINS = { 128 | { 65, 0, 0, 0, 0, 0}, { 65, 73, 0, 0, 0, 0}, 129 | { 65, 78, 0, 0, 0, 0}, { 65, 78, 71, 0, 0, 0}, 130 | { 65, 79, 0, 0, 0, 0}, { 66, 65, 0, 0, 0, 0}, 131 | { 66, 65, 73, 0, 0, 0}, { 66, 65, 78, 0, 0, 0}, 132 | { 66, 65, 78, 71, 0, 0}, { 66, 65, 79, 0, 0, 0}, 133 | { 66, 69, 73, 0, 0, 0}, { 66, 69, 78, 0, 0, 0}, 134 | { 66, 69, 78, 71, 0, 0}, { 66, 73, 0, 0, 0, 0}, 135 | { 66, 73, 65, 78, 0, 0}, { 66, 73, 65, 79, 0, 0}, 136 | { 66, 73, 69, 0, 0, 0}, { 66, 73, 78, 0, 0, 0}, 137 | { 66, 73, 78, 71, 0, 0}, { 66, 79, 0, 0, 0, 0}, 138 | { 66, 85, 0, 0, 0, 0}, { 67, 65, 0, 0, 0, 0}, 139 | { 67, 65, 73, 0, 0, 0}, { 67, 65, 78, 0, 0, 0}, 140 | { 67, 65, 78, 71, 0, 0}, { 67, 65, 79, 0, 0, 0}, 141 | { 67, 69, 0, 0, 0, 0}, { 67, 69, 78, 0, 0, 0}, 142 | { 67, 69, 78, 71, 0, 0}, { 90, 69, 78, 71, 0, 0}, 143 | { 67, 69, 78, 71, 0, 0}, { 67, 72, 65, 0, 0, 0}, 144 | { 67, 72, 65, 73, 0, 0}, { 67, 72, 65, 78, 0, 0}, 145 | { 67, 72, 65, 78, 71, 0}, { 67, 72, 65, 79, 0, 0}, 146 | { 67, 72, 69, 0, 0, 0}, { 67, 72, 69, 78, 0, 0}, 147 | { 83, 72, 69, 78, 0, 0}, { 67, 72, 69, 78, 0, 0}, 148 | { 67, 72, 69, 78, 71, 0}, { 67, 72, 73, 0, 0, 0}, 149 | { 67, 72, 79, 78, 71, 0}, { 67, 72, 79, 85, 0, 0}, 150 | { 67, 72, 85, 0, 0, 0}, { 67, 72, 85, 65, 0, 0}, 151 | { 67, 72, 85, 65, 73, 0}, { 67, 72, 85, 65, 78, 0}, 152 | { 67, 72, 85, 65, 78, 71}, { 67, 72, 85, 73, 0, 0}, 153 | { 67, 72, 85, 78, 0, 0}, { 67, 72, 85, 79, 0, 0}, 154 | { 67, 73, 0, 0, 0, 0}, { 67, 79, 78, 71, 0, 0}, 155 | { 67, 79, 85, 0, 0, 0}, { 67, 85, 0, 0, 0, 0}, 156 | { 67, 85, 65, 78, 0, 0}, { 67, 85, 73, 0, 0, 0}, 157 | { 67, 85, 78, 0, 0, 0}, { 67, 85, 79, 0, 0, 0}, 158 | { 68, 65, 0, 0, 0, 0}, { 68, 65, 73, 0, 0, 0}, 159 | { 68, 65, 78, 0, 0, 0}, { 68, 65, 78, 71, 0, 0}, 160 | { 68, 65, 79, 0, 0, 0}, { 68, 69, 0, 0, 0, 0}, 161 | { 68, 69, 78, 0, 0, 0}, { 68, 69, 78, 71, 0, 0}, 162 | { 68, 73, 0, 0, 0, 0}, { 68, 73, 65, 0, 0, 0}, 163 | { 68, 73, 65, 78, 0, 0}, { 68, 73, 65, 79, 0, 0}, 164 | { 68, 73, 69, 0, 0, 0}, { 68, 73, 78, 71, 0, 0}, 165 | { 68, 73, 85, 0, 0, 0}, { 68, 79, 78, 71, 0, 0}, 166 | { 68, 79, 85, 0, 0, 0}, { 68, 85, 0, 0, 0, 0}, 167 | { 68, 85, 65, 78, 0, 0}, { 68, 85, 73, 0, 0, 0}, 168 | { 68, 85, 78, 0, 0, 0}, { 68, 85, 79, 0, 0, 0}, 169 | { 69, 0, 0, 0, 0, 0}, { 69, 73, 0, 0, 0, 0}, 170 | { 69, 78, 0, 0, 0, 0}, { 69, 78, 71, 0, 0, 0}, 171 | { 69, 82, 0, 0, 0, 0}, { 70, 65, 0, 0, 0, 0}, 172 | { 70, 65, 78, 0, 0, 0}, { 70, 65, 78, 71, 0, 0}, 173 | { 70, 69, 73, 0, 0, 0}, { 70, 69, 78, 0, 0, 0}, 174 | { 70, 69, 78, 71, 0, 0}, { 70, 73, 65, 79, 0, 0}, 175 | { 70, 79, 0, 0, 0, 0}, { 70, 79, 85, 0, 0, 0}, 176 | { 70, 85, 0, 0, 0, 0}, { 71, 65, 0, 0, 0, 0}, 177 | { 71, 65, 73, 0, 0, 0}, { 71, 65, 78, 0, 0, 0}, 178 | { 71, 65, 78, 71, 0, 0}, { 71, 65, 79, 0, 0, 0}, 179 | { 71, 69, 0, 0, 0, 0}, { 71, 69, 73, 0, 0, 0}, 180 | { 71, 69, 78, 0, 0, 0}, { 71, 69, 78, 71, 0, 0}, 181 | { 71, 79, 78, 71, 0, 0}, { 71, 79, 85, 0, 0, 0}, 182 | { 71, 85, 0, 0, 0, 0}, { 71, 85, 65, 0, 0, 0}, 183 | { 71, 85, 65, 73, 0, 0}, { 71, 85, 65, 78, 0, 0}, 184 | { 71, 85, 65, 78, 71, 0}, { 71, 85, 73, 0, 0, 0}, 185 | { 71, 85, 78, 0, 0, 0}, { 71, 85, 79, 0, 0, 0}, 186 | { 72, 65, 0, 0, 0, 0}, { 72, 65, 73, 0, 0, 0}, 187 | { 72, 65, 78, 0, 0, 0}, { 72, 65, 78, 71, 0, 0}, 188 | { 72, 65, 79, 0, 0, 0}, { 72, 69, 0, 0, 0, 0}, 189 | { 72, 69, 73, 0, 0, 0}, { 72, 69, 78, 0, 0, 0}, 190 | { 72, 69, 78, 71, 0, 0}, { 72, 77, 0, 0, 0, 0}, 191 | { 72, 79, 78, 71, 0, 0}, { 72, 79, 85, 0, 0, 0}, 192 | { 72, 85, 0, 0, 0, 0}, { 72, 85, 65, 0, 0, 0}, 193 | { 72, 85, 65, 73, 0, 0}, { 72, 85, 65, 78, 0, 0}, 194 | { 72, 85, 65, 78, 71, 0}, { 72, 85, 73, 0, 0, 0}, 195 | { 72, 85, 78, 0, 0, 0}, { 72, 85, 79, 0, 0, 0}, 196 | { 74, 73, 0, 0, 0, 0}, { 74, 73, 65, 0, 0, 0}, 197 | { 74, 73, 65, 78, 0, 0}, { 74, 73, 65, 78, 71, 0}, 198 | { 74, 73, 65, 79, 0, 0}, { 74, 73, 69, 0, 0, 0}, 199 | { 74, 73, 78, 0, 0, 0}, { 74, 73, 78, 71, 0, 0}, 200 | { 74, 73, 79, 78, 71, 0}, { 74, 73, 85, 0, 0, 0}, 201 | { 74, 85, 0, 0, 0, 0}, { 74, 85, 65, 78, 0, 0}, 202 | { 74, 85, 69, 0, 0, 0}, { 74, 85, 78, 0, 0, 0}, 203 | { 75, 65, 0, 0, 0, 0}, { 75, 65, 73, 0, 0, 0}, 204 | { 75, 65, 78, 0, 0, 0}, { 75, 65, 78, 71, 0, 0}, 205 | { 75, 65, 79, 0, 0, 0}, { 75, 69, 0, 0, 0, 0}, 206 | { 75, 69, 78, 0, 0, 0}, { 75, 69, 78, 71, 0, 0}, 207 | { 75, 79, 78, 71, 0, 0}, { 75, 79, 85, 0, 0, 0}, 208 | { 75, 85, 0, 0, 0, 0}, { 75, 85, 65, 0, 0, 0}, 209 | { 75, 85, 65, 73, 0, 0}, { 75, 85, 65, 78, 0, 0}, 210 | { 75, 85, 65, 78, 71, 0}, { 75, 85, 73, 0, 0, 0}, 211 | { 75, 85, 78, 0, 0, 0}, { 75, 85, 79, 0, 0, 0}, 212 | { 76, 65, 0, 0, 0, 0}, { 76, 65, 73, 0, 0, 0}, 213 | { 76, 65, 78, 0, 0, 0}, { 76, 65, 78, 71, 0, 0}, 214 | { 76, 65, 79, 0, 0, 0}, { 76, 69, 0, 0, 0, 0}, 215 | { 76, 69, 73, 0, 0, 0}, { 76, 69, 78, 71, 0, 0}, 216 | { 76, 73, 0, 0, 0, 0}, { 76, 73, 65, 0, 0, 0}, 217 | { 76, 73, 65, 78, 0, 0}, { 76, 73, 65, 78, 71, 0}, 218 | { 76, 73, 65, 79, 0, 0}, { 76, 73, 69, 0, 0, 0}, 219 | { 76, 73, 78, 0, 0, 0}, { 76, 73, 78, 71, 0, 0}, 220 | { 76, 73, 85, 0, 0, 0}, { 76, 79, 0, 0, 0, 0}, 221 | { 76, 79, 78, 71, 0, 0}, { 76, 79, 85, 0, 0, 0}, 222 | { 76, 85, 0, 0, 0, 0}, { 76, 85, 65, 78, 0, 0}, 223 | { 76, 85, 69, 0, 0, 0}, { 76, 85, 78, 0, 0, 0}, 224 | { 76, 85, 79, 0, 0, 0}, { 77, 0, 0, 0, 0, 0}, 225 | { 77, 65, 0, 0, 0, 0}, { 77, 65, 73, 0, 0, 0}, 226 | { 77, 65, 78, 0, 0, 0}, { 77, 65, 78, 71, 0, 0}, 227 | { 77, 65, 79, 0, 0, 0}, { 77, 69, 0, 0, 0, 0}, 228 | { 77, 69, 73, 0, 0, 0}, { 77, 69, 78, 0, 0, 0}, 229 | { 77, 69, 78, 71, 0, 0}, { 77, 73, 0, 0, 0, 0}, 230 | { 77, 73, 65, 78, 0, 0}, { 77, 73, 65, 79, 0, 0}, 231 | { 77, 73, 69, 0, 0, 0}, { 77, 73, 78, 0, 0, 0}, 232 | { 77, 73, 78, 71, 0, 0}, { 77, 73, 85, 0, 0, 0}, 233 | { 77, 79, 0, 0, 0, 0}, { 77, 79, 85, 0, 0, 0}, 234 | { 77, 85, 0, 0, 0, 0}, { 78, 0, 0, 0, 0, 0}, 235 | { 78, 65, 0, 0, 0, 0}, { 78, 65, 73, 0, 0, 0}, 236 | { 78, 65, 78, 0, 0, 0}, { 78, 65, 78, 71, 0, 0}, 237 | { 78, 65, 79, 0, 0, 0}, { 78, 69, 0, 0, 0, 0}, 238 | { 78, 69, 73, 0, 0, 0}, { 78, 69, 78, 0, 0, 0}, 239 | { 78, 69, 78, 71, 0, 0}, { 78, 73, 0, 0, 0, 0}, 240 | { 78, 73, 65, 78, 0, 0}, { 78, 73, 65, 78, 71, 0}, 241 | { 78, 73, 65, 79, 0, 0}, { 78, 73, 69, 0, 0, 0}, 242 | { 78, 73, 78, 0, 0, 0}, { 78, 73, 78, 71, 0, 0}, 243 | { 78, 73, 85, 0, 0, 0}, { 78, 79, 78, 71, 0, 0}, 244 | { 78, 79, 85, 0, 0, 0}, { 78, 85, 0, 0, 0, 0}, 245 | { 78, 85, 65, 78, 0, 0}, { 78, 85, 69, 0, 0, 0}, 246 | { 78, 85, 78, 0, 0, 0}, { 78, 85, 79, 0, 0, 0}, 247 | { 79, 0, 0, 0, 0, 0}, { 79, 85, 0, 0, 0, 0}, 248 | { 80, 65, 0, 0, 0, 0}, { 80, 65, 73, 0, 0, 0}, 249 | { 80, 65, 78, 0, 0, 0}, { 80, 65, 78, 71, 0, 0}, 250 | { 80, 65, 79, 0, 0, 0}, { 80, 69, 73, 0, 0, 0}, 251 | { 80, 69, 78, 0, 0, 0}, { 80, 69, 78, 71, 0, 0}, 252 | { 80, 73, 0, 0, 0, 0}, { 80, 73, 65, 78, 0, 0}, 253 | { 80, 73, 65, 79, 0, 0}, { 80, 73, 69, 0, 0, 0}, 254 | { 80, 73, 78, 0, 0, 0}, { 80, 73, 78, 71, 0, 0}, 255 | { 80, 79, 0, 0, 0, 0}, { 80, 79, 85, 0, 0, 0}, 256 | { 80, 85, 0, 0, 0, 0}, { 81, 73, 0, 0, 0, 0}, 257 | { 81, 73, 65, 0, 0, 0}, { 81, 73, 65, 78, 0, 0}, 258 | { 81, 73, 65, 78, 71, 0}, { 81, 73, 65, 79, 0, 0}, 259 | { 81, 73, 69, 0, 0, 0}, { 81, 73, 78, 0, 0, 0}, 260 | { 81, 73, 78, 71, 0, 0}, { 81, 73, 79, 78, 71, 0}, 261 | { 81, 73, 85, 0, 0, 0}, { 81, 85, 0, 0, 0, 0}, 262 | { 81, 85, 65, 78, 0, 0}, { 81, 85, 69, 0, 0, 0}, 263 | { 81, 85, 78, 0, 0, 0}, { 82, 65, 78, 0, 0, 0}, 264 | { 82, 65, 78, 71, 0, 0}, { 82, 65, 79, 0, 0, 0}, 265 | { 82, 69, 0, 0, 0, 0}, { 82, 69, 78, 0, 0, 0}, 266 | { 82, 69, 78, 71, 0, 0}, { 82, 73, 0, 0, 0, 0}, 267 | { 82, 79, 78, 71, 0, 0}, { 82, 79, 85, 0, 0, 0}, 268 | { 82, 85, 0, 0, 0, 0}, { 82, 85, 65, 0, 0, 0}, 269 | { 82, 85, 65, 78, 0, 0}, { 82, 85, 73, 0, 0, 0}, 270 | { 82, 85, 78, 0, 0, 0}, { 82, 85, 79, 0, 0, 0}, 271 | { 83, 65, 0, 0, 0, 0}, { 83, 65, 73, 0, 0, 0}, 272 | { 83, 65, 78, 0, 0, 0}, { 83, 65, 78, 71, 0, 0}, 273 | { 83, 65, 79, 0, 0, 0}, { 83, 69, 0, 0, 0, 0}, 274 | { 83, 69, 78, 0, 0, 0}, { 83, 69, 78, 71, 0, 0}, 275 | { 83, 72, 65, 0, 0, 0}, { 83, 72, 65, 73, 0, 0}, 276 | { 83, 72, 65, 78, 0, 0}, { 83, 72, 65, 78, 71, 0}, 277 | { 83, 72, 65, 79, 0, 0}, { 83, 72, 69, 0, 0, 0}, 278 | { 83, 72, 69, 78, 0, 0}, { 88, 73, 78, 0, 0, 0}, 279 | { 83, 72, 69, 78, 0, 0}, { 83, 72, 69, 78, 71, 0}, 280 | { 83, 72, 73, 0, 0, 0}, { 83, 72, 79, 85, 0, 0}, 281 | { 83, 72, 85, 0, 0, 0}, { 83, 72, 85, 65, 0, 0}, 282 | { 83, 72, 85, 65, 73, 0}, { 83, 72, 85, 65, 78, 0}, 283 | { 83, 72, 85, 65, 78, 71}, { 83, 72, 85, 73, 0, 0}, 284 | { 83, 72, 85, 78, 0, 0}, { 83, 72, 85, 79, 0, 0}, 285 | { 83, 73, 0, 0, 0, 0}, { 83, 79, 78, 71, 0, 0}, 286 | { 83, 79, 85, 0, 0, 0}, { 83, 85, 0, 0, 0, 0}, 287 | { 83, 85, 65, 78, 0, 0}, { 83, 85, 73, 0, 0, 0}, 288 | { 83, 85, 78, 0, 0, 0}, { 83, 85, 79, 0, 0, 0}, 289 | { 84, 65, 0, 0, 0, 0}, { 84, 65, 73, 0, 0, 0}, 290 | { 84, 65, 78, 0, 0, 0}, { 84, 65, 78, 71, 0, 0}, 291 | { 84, 65, 79, 0, 0, 0}, { 84, 69, 0, 0, 0, 0}, 292 | { 84, 69, 78, 71, 0, 0}, { 84, 73, 0, 0, 0, 0}, 293 | { 84, 73, 65, 78, 0, 0}, { 84, 73, 65, 79, 0, 0}, 294 | { 84, 73, 69, 0, 0, 0}, { 84, 73, 78, 71, 0, 0}, 295 | { 84, 79, 78, 71, 0, 0}, { 84, 79, 85, 0, 0, 0}, 296 | { 84, 85, 0, 0, 0, 0}, { 84, 85, 65, 78, 0, 0}, 297 | { 84, 85, 73, 0, 0, 0}, { 84, 85, 78, 0, 0, 0}, 298 | { 84, 85, 79, 0, 0, 0}, { 87, 65, 0, 0, 0, 0}, 299 | { 87, 65, 73, 0, 0, 0}, { 87, 65, 78, 0, 0, 0}, 300 | { 87, 65, 78, 71, 0, 0}, { 87, 69, 73, 0, 0, 0}, 301 | { 87, 69, 78, 0, 0, 0}, { 87, 69, 78, 71, 0, 0}, 302 | { 87, 79, 0, 0, 0, 0}, { 87, 85, 0, 0, 0, 0}, 303 | { 88, 73, 0, 0, 0, 0}, { 88, 73, 65, 0, 0, 0}, 304 | { 88, 73, 65, 78, 0, 0}, { 88, 73, 65, 78, 71, 0}, 305 | { 88, 73, 65, 79, 0, 0}, { 88, 73, 69, 0, 0, 0}, 306 | { 88, 73, 78, 0, 0, 0}, { 88, 73, 78, 71, 0, 0}, 307 | { 88, 73, 79, 78, 71, 0}, { 88, 73, 85, 0, 0, 0}, 308 | { 88, 85, 0, 0, 0, 0}, { 88, 85, 65, 78, 0, 0}, 309 | { 88, 85, 69, 0, 0, 0}, { 88, 85, 78, 0, 0, 0}, 310 | { 89, 65, 0, 0, 0, 0}, { 89, 65, 78, 0, 0, 0}, 311 | { 89, 65, 78, 71, 0, 0}, { 89, 65, 79, 0, 0, 0}, 312 | { 89, 69, 0, 0, 0, 0}, { 89, 73, 0, 0, 0, 0}, 313 | { 89, 73, 78, 0, 0, 0}, { 89, 73, 78, 71, 0, 0}, 314 | { 89, 79, 0, 0, 0, 0}, { 89, 79, 78, 71, 0, 0}, 315 | { 89, 79, 85, 0, 0, 0}, { 89, 85, 0, 0, 0, 0}, 316 | { 89, 85, 65, 78, 0, 0}, { 89, 85, 69, 0, 0, 0}, 317 | { 89, 85, 78, 0, 0, 0}, { 74, 85, 78, 0, 0, 0}, 318 | { 89, 85, 78, 0, 0, 0}, { 90, 65, 0, 0, 0, 0}, 319 | { 90, 65, 73, 0, 0, 0}, { 90, 65, 78, 0, 0, 0}, 320 | { 90, 65, 78, 71, 0, 0}, { 90, 65, 79, 0, 0, 0}, 321 | { 90, 69, 0, 0, 0, 0}, { 90, 69, 73, 0, 0, 0}, 322 | { 90, 69, 78, 0, 0, 0}, { 90, 69, 78, 71, 0, 0}, 323 | { 90, 72, 65, 0, 0, 0}, { 90, 72, 65, 73, 0, 0}, 324 | { 90, 72, 65, 78, 0, 0}, { 90, 72, 65, 78, 71, 0}, 325 | { 67, 72, 65, 78, 71, 0}, { 90, 72, 65, 78, 71, 0}, 326 | { 90, 72, 65, 79, 0, 0}, { 90, 72, 69, 0, 0, 0}, 327 | { 90, 72, 69, 78, 0, 0}, { 90, 72, 69, 78, 71, 0}, 328 | { 90, 72, 73, 0, 0, 0}, { 83, 72, 73, 0, 0, 0}, 329 | { 90, 72, 73, 0, 0, 0}, { 90, 72, 79, 78, 71, 0}, 330 | { 90, 72, 79, 85, 0, 0}, { 90, 72, 85, 0, 0, 0}, 331 | { 90, 72, 85, 65, 0, 0}, { 90, 72, 85, 65, 73, 0}, 332 | { 90, 72, 85, 65, 78, 0}, { 90, 72, 85, 65, 78, 71}, 333 | { 90, 72, 85, 73, 0, 0}, { 90, 72, 85, 78, 0, 0}, 334 | { 90, 72, 85, 79, 0, 0}, { 90, 73, 0, 0, 0, 0}, 335 | { 90, 79, 78, 71, 0, 0}, { 90, 79, 85, 0, 0, 0}, 336 | { 90, 85, 0, 0, 0, 0}, { 90, 85, 65, 78, 0, 0}, 337 | { 90, 85, 73, 0, 0, 0}, { 90, 85, 78, 0, 0, 0}, 338 | { 90, 85, 79, 0, 0, 0}, { 0, 0, 0, 0, 0, 0}, 339 | { 83, 72, 65, 78, 0, 0}, { 0, 0, 0, 0, 0, 0}, }; 340 | 341 | /** First and last Chinese character with known Pinyin according to zh collation */ 342 | private static final String FIRST_PINYIN_UNIHAN = "\u963F"; 343 | private static final String LAST_PINYIN_UNIHAN = "\u9FFF"; 344 | 345 | private static final Collator COLLATOR = Collator.getInstance(Locale.CHINA); 346 | 347 | private static HanziToPinyin3 sInstance; 348 | private final boolean mHasChinaCollator; 349 | 350 | public static class Token { 351 | /** 352 | * Separator between target string for each source char 353 | */ 354 | public static final String SEPARATOR = " "; 355 | 356 | public static final int LATIN = 1; 357 | public static final int PINYIN = 2; 358 | public static final int UNKNOWN = 3; 359 | 360 | public Token() { 361 | } 362 | 363 | public Token(int type, String source, String target) { 364 | this.type = type; 365 | this.source = source; 366 | this.target = target; 367 | } 368 | 369 | /** 370 | * Type of this token, ASCII, PINYIN or UNKNOWN. 371 | */ 372 | public int type; 373 | /** 374 | * Original string before translation. 375 | */ 376 | public String source; 377 | /** 378 | * Translated string of source. For Han, target is corresponding Pinyin. Otherwise target is 379 | * original string in source. 380 | */ 381 | public String target; 382 | } 383 | 384 | protected HanziToPinyin3(boolean hasChinaCollator) { 385 | mHasChinaCollator = hasChinaCollator; 386 | } 387 | 388 | public static HanziToPinyin3 getInstance() { 389 | synchronized (HanziToPinyin3.class) { 390 | if (sInstance != null) { 391 | return sInstance; 392 | } 393 | // Check if zh_CN collation data is available 394 | final Locale locale[] = Collator.getAvailableLocales(); 395 | for (int i = 0; i < locale.length; i++) { 396 | if (locale[i].equals(Locale.CHINA)) { 397 | // Do self validation just once. 398 | if (DEBUG) { 399 | Log.d(TAG, "Self validation. Result: " + doSelfValidation()); 400 | } 401 | sInstance = new HanziToPinyin3(true); 402 | return sInstance; 403 | } 404 | } 405 | Log.w(TAG, "There is no Chinese collator, HanziToPinyin is disabled"); 406 | sInstance = new HanziToPinyin3(false); 407 | return sInstance; 408 | } 409 | } 410 | 411 | /** 412 | * Validate if our internal table has some wrong value. 413 | * 414 | * @return true when the table looks correct. 415 | */ 416 | private static boolean doSelfValidation() { 417 | char lastChar = UNIHANS[0]; 418 | String lastString = Character.toString(lastChar); 419 | for (char c : UNIHANS) { 420 | if (lastChar == c) { 421 | continue; 422 | } 423 | final String curString = Character.toString(c); 424 | int cmp = COLLATOR.compare(lastString, curString); 425 | if (cmp >= 0) { 426 | Log.e(TAG, "Internal error in Unihan table. " + "The last string \"" + lastString 427 | + "\" is greater than current string \"" + curString + "\"."); 428 | return false; 429 | } 430 | lastString = curString; 431 | } 432 | return true; 433 | } 434 | 435 | private Token getToken(char character) { 436 | Token token = new Token(); 437 | final String letter = Character.toString(character); 438 | token.source = letter; 439 | int offset = -1; 440 | int cmp; 441 | if (character < 256) { 442 | token.type = Token.LATIN; 443 | token.target = letter; 444 | return token; 445 | } else { 446 | cmp = COLLATOR.compare(letter, FIRST_PINYIN_UNIHAN); 447 | if (cmp < 0) { 448 | token.type = Token.UNKNOWN; 449 | token.target = letter; 450 | return token; 451 | } else if (cmp == 0) { 452 | token.type = Token.PINYIN; 453 | offset = 0; 454 | } else { 455 | cmp = COLLATOR.compare(letter, LAST_PINYIN_UNIHAN); 456 | if (cmp > 0) { 457 | token.type = Token.UNKNOWN; 458 | token.target = letter; 459 | return token; 460 | } else if (cmp == 0) { 461 | token.type = Token.PINYIN; 462 | offset = UNIHANS.length - 1; 463 | } 464 | } 465 | } 466 | 467 | token.type = Token.PINYIN; 468 | if (offset < 0) { 469 | int begin = 0; 470 | int end = UNIHANS.length - 1; 471 | while (begin <= end) { 472 | offset = (begin + end) / 2; 473 | final String unihan = Character.toString(UNIHANS[offset]); 474 | cmp = COLLATOR.compare(letter, unihan); 475 | if (cmp == 0) { 476 | break; 477 | } else if (cmp > 0) { 478 | begin = offset + 1; 479 | } else { 480 | end = offset - 1; 481 | } 482 | } 483 | } 484 | if (cmp < 0) { 485 | offset--; 486 | } 487 | StringBuilder pinyin = new StringBuilder(); 488 | for (int j = 0; j < PINYINS[offset].length && PINYINS[offset][j] != 0; j++) { 489 | pinyin.append((char) PINYINS[offset][j]); 490 | } 491 | token.target = pinyin.toString(); 492 | if (TextUtils.isEmpty(token.target)) { 493 | token.type = Token.UNKNOWN; 494 | token.target = token.source; 495 | } 496 | return token; 497 | } 498 | 499 | /** 500 | * Convert the input to a array of tokens. The sequence of ASCII or Unknown characters without 501 | * space will be put into a Token, One Hanzi character which has pinyin will be treated as a 502 | * Token. If these is no China collator, the empty token array is returned. 503 | */ 504 | public ArrayList get(final String input) { 505 | ArrayList tokens = new ArrayList(); 506 | if (!mHasChinaCollator || TextUtils.isEmpty(input)) { 507 | // return empty tokens. 508 | return tokens; 509 | } 510 | final int inputLength = input.length(); 511 | final StringBuilder sb = new StringBuilder(); 512 | int tokenType = Token.LATIN; 513 | // Go through the input, create a new token when 514 | // a. Token type changed 515 | // b. Get the Pinyin of current charater. 516 | // c. current character is space. 517 | for (int i = 0; i < inputLength; i++) { 518 | final char character = input.charAt(i); 519 | if (character == ' ') { 520 | if (sb.length() > 0) { 521 | addToken(sb, tokens, tokenType); 522 | } 523 | } else if (character < 256) { 524 | if (tokenType != Token.LATIN && sb.length() > 0) { 525 | addToken(sb, tokens, tokenType); 526 | } 527 | tokenType = Token.LATIN; 528 | sb.append(character); 529 | } else { 530 | Token t = getToken(character); 531 | if (t.type == Token.PINYIN) { 532 | if (sb.length() > 0) { 533 | addToken(sb, tokens, tokenType); 534 | } 535 | tokens.add(t); 536 | tokenType = Token.PINYIN; 537 | } else { 538 | if (tokenType != t.type && sb.length() > 0) { 539 | addToken(sb, tokens, tokenType); 540 | } 541 | tokenType = t.type; 542 | sb.append(character); 543 | } 544 | } 545 | } 546 | if (sb.length() > 0) { 547 | addToken(sb, tokens, tokenType); 548 | } 549 | return tokens; 550 | } 551 | 552 | private void addToken( 553 | final StringBuilder sb, final ArrayList tokens, final int tokenType) { 554 | String str = sb.toString(); 555 | tokens.add(new Token(tokenType, str, str)); 556 | sb.setLength(0); 557 | } 558 | } 559 | -------------------------------------------------------------------------------- /CityList/src/com/liucanwen/citylist/widget/pinyin/PinYin.java: -------------------------------------------------------------------------------- 1 | package com.liucanwen.citylist.widget.pinyin; 2 | 3 | import java.util.ArrayList; 4 | 5 | import com.liucanwen.citylist.widget.pinyin.HanziToPinyin3.Token; 6 | 7 | public class PinYin 8 | { 9 | // 汉字返回拼音,字母原样返回,都转换为小写 10 | public static String getPinYin(String input) 11 | { 12 | ArrayList tokens = HanziToPinyin3.getInstance().get(input); 13 | StringBuilder sb = new StringBuilder(); 14 | if (tokens != null && tokens.size() > 0) 15 | { 16 | for (Token token : tokens) 17 | { 18 | if (Token.PINYIN == token.type) 19 | { 20 | sb.append(token.target); 21 | } else 22 | { 23 | sb.append(token.source); 24 | } 25 | } 26 | } 27 | return sb.toString().toLowerCase(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 中国城市列表,类似手机通讯录显示方式,可以通过触摸屏幕右边城市拼音首字母快速定位,还可通过中文、拼音快速查找。 2 | 3 | * * * 4 | 5 | 显示效果: 6 | 7 | ![Screenshot](https://github.com/kk-java/ChineseCityList/raw/master/all_screenshot.jpg) 8 | 9 | 联系邮箱: 10 | liucanwen517@gmail.com 11 | -------------------------------------------------------------------------------- /all_screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/all_screenshot.jpg -------------------------------------------------------------------------------- /screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/screenshot1.png -------------------------------------------------------------------------------- /screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/screenshot2.png -------------------------------------------------------------------------------- /screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kk-java/ChineseCityList/ee00f5bd42e38b1816776a0dfde61673f353f672/screenshot3.png --------------------------------------------------------------------------------