├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── city.json │ └── city2.json │ ├── java │ └── cn │ │ └── qqtheme │ │ └── androidpicker │ │ ├── AddressInitTask.java │ │ ├── AssetsUtils.java │ │ ├── CustomHeaderAndFooterPicker.java │ │ └── MainActivity.java │ └── res │ ├── anim │ ├── popup_in.xml │ └── popup_out.xml │ ├── layout │ ├── activity_main.xml │ ├── picker_footer.xml │ └── picker_header.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ └── values │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── ColorPicker │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── cn │ │ │ └── qqtheme │ │ │ └── framework │ │ │ ├── picker │ │ │ └── ColorPicker.java │ │ │ └── widget │ │ │ └── ColorPanelView.java │ │ └── res │ │ └── drawable-hdpi │ │ ├── color_picker_cursor_bottom.png │ │ └── color_picker_cursor_top.png ├── Common │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── cn │ │ │ └── qqtheme │ │ │ └── framework │ │ │ ├── AppConfig.java │ │ │ ├── popup │ │ │ ├── BottomPopup.java │ │ │ ├── ConfirmPopup.java │ │ │ └── Popup.java │ │ │ └── util │ │ │ ├── CompatUtils.java │ │ │ ├── ConvertUtils.java │ │ │ ├── DateUtils.java │ │ │ ├── LogUtils.java │ │ │ └── ScreenUtils.java │ │ └── res │ │ └── values │ │ └── styles.xml ├── FilePicker │ ├── .gitignore │ ├── build.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── cn │ │ │ └── qqtheme │ │ │ └── framework │ │ │ ├── adapter │ │ │ └── FileAdapter.java │ │ │ ├── entity │ │ │ └── FileItem.java │ │ │ ├── picker │ │ │ └── FilePicker.java │ │ │ ├── util │ │ │ ├── FileUtils.java │ │ │ └── StorageUtils.java │ │ │ └── widget │ │ │ └── MarqueeTextView.java │ │ └── res │ │ ├── drawable-hdpi │ │ ├── file_picker_file.png │ │ ├── file_picker_folder.png │ │ ├── file_picker_home.png │ │ └── file_picker_updir.png │ │ └── layout │ │ └── file_item.xml └── WheelPicker │ ├── .gitignore │ ├── build.gradle │ └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── cn │ └── qqtheme │ └── framework │ ├── picker │ ├── AddressPicker.java │ ├── ChineseZodiacPicker.java │ ├── ConstellationPicker.java │ ├── DatePicker.java │ ├── DateTimePicker.java │ ├── LinkagePicker.java │ ├── NumberPicker.java │ ├── OptionPicker.java │ ├── SexPicker.java │ ├── TimePicker.java │ └── WheelPicker.java │ └── widget │ └── WheelView.java ├── publish.cmd ├── screenshots ├── address.gif ├── address.png ├── chinesezodiac.gif ├── color.gif ├── constellation.gif ├── custom.gif ├── date.gif ├── dir.gif ├── file.gif ├── number.gif ├── option.gif └── time.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | /*.iml 2 | /gradlew 3 | /*/*.iml 4 | /gradle 5 | /.idea 6 | /gradlew.bat 7 | bin/ 8 | gen/ 9 | .gradle/ 10 | build/ 11 | /*/build/ 12 | local.properties 13 | proguard/ 14 | *.log 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | [![API](https://img.shields.io/badge/API-9%2B-green.svg)](https://github.com/gzu-liyujiang/AndroidPicker) 3 | [![Download](https://api.bintray.com/packages/gzu-liyujiang/maven/WheelPicker/images/download.svg)](http://jcenter.bintray.com/cn/qqtheme/framework/) 4 | 安卓选择器类库,包括日期选择器、时间选择器、单项选择器、城市选择器、颜色选择器、文件选择器、目录选择器、数字选择器、星座选择器、生肖选择器等,可自定义顶部及底部界面,可自定义窗口动画。 5 | 欢迎大伙儿在[Issues](https://github.com/gzu-liyujiang/AndroidPicker/issues)提交你的意见或建议。欢迎Fork & Pull requests贡献您的代码。 6 | 7 | # Change Log 8 | - v1.1.2 - 2016.05.06 9 | + 添加二三级联动选择器; 10 | + 文件选择器布局调整; 11 | - v1.1.1 - 2016.04.23 12 | + 合并@Wastrel及@lutas2000贡献的代码,地址选择器支持只选择省和市、不能混淆某些类; 13 | - v1.1.0 - 2016.01.29 14 | + 添加注解约束,如“setOffset()”只能是1至4; 15 | + 所有枚举类改为常量来表示,据说这样可以节约内存; 16 | + 支持自定义选择器的顶部及底部的视图; 17 | + 支持使用第三方动画库来实现窗口动画; 18 | - v1.0.3 - 2016.01.19 19 | + 日期时间、地址、单项、数字等选择器支持伪循环滚动。 20 | - v1.0.2 - 2016.01.15 21 | + 年或月变动时,保持之前选择的日不动:如果之前选择的日是之前年月的最大日,则日自动为该年月的最大日。 22 | - v1.0.1 - 2016.01.14 23 | + 精简文件选择器的数据适配器; 24 | + 添加选择器顶部确定、取消按钮所在容器的背景色设置。 25 | - v1.0.0 - 2016.01.13 26 | + 发布到jcenter,支持远程maven依赖。 27 | 28 | # Install 29 | “app”是测试用例;“library”包括WheelPicker、ColorPicker、FilePicker, 30 | WheelPicker包括DatePicker、TimePicker、OptionPicker、AddressPicker、NumberPicker等, 31 | 可下载本项目手动进行源代码集成,导入“library”下的相关module,然后依赖,如: 32 | ```groovy 33 | dependencies { 34 | compile project(':WheelPicker') 35 | compile project(':FilePicker') 36 | } 37 | ``` 38 | 也可以直接远程加载jcenter里的,如: 39 | ```groovy 40 | dependencies { 41 | compile 'cn.qqtheme.framework:WheelPicker:1.1.2' 42 | compile 'cn.qqtheme.framework:FilePicker:1.1.2' 43 | } 44 | ``` 45 | *注:* 46 | 本项目使用gradle来构建,迁移到Eclipse比较麻烦,建议换为Android Studio或Intellij IDEA。 47 | 由于地址选择器使用了FastJson来解析,混淆时候需要加入以下类似的规则,不混淆Province、City等实体类。 48 | ``` 49 | -keep class cn.qqtheme.framework.entity.** { *;} 50 | -keep class cn.qqtheme.framework.picker.AddressPicker$* { *;} 51 | ``` 52 | 53 | # Custom 54 | ### 自定义窗口进入退出动画(可选,默认动画为淡入淡出) 55 | ```xml 56 | 57 | 61 | 62 | ``` 63 | ```java 64 | picker.setAnimationStyle(R.style.Animation_CustomPopup); 65 | ``` 66 | 或者使用[ViewAnimator](https://github.com/gzu-liyujiang/ViewAnimator)这个动画库来实现: 67 | ```groovy 68 | dependencies { 69 | compile 'com.github.florent37:viewanimator:1.0.3' 70 | } 71 | ``` 72 | ```java 73 | ViewAnimator.animate(picker.getRootView()) 74 | .slideBottomIn() 75 | .interpolator(new AccelerateInterpolator()) 76 | .start(); 77 | ``` 78 | 79 | ### 自定义顶部及底部界面 80 | 添加自己的类,继承自现有的选择器,覆盖makeHeaderView、makeFooterView,在确定选择时调用onSubmit, 81 | 取消选择时调用onCancel。详见示例:CustomHeaderAndFooterPicker.java。 82 | ```java 83 | public class CustomHeaderAndFooterPicker extends OptionPicker { 84 | 85 | @Nullable 86 | @Override 87 | protected View makeHeaderView() { 88 | return null;//顶部视图 89 | } 90 | 91 | @Nullable 92 | @Override 93 | protected View makeFooterView() { 94 | return null;//底部视图 95 | } 96 | 97 | } 98 | ``` 99 | 100 | # Sample (更多用法详见示例项目) 101 | 日期选择器: 102 | ```java 103 | DatePicker picker = new DatePicker(this, DatePicker.YEAR_MONTH_DAY); 104 | picker.setRange(1990, 2015);//年份范围 105 | picker.setOnDatePickListener(new DatePicker.OnYearMonthDayPickListener() { 106 | @Override 107 | public void onDatePicked(String year, String month, String day) { 108 | showToast(year + "-" + month + "-" + day); 109 | } 110 | }); 111 | picker.show(); 112 | ``` 113 | 114 | 时间选择器: 115 | ```java 116 | //默认选中当前时间 117 | TimePicker picker = new TimePicker(this, TimePicker.HOUR_OF_DAY); 118 | picker.setTopLineVisible(false); 119 | picker.setOnTimePickListener(new TimePicker.OnTimePickListener() { 120 | @Override 121 | public void onTimePicked(String hour, String minute) { 122 | showToast(hour + ":" + minute); 123 | } 124 | }); 125 | picker.show(); 126 | ``` 127 | 128 | 单项选择器(可用于性别、学历、职业、星座等选择): 129 | ```java 130 | OptionPicker picker = new OptionPicker(this, new String[]{ 131 | "第一项", "第二项", "这是一个很长很长很长很长很长很长很长很长很长的很长很长的很长很长的项" 132 | }); 133 | picker.setOffset(2); 134 | picker.setSelectedIndex(1); 135 | picker.setTextSize(11); 136 | picker.setOnOptionPickListener(new OptionPicker.OnOptionPickListener() { 137 | @Override 138 | public void onOptionPicked(String option) { 139 | showToast(option); 140 | } 141 | }); 142 | picker.show(); 143 | ``` 144 | 145 | 数字选择器(可用于身高、体重、年龄等选择): 146 | ```java 147 | NumberPicker picker = new NumberPicker(this); 148 | picker.setOffset(2);//偏移量 149 | picker.setRange(145, 200);//数字范围 150 | picker.setSelectedItem(172); 151 | picker.setLabel("厘米"); 152 | picker.setOnOptionPickListener(new OptionPicker.OnOptionPickListener() { 153 | @Override 154 | public void onOptionPicked(String option) { 155 | showToast(option); 156 | } 157 | }); 158 | picker.show(); 159 | ``` 160 | 161 | 二三级联动选择器(参见地址选择器) 162 | 163 | 地址选择器(含省级、地级、县级): 164 | ```java 165 | ArrayList data = new ArrayList(); 166 | String json = AssetsUtils.readText(this, "city.json"); 167 | data.addAll(JSON.parseArray(json, AddressPicker.Province.class)); 168 | AddressPicker picker = new AddressPicker(this, result); 169 | picker.setSelectedItem("贵州", "贵阳", "花溪"); 170 | //picker.setHideProvince(true);//加上此句举将只显示地级及县级 171 | //picker.setHideCounty(true);//加上此句举将只显示省级及地级 172 | picker.setOnAddressPickListener(new AddressPicker.OnAddressPickListener() { 173 | @Override 174 | public void onAddressPicked(String province, String city, String county) { 175 | showToast(province + city + county); 176 | } 177 | }); 178 | picker.show(); 179 | ``` 180 | 181 | 星座选择器: 182 | ```java 183 | ConstellationPicker picker = new ConstellationPicker(this); 184 | picker.setTopBackgroundColor(0xFFEEEEEE); 185 | picker.setTopLineVisible(false); 186 | picker.setCancelTextColor(0xFF33B5E5); 187 | picker.setSubmitTextColor(0xFF33B5E5); 188 | picker.setTextColor(0xFFFF0000, 0xFFCCCCCC); 189 | picker.setLineColor(0xFFEE0000); 190 | picker.setSelectedItem("射手"); 191 | picker.setOnOptionPickListener(new OptionPicker.OnOptionPickListener() { 192 | @Override 193 | public void onOptionPicked(String option) { 194 | showToast(option); 195 | } 196 | }); 197 | picker.show(); 198 | ``` 199 | 200 | 颜色选择器: 201 | ```java 202 | ColorPicker picker = new ColorPicker(this); 203 | picker.setInitColor(0xFFDD00DD); 204 | picker.setOnColorPickListener(new ColorPicker.OnColorPickListener() { 205 | @Override 206 | public void onColorPicked(int pickedColor) { 207 | showToast(ConvertUtils.toColorString(pickedColor)); 208 | } 209 | }); 210 | picker.show(); 211 | ``` 212 | 213 | 文件选择器(需要权限android.permission.READ_EXTERNAL_STORAGE): 214 | ```java 215 | //noinspection MissingPermission 216 | FilePicker picker = new FilePicker(this, FilePicker.FILE); 217 | picker.setShowHideDir(false); 218 | picker.setRootPath(StorageUtils.getRootPath(this) + "Download/"); 219 | //picker.setAllowExtensions(new String[]{".apk"}); 220 | picker.setOnFilePickListener(new FilePicker.OnFilePickListener() { 221 | @Override 222 | public void onFilePicked(String currentPath) { 223 | showToast(currentPath); 224 | } 225 | }); 226 | picker.show(); 227 | ``` 228 | 229 | 目录选择器(需要权限android.permission.READ_EXTERNAL_STORAGE): 230 | ```java 231 | //noinspection MissingPermission 232 | FilePicker picker = new FilePicker(this, FilePicker.DIRECTORY); 233 | picker.setOnFilePickListener(new FilePicker.OnFilePickListener() { 234 | @Override 235 | public void onFilePicked(String currentPath) { 236 | showToast(currentPath); 237 | } 238 | }); 239 | picker.show(); 240 | ``` 241 | 242 | # Thanks 243 | 库项目修改了使用以下项目: 244 | https://github.com/wangjiegulu/WheelView 245 | https://github.com/jbruchanov/AndroidColorPicker 246 | 247 | # Screenshots 248 | ![自定义选择器效果图](/screenshots/custom.gif) 249 | ![日期选择器效果图](/screenshots/date.gif) 250 | ![时间选择器效果图](/screenshots/time.gif) 251 | ![单项选择器效果图](/screenshots/option.gif) 252 | ![地址选择器效果图](/screenshots/address.gif) 253 | ![地址选择器效果图](/screenshots/address.png) 254 | ![数字选择器效果图](/screenshots/number.gif) 255 | ![星座选择器效果图](/screenshots/constellation.gif) 256 | ![生肖选择器效果图](/screenshots/chinesezodiac.gif) 257 | ![颜色选择器效果图](/screenshots/color.gif) 258 | ![文件选择器效果图](/screenshots/file.gif) 259 | ![目录选择器效果图](/screenshots/dir.gif) 260 | 261 | # Contact 262 | 点击这里给我发消息 263 | 264 | 265 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /*.iml -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | 5 | buildTypes { 6 | release { 7 | //是否zip优化 8 | zipAlignEnabled true 9 | //是否移除无用的资源 10 | shrinkResources true 11 | //是否混淆 12 | minifyEnabled true 13 | //混淆配置文件 14 | proguardFile 'proguard-rules.pro' 15 | } 16 | } 17 | 18 | } 19 | 20 | dependencies { 21 | compile 'com.alibaba:fastjson:1.1.46.android' 22 | compile 'com.github.florent37:viewanimator:1.0.3' 23 | compile project(':library:WheelPicker') 24 | compile project(':library:FilePicker') 25 | compile project(':library:ColorPicker') 26 | // compile 'cn.qqtheme.framework:WheelPicker:1.1.1' 27 | // compile 'cn.qqtheme.framework:FilePicker:1.1.1' 28 | // compile 'cn.qqtheme.framework:ColorPicker:1.1.1' 29 | } 30 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -keep class cn.qqtheme.framework.entity.** { *;} 2 | -keep class cn.qqtheme.framework.picker.AddressPickerr$* { *;} -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/assets/city2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "cities": [ 4 | { 5 | "counties": [ 6 | { 7 | "areaName": "南明区 ", 8 | "areaId": "520102" 9 | }, 10 | { 11 | "areaName": "云岩区", 12 | "areaId": "520103" 13 | }, 14 | { 15 | "areaName": "花溪区 ", 16 | "areaId": "520111" 17 | }, 18 | { 19 | "areaName": "乌当区 ", 20 | "areaId": "520112" 21 | }, 22 | { 23 | "areaName": "白云区", 24 | "areaId": "520113" 25 | }, 26 | { 27 | "areaName": "观山湖区", 28 | "areaId": "520115" 29 | }, 30 | { 31 | "areaName": "开阳县", 32 | "areaId": "520121" 33 | }, 34 | { 35 | "areaName": "息烽县", 36 | "areaId": "520122" 37 | }, 38 | { 39 | "areaName": "修文县 ", 40 | "areaId": "520123" 41 | }, 42 | { 43 | "areaName": "清镇市", 44 | "areaId": "520181" 45 | } 46 | ], 47 | "areaName": "贵阳市 ", 48 | "areaId": "520100" 49 | }, 50 | { 51 | "counties": [ 52 | { 53 | "areaName": "钟山区", 54 | "areaId": "520201" 55 | }, 56 | { 57 | "areaName": "六枝特区 ", 58 | "areaId": "520203" 59 | }, 60 | { 61 | "areaName": "水城县 ", 62 | "areaId": "520221" 63 | }, 64 | { 65 | "areaName": "盘县 ", 66 | "areaId": "520222" 67 | } 68 | ], 69 | "areaName": "六盘水市", 70 | "areaId": "520200" 71 | }, 72 | { 73 | "counties": [ 74 | { 75 | "areaName": "红花岗区 ", 76 | "areaId": "520302" 77 | }, 78 | { 79 | "areaName": "汇川区 ", 80 | "areaId": "520303" 81 | }, 82 | { 83 | "areaName": "遵义县 ", 84 | "areaId": "520321" 85 | }, 86 | { 87 | "areaName": "桐梓县", 88 | "areaId": "520322" 89 | }, 90 | { 91 | "areaName": "绥阳县", 92 | "areaId": "520323" 93 | }, 94 | { 95 | "areaName": "正安县", 96 | "areaId": "520324" 97 | }, 98 | { 99 | "areaName": "道真仡佬族苗族自治县", 100 | "areaId": "520325" 101 | }, 102 | { 103 | "areaName": "务川仡佬族苗族自治县 ", 104 | "areaId": "520326" 105 | }, 106 | { 107 | "areaName": "凤冈县 ", 108 | "areaId": "520327" 109 | }, 110 | { 111 | "areaName": "湄潭县 ", 112 | "areaId": "520328" 113 | }, 114 | { 115 | "areaName": "余庆县 ", 116 | "areaId": "520329" 117 | }, 118 | { 119 | "areaName": "习水县 ", 120 | "areaId": "520330" 121 | }, 122 | { 123 | "areaName": "赤水市", 124 | "areaId": "520381" 125 | }, 126 | { 127 | "areaName": "仁怀市", 128 | "areaId": "520382" 129 | } 130 | ], 131 | "areaName": "遵义市 ", 132 | "areaId": "520300" 133 | }, 134 | { 135 | "counties": [ 136 | { 137 | "areaName": "西秀区 ", 138 | "areaId": "520402" 139 | }, 140 | { 141 | "areaName": "平坝区 ", 142 | "areaId": "520403" 143 | }, 144 | { 145 | "areaName": "普定县 ", 146 | "areaId": "520422" 147 | }, 148 | { 149 | "areaName": "镇宁布依族苗族自治县 ", 150 | "areaId": "520423" 151 | }, 152 | { 153 | "areaName": "关岭布依族苗族自治县 ", 154 | "areaId": "520424" 155 | }, 156 | { 157 | "areaName": "紫云苗族布依族自治县", 158 | "areaId": "520425" 159 | } 160 | ], 161 | "areaName": "安顺市 ", 162 | "areaId": "520400" 163 | }, 164 | { 165 | "counties": [ 166 | { 167 | "areaName": "七星关区 ", 168 | "areaId": "520502" 169 | }, 170 | { 171 | "areaName": "大方县", 172 | "areaId": "520521" 173 | }, 174 | { 175 | "areaName": "黔西县 ", 176 | "areaId": "520522" 177 | }, 178 | { 179 | "areaName": "金沙县 ", 180 | "areaId": "520523" 181 | }, 182 | { 183 | "areaName": "织金县 ", 184 | "areaId": "520524" 185 | }, 186 | { 187 | "areaName": "纳雍县 ", 188 | "areaId": "520525" 189 | }, 190 | { 191 | "areaName": "威宁彝族回族苗族自治县 ", 192 | "areaId": "520526" 193 | }, 194 | { 195 | "areaName": " 赫章县 ", 196 | "areaId": "520527" 197 | } 198 | ], 199 | "areaName": "毕节市 ", 200 | "areaId": "520500" 201 | }, 202 | { 203 | "counties": [ 204 | { 205 | "areaName": "碧江区 ", 206 | "areaId": "520602" 207 | }, 208 | { 209 | "areaName": "万山区", 210 | "areaId": "520603" 211 | }, 212 | { 213 | "areaName": "江口县 ", 214 | "areaId": "520621" 215 | }, 216 | { 217 | "areaName": "玉屏侗族自治县", 218 | "areaId": "520622" 219 | }, 220 | { 221 | "areaName": "石阡县 ", 222 | "areaId": "520623" 223 | }, 224 | { 225 | "areaName": "思南县 ", 226 | "areaId": "520624" 227 | }, 228 | { 229 | "areaName": "印江土家族苗族自治县 ", 230 | "areaId": "520625" 231 | }, 232 | { 233 | "areaName": "德江县 ", 234 | "areaId": "520626" 235 | }, 236 | { 237 | "areaName": "沿河土家族自治县 ", 238 | "areaId": "520627" 239 | }, 240 | { 241 | "areaName": "松桃苗族自治县", 242 | "areaId": "520628" 243 | } 244 | ], 245 | "areaName": "铜仁市", 246 | "areaId": "520600" 247 | }, 248 | { 249 | "counties": [ 250 | { 251 | "areaName": "兴义市 ", 252 | "areaId": "522301" 253 | }, 254 | { 255 | "areaName": "兴仁县 ", 256 | "areaId": "522322" 257 | }, 258 | { 259 | "areaName": "普安县 ", 260 | "areaId": "522323" 261 | }, 262 | { 263 | "areaName": "晴隆县 ", 264 | "areaId": "522324" 265 | }, 266 | { 267 | "areaName": "贞丰县 ", 268 | "areaId": "522325" 269 | }, 270 | { 271 | "areaName": "望谟县 ", 272 | "areaId": "522326" 273 | }, 274 | { 275 | "areaName": "册亨县 ", 276 | "areaId": "522327" 277 | }, 278 | { 279 | "areaName": "安龙县 ", 280 | "areaId": "522328" 281 | } 282 | ], 283 | "areaName": "黔西南布依族苗族自治州", 284 | "areaId": "522300" 285 | }, 286 | { 287 | "counties": [ 288 | { 289 | "areaName": "凯里市 ", 290 | "areaId": "522601" 291 | }, 292 | { 293 | "areaName": "黄平县 ", 294 | "areaId": "522622" 295 | }, 296 | { 297 | "areaName": "施秉县", 298 | "areaId": "522623" 299 | }, 300 | { 301 | "areaName": "三穗县", 302 | "areaId": "522624" 303 | }, 304 | { 305 | "areaName": "镇远县 ", 306 | "areaId": "522625" 307 | }, 308 | { 309 | "areaName": "岑巩县", 310 | "areaId": "522626" 311 | }, 312 | { 313 | "areaName": "天柱县 ", 314 | "areaId": "522627" 315 | }, 316 | { 317 | "areaName": "锦屏县", 318 | "areaId": "522628" 319 | }, 320 | { 321 | "areaName": "剑河县 ", 322 | "areaId": "522629" 323 | }, 324 | { 325 | "areaName": "台江县 ", 326 | "areaId": "522630" 327 | }, 328 | { 329 | "areaName": "黎平县 ", 330 | "areaId": "522631" 331 | }, 332 | { 333 | "areaName": "榕江县 ", 334 | "areaId": "522632" 335 | }, 336 | { 337 | "areaName": "从江县 ", 338 | "areaId": "522633" 339 | }, 340 | { 341 | "areaName": "雷山县 ", 342 | "areaId": "522634" 343 | }, 344 | { 345 | "areaName": "麻江县", 346 | "areaId": "522635" 347 | }, 348 | { 349 | "areaName": "丹寨县", 350 | "areaId": "522636" 351 | } 352 | ], 353 | "areaName": "黔东南苗族侗族自治州", 354 | "areaId": "522600" 355 | }, 356 | { 357 | "counties": [ 358 | { 359 | "areaName": "都匀市 ", 360 | "areaId": "522701" 361 | }, 362 | { 363 | "areaName": "福泉市 ", 364 | "areaId": "522702" 365 | }, 366 | { 367 | "areaName": "荔波县 ", 368 | "areaId": "522722" 369 | }, 370 | { 371 | "areaName": "贵定县 ", 372 | "areaId": "522723" 373 | }, 374 | { 375 | "areaName": "瓮安县", 376 | "areaId": "522725" 377 | }, 378 | { 379 | "areaName": "独山县 ", 380 | "areaId": "522726" 381 | }, 382 | { 383 | "areaName": "平塘县", 384 | "areaId": "522727" 385 | }, 386 | { 387 | "areaName": "罗甸县", 388 | "areaId": "522728" 389 | }, 390 | { 391 | "areaName": "长顺县 ", 392 | "areaId": "522729" 393 | }, 394 | { 395 | "areaName": "龙里县", 396 | "areaId": "522730" 397 | }, 398 | { 399 | "areaName": "惠水县 ", 400 | "areaId": "522731" 401 | }, 402 | { 403 | "areaName": "三都水族自治县 ", 404 | "areaId": "522732" 405 | } 406 | ], 407 | "areaName": "黔南布依族苗族自治州 ", 408 | "areaId": "522700" 409 | }, 410 | { 411 | "counties": [ 412 | { 413 | "areaName": "贵安新区", 414 | "areaId": "529900" 415 | } 416 | ], 417 | "areaName": "贵安新区", 418 | "areaId": "529900" 419 | } 420 | ], 421 | "areaName": "贵州省 ", 422 | "areaId": "520000" 423 | } 424 | ] -------------------------------------------------------------------------------- /app/src/main/java/cn/qqtheme/androidpicker/AddressInitTask.java: -------------------------------------------------------------------------------- 1 | package cn.qqtheme.androidpicker; 2 | 3 | import android.app.Activity; 4 | import android.app.ProgressDialog; 5 | import android.os.AsyncTask; 6 | import android.widget.Toast; 7 | 8 | import com.alibaba.fastjson.JSON; 9 | 10 | import java.util.ArrayList; 11 | 12 | import cn.qqtheme.framework.picker.AddressPicker; 13 | 14 | /** 15 | * 获取地址数据并显示地址选择器 16 | * 17 | * @author 李玉江[QQ:1032694760] 18 | * @version 2015/12/15 19 | */ 20 | public class AddressInitTask extends AsyncTask> { 21 | private Activity activity; 22 | private ProgressDialog dialog; 23 | private String selectedProvince = "", selectedCity = "", selectedCounty = ""; 24 | private boolean hideCounty=false; 25 | 26 | /** 27 | * 初始化为不显示区县的模式 28 | * @param activity 29 | * @param hideCounty is hide County 30 | */ 31 | public AddressInitTask(Activity activity,boolean hideCounty) { 32 | this.activity = activity; 33 | this.hideCounty=hideCounty; 34 | dialog = ProgressDialog.show(activity, null, "正在初始化数据...", true, true); 35 | } 36 | 37 | public AddressInitTask(Activity activity) { 38 | this.activity = activity; 39 | dialog = ProgressDialog.show(activity, null, "正在初始化数据...", true, true); 40 | } 41 | @Override 42 | protected ArrayList doInBackground(String... params) { 43 | if (params != null) { 44 | switch (params.length) { 45 | case 1: 46 | selectedProvince = params[0]; 47 | break; 48 | case 2: 49 | selectedProvince = params[0]; 50 | selectedCity = params[1]; 51 | break; 52 | case 3: 53 | selectedProvince = params[0]; 54 | selectedCity = params[1]; 55 | selectedCounty = params[2]; 56 | break; 57 | default: 58 | break; 59 | } 60 | } 61 | ArrayList data = new ArrayList(); 62 | try { 63 | String json = AssetsUtils.readText(activity, "city.json"); 64 | data.addAll(JSON.parseArray(json, AddressPicker.Province.class)); 65 | } catch (Exception e) { 66 | e.printStackTrace(); 67 | } 68 | return data; 69 | } 70 | 71 | @Override 72 | protected void onPostExecute(ArrayList result) { 73 | dialog.dismiss(); 74 | if (result.size() > 0) { 75 | AddressPicker picker = new AddressPicker(activity, result); 76 | picker.setHideCounty(hideCounty); 77 | picker.setSelectedItem(selectedProvince, selectedCity, selectedCounty); 78 | picker.setOnAddressPickListener(new AddressPicker.OnAddressPickListener() { 79 | @Override 80 | public void onAddressPicked(String province, String city, String county) { 81 | if (county==null){ 82 | Toast.makeText(activity, province + city, Toast.LENGTH_LONG).show(); 83 | } else { 84 | Toast.makeText(activity, province + city + county, Toast.LENGTH_LONG).show(); 85 | } 86 | } 87 | }); 88 | picker.show(); 89 | } else { 90 | Toast.makeText(activity, "数据初始化失败", Toast.LENGTH_SHORT).show(); 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/cn/qqtheme/androidpicker/AssetsUtils.java: -------------------------------------------------------------------------------- 1 | package cn.qqtheme.androidpicker; 2 | 3 | import android.content.Context; 4 | 5 | import cn.qqtheme.framework.util.ConvertUtils; 6 | import cn.qqtheme.framework.util.LogUtils; 7 | 8 | /** 9 | * 操作安装包中的“assets”目录下的文件 10 | * 11 | * @author 李玉江[QQ:1023694760] 12 | * @version 2013-11-2 13 | */ 14 | public class AssetsUtils { 15 | 16 | /** 17 | * read file content 18 | * 19 | * @param context the context 20 | * @param assetPath the asset path 21 | * @return String string 22 | */ 23 | public static String readText(Context context, String assetPath) { 24 | LogUtils.debug("read assets file as text: " + assetPath); 25 | try { 26 | return ConvertUtils.toString(context.getAssets().open(assetPath)); 27 | } catch (Exception e) { 28 | LogUtils.error(e); 29 | return ""; 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/cn/qqtheme/androidpicker/CustomHeaderAndFooterPicker.java: -------------------------------------------------------------------------------- 1 | package cn.qqtheme.androidpicker; 2 | 3 | import android.app.Activity; 4 | import android.support.annotation.Nullable; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.animation.AccelerateInterpolator; 8 | import android.widget.Button; 9 | import android.widget.TextView; 10 | 11 | import com.github.florent37.viewanimator.AnimationListener; 12 | import com.github.florent37.viewanimator.ViewAnimator; 13 | 14 | import cn.qqtheme.framework.picker.OptionPicker; 15 | 16 | /** 17 | * 自定义顶部及底部 18 | *

19 | * Author:李玉江[QQ:1032694760] 20 | * Email:liyujiang_tk@yeah.net 21 | * DateTime:2016/1/29 14:47 22 | * Builder:Android Studio 23 | */ 24 | public class CustomHeaderAndFooterPicker extends OptionPicker { 25 | 26 | public CustomHeaderAndFooterPicker(Activity activity) { 27 | super(activity, new String[]{ 28 | "C/C++", "Java", "PHP", "Swift", "Node.js", "C#", "HTML5" 29 | }); 30 | setTitleText("请选择你最擅长的语言"); 31 | setSelectedItem("PHP"); 32 | } 33 | 34 | @Override 35 | public void show() { 36 | super.show(); 37 | ViewAnimator.animate(getRootView()) 38 | .duration(2000) 39 | .interpolator(new AccelerateInterpolator()) 40 | .slideBottom() 41 | .start(); 42 | } 43 | 44 | @Override 45 | public void dismiss() { 46 | ViewAnimator.animate(getRootView()) 47 | .duration(1000) 48 | .rollOut() 49 | .onStop(new AnimationListener.Stop() { 50 | @Override 51 | public void onStop() { 52 | CustomHeaderAndFooterPicker.super.dismiss(); 53 | } 54 | }) 55 | .start(); 56 | } 57 | 58 | @Nullable 59 | @Override 60 | protected View makeHeaderView() { 61 | View view = LayoutInflater.from(activity).inflate(R.layout.picker_header, null); 62 | TextView titleView = (TextView) view.findViewById(R.id.picker_title); 63 | titleView.setText(titleText); 64 | return view; 65 | } 66 | 67 | @Nullable 68 | @Override 69 | protected View makeFooterView() { 70 | View view = LayoutInflater.from(activity).inflate(R.layout.picker_footer, null); 71 | Button submitView = (Button) view.findViewById(R.id.picker_submit); 72 | submitView.setText(submitText); 73 | submitView.setOnClickListener(new View.OnClickListener() { 74 | @Override 75 | public void onClick(View v) { 76 | dismiss(); 77 | onSubmit(); 78 | } 79 | }); 80 | Button cancelView = (Button) view.findViewById(R.id.picker_cancel); 81 | cancelView.setText(cancelText); 82 | cancelView.setOnClickListener(new View.OnClickListener() { 83 | @Override 84 | public void onClick(View v) { 85 | dismiss(); 86 | onCancel(); 87 | } 88 | }); 89 | return view; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/cn/qqtheme/androidpicker/MainActivity.java: -------------------------------------------------------------------------------- 1 | package cn.qqtheme.androidpicker; 2 | 3 | import android.app.Activity; 4 | import android.content.DialogInterface; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Bundle; 8 | import android.view.View; 9 | import android.widget.Toast; 10 | 11 | import com.alibaba.fastjson.JSON; 12 | import com.github.florent37.viewanimator.ViewAnimator; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Calendar; 16 | 17 | import cn.qqtheme.framework.picker.AddressPicker; 18 | import cn.qqtheme.framework.picker.ChineseZodiacPicker; 19 | import cn.qqtheme.framework.picker.ColorPicker; 20 | import cn.qqtheme.framework.picker.ConstellationPicker; 21 | import cn.qqtheme.framework.picker.DatePicker; 22 | import cn.qqtheme.framework.picker.DateTimePicker; 23 | import cn.qqtheme.framework.picker.FilePicker; 24 | import cn.qqtheme.framework.picker.LinkagePicker; 25 | import cn.qqtheme.framework.picker.NumberPicker; 26 | import cn.qqtheme.framework.picker.OptionPicker; 27 | import cn.qqtheme.framework.picker.SexPicker; 28 | import cn.qqtheme.framework.picker.TimePicker; 29 | import cn.qqtheme.framework.util.ConvertUtils; 30 | import cn.qqtheme.framework.util.DateUtils; 31 | import cn.qqtheme.framework.util.StorageUtils; 32 | 33 | public class MainActivity extends Activity { 34 | 35 | private Calendar calendar = Calendar.getInstance(); 36 | @Override 37 | protected void onCreate(Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | setContentView(R.layout.activity_main); 40 | } 41 | 42 | @Override 43 | public void onBackPressed() { 44 | System.exit(0); 45 | android.os.Process.killProcess(android.os.Process.myPid()); 46 | finish(); 47 | } 48 | 49 | private void showToast(String msg) { 50 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); 51 | } 52 | 53 | public void onAnimationStyle(View view) { 54 | NumberPicker picker = new NumberPicker(this); 55 | picker.setAnimationStyle(R.style.Animation_CustomPopup); 56 | picker.setOffset(2);//偏移量 57 | picker.setRange(40, 100);//数字范围 58 | picker.setSelectedItem(65); 59 | picker.setLabel("Kg"); 60 | picker.setOnOptionPickListener(new OptionPicker.OnOptionPickListener() { 61 | @Override 62 | public void onOptionPicked(String option) { 63 | showToast(option); 64 | } 65 | }); 66 | picker.show(); 67 | } 68 | 69 | public void onAnimator(View view) { 70 | CustomHeaderAndFooterPicker picker = new CustomHeaderAndFooterPicker(this); 71 | picker.setOnOptionPickListener(new OptionPicker.OnOptionPickListener() { 72 | @Override 73 | public void onOptionPicked(String option) { 74 | showToast(option); 75 | } 76 | }); 77 | picker.show(); 78 | } 79 | 80 | public void onYearMonthDayPicker(View view) { 81 | DatePicker picker = new DatePicker(this); 82 | picker.setRange(2000, 2030); 83 | picker.setSelectedItem(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH)); 84 | picker.setOnDatePickListener(new DatePicker.OnYearMonthDayPickListener() { 85 | @Override 86 | public void onDatePicked(String year, String month, String day) { 87 | showToast(year + "-" + month + "-" + day); 88 | } 89 | }); 90 | picker.show(); 91 | } 92 | 93 | 94 | public void onYearMonthDayTimePicker(View view) { 95 | DateTimePicker picker = new DateTimePicker(this, DateTimePicker.HOUR_OF_DAY); 96 | picker.setRange(2000, 2030); 97 | picker.setSelectedItem(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH)+1, calendar.get(Calendar.DAY_OF_MONTH), 98 | calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE)); 99 | picker.setOnDateTimePickListener(new DateTimePicker.OnYearMonthDayTimePickListener() { 100 | @Override 101 | public void onDateTimePicked(String year, String month, String day, String hour, String minute) { 102 | showToast(year + "-" + month + "-" + day + " " + hour + ":" + minute); 103 | } 104 | }); 105 | picker.show(); 106 | } 107 | 108 | 109 | 110 | public void onYearMonthPicker(View view) { 111 | DatePicker picker = new DatePicker(this, DatePicker.YEAR_MONTH); 112 | picker.setRange(1990, 2015); 113 | picker.setOnDatePickListener(new DatePicker.OnYearMonthPickListener() { 114 | @Override 115 | public void onDatePicked(String year, String month) { 116 | showToast(year + "-" + month); 117 | } 118 | }); 119 | picker.show(); 120 | } 121 | 122 | public void onMonthDayPicker(View view) { 123 | DatePicker picker = new DatePicker(this, DatePicker.MONTH_DAY); 124 | picker.setOnDatePickListener(new DatePicker.OnMonthDayPickListener() { 125 | @Override 126 | public void onDatePicked(String month, String day) { 127 | showToast(month + "-" + day); 128 | } 129 | }); 130 | picker.show(); 131 | } 132 | 133 | public void onTimePicker(View view) { 134 | //默认选中当前时间 135 | TimePicker picker = new TimePicker(this, TimePicker.HOUR_OF_DAY); 136 | picker.setTopLineVisible(false); 137 | picker.setOnTimePickListener(new TimePicker.OnTimePickListener() { 138 | @Override 139 | public void onTimePicked(String hour, String minute) { 140 | showToast(hour + ":" + minute); 141 | } 142 | }); 143 | picker.show(); 144 | } 145 | 146 | public void onOptionPicker(View view) { 147 | OptionPicker picker = new OptionPicker(this, new String[]{ 148 | "第一项", "第二项", "这是一个很长很长很长很长很长很长很长很长很长的很长很长的很长很长的项" 149 | }); 150 | picker.setOffset(2); 151 | picker.setSelectedIndex(1); 152 | picker.setTextSize(11); 153 | picker.setOnOptionPickListener(new OptionPicker.OnOptionPickListener() { 154 | @Override 155 | public void onOptionPicked(String option) { 156 | showToast(option); 157 | } 158 | }); 159 | picker.show(); 160 | } 161 | 162 | public void onLinkagePicker(View view) { 163 | ArrayList firstList = new ArrayList(); 164 | firstList.add("今天"); 165 | firstList.add("明天"); 166 | ArrayList> secondList = new ArrayList>(); 167 | ArrayList secondListItem = new ArrayList(); 168 | for (int i = 0; i < 24; i++) { 169 | secondListItem.add(DateUtils.fillZero(i) + "点"); 170 | } 171 | secondList.add(secondListItem);//对应今天 172 | secondList.add(secondListItem);//对应明天 173 | ArrayList>> thirdList = new ArrayList>>(); 174 | ArrayList> thirdListItem1 = new ArrayList>(); 175 | ArrayList thirdListItem2 = new ArrayList(); 176 | for (int i = 0; i < 60; i++) { 177 | thirdListItem2.add(DateUtils.fillZero(i) + "分"); 178 | } 179 | for (int i = 0; i < 24; i++) { 180 | thirdListItem1.add(thirdListItem2);//对应0-23点 181 | } 182 | thirdList.add(thirdListItem1);//对应今天 183 | thirdList.add(thirdListItem1);//对应明天 184 | LinkagePicker picker = new LinkagePicker(this, firstList, secondList); 185 | picker.setSelectedItem("明天", "9点"); 186 | picker.setOnLinkageListener(new LinkagePicker.OnLinkageListener() { 187 | 188 | @Override 189 | public void onPicked(String first, String second, String third) { 190 | showToast(first + "-" + second + "-" + third); 191 | } 192 | }); 193 | picker.show(); 194 | } 195 | 196 | public void onConstellationPicker(View view) { 197 | ConstellationPicker picker = new ConstellationPicker(this); 198 | picker.setTopBackgroundColor(0xFFEEEEEE); 199 | picker.setTopLineVisible(false); 200 | picker.setCancelTextColor(0xFF33B5E5); 201 | picker.setSubmitTextColor(0xFF33B5E5); 202 | picker.setTextColor(0xFFFF0000, 0xFFCCCCCC); 203 | picker.setLineColor(0xFFEE0000); 204 | picker.setSelectedItem("射手"); 205 | picker.setOnOptionPickListener(new OptionPicker.OnOptionPickListener() { 206 | @Override 207 | public void onOptionPicked(String option) { 208 | showToast(option); 209 | } 210 | }); 211 | picker.show(); 212 | } 213 | 214 | public void onChineseZodiacPicker(View view) { 215 | ChineseZodiacPicker picker = new ChineseZodiacPicker(this); 216 | picker.setLineVisible(false); 217 | picker.setSelectedItem("羊"); 218 | picker.setOnOptionPickListener(new OptionPicker.OnOptionPickListener() { 219 | @Override 220 | public void onOptionPicked(String option) { 221 | showToast(option); 222 | } 223 | }); 224 | picker.show(); 225 | } 226 | 227 | public void onNumberPicker(View view) { 228 | NumberPicker picker = new NumberPicker(this); 229 | picker.setOffset(2);//偏移量 230 | picker.setRange(145, 200);//数字范围 231 | picker.setSelectedItem(172); 232 | picker.setLabel("厘米"); 233 | picker.setOnOptionPickListener(new OptionPicker.OnOptionPickListener() { 234 | @Override 235 | public void onOptionPicked(String option) { 236 | showToast(option); 237 | } 238 | }); 239 | picker.show(); 240 | } 241 | 242 | public void onSexPicker(View view) { 243 | SexPicker picker = new SexPicker(this); 244 | //picker.onlyMaleAndFemale(); 245 | picker.setOnOptionPickListener(new OptionPicker.OnOptionPickListener() { 246 | @Override 247 | public void onOptionPicked(String option) { 248 | showToast(option); 249 | } 250 | }); 251 | picker.show(); 252 | } 253 | 254 | public void onAddressPicker(View view) { 255 | new AddressInitTask(this).execute("贵州", "毕节", "纳雍"); 256 | } 257 | 258 | public void onAddress2Picker(View view) { 259 | try { 260 | ArrayList data = new ArrayList(); 261 | String json = AssetsUtils.readText(this, "city2.json"); 262 | data.addAll(JSON.parseArray(json, AddressPicker.Province.class)); 263 | AddressPicker picker = new AddressPicker(this, data); 264 | picker.setHideProvince(true); 265 | picker.setSelectedItem("贵州", "贵阳", "花溪"); 266 | picker.setOnAddressPickListener(new AddressPicker.OnAddressPickListener() { 267 | @Override 268 | public void onAddressPicked(String province, String city, String county) { 269 | showToast(city + county); 270 | } 271 | }); 272 | picker.show(); 273 | } catch (Exception e) { 274 | showToast(e.toString()); 275 | } 276 | } 277 | 278 | 279 | public void onAddress3Picker(View view) { 280 | new AddressInitTask(this, true).execute("四川", "成都"); 281 | } 282 | 283 | public void onColorPicker(View view) { 284 | ColorPicker picker = new ColorPicker(this); 285 | picker.setInitColor(0xDD00DD); 286 | picker.setOnColorPickListener(new ColorPicker.OnColorPickListener() { 287 | @Override 288 | public void onColorPicked(int pickedColor) { 289 | showToast(ConvertUtils.toColorString(pickedColor)); 290 | } 291 | }); 292 | picker.show(); 293 | } 294 | 295 | public void onFilePicker(View view) { 296 | //noinspection MissingPermission 297 | FilePicker picker = new FilePicker(this, FilePicker.FILE); 298 | picker.setShowHideDir(false); 299 | //picker.setAllowExtensions(new String[]{".apk"}); 300 | picker.setOnFilePickListener(new FilePicker.OnFilePickListener() { 301 | @Override 302 | public void onFilePicked(String currentPath) { 303 | showToast(currentPath); 304 | } 305 | }); 306 | picker.show(); 307 | } 308 | 309 | public void onDirPicker(View view) { 310 | //noinspection MissingPermission 311 | FilePicker picker = new FilePicker(this, FilePicker.DIRECTORY); 312 | picker.setRootPath(StorageUtils.getRootPath(this) + "Download/"); 313 | picker.setOnFilePickListener(new FilePicker.OnFilePickListener() { 314 | @Override 315 | public void onFilePicked(String currentPath) { 316 | showToast(currentPath); 317 | } 318 | }); 319 | picker.show(); 320 | } 321 | 322 | public void onContact(View view) { 323 | Intent intent = new Intent(Intent.ACTION_SENDTO); 324 | intent.setData(Uri.parse("mailto:liyujiang_tk@yeah.net")); 325 | intent.putExtra(Intent.EXTRA_CC, new String[] 326 | {"1032694760@qq.com"}); 327 | intent.putExtra(Intent.EXTRA_EMAIL, ""); 328 | intent.putExtra(Intent.EXTRA_TEXT, "欢迎提供意您的见或建议"); 329 | startActivity(Intent.createChooser(intent, "选择邮件客户端")); 330 | } 331 | 332 | } 333 | -------------------------------------------------------------------------------- /app/src/main/res/anim/popup_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/anim/popup_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 |