├── .gitignore ├── LICENSE ├── README-en.md ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── bigkoo │ │ └── pickerviewdemo │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── province.json │ ├── java │ └── com │ │ └── bigkoo │ │ └── pickerviewdemo │ │ ├── FragmentTestActivity.java │ │ ├── GetJsonDataUtil.java │ │ ├── JsonDataActivity.java │ │ ├── MainActivity.java │ │ ├── TestCircleWheelViewActivity.java │ │ ├── TestFragment.java │ │ └── bean │ │ ├── CardBean.java │ │ ├── JsonBean.java │ │ └── ProvinceBean.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ ├── ic_launcher.png │ └── to_down.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── layout │ ├── activity_fragmenttest.xml │ ├── activity_json_data.xml │ ├── activity_main.xml │ ├── activity_test_circle_wheelview.xml │ ├── fragment_test.xml │ ├── pickerview_custom_lunar.xml │ ├── pickerview_custom_options.xml │ └── pickerview_custom_time.xml │ ├── menu │ └── menu_main.xml │ ├── values-en │ └── strings.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── pickerview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── bigkoo │ │ └── pickerview │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── bigkoo │ │ └── pickerview │ │ ├── adapter │ │ ├── ArrayWheelAdapter.java │ │ └── NumericWheelAdapter.java │ │ ├── builder │ │ ├── OptionsPickerBuilder.java │ │ └── TimePickerBuilder.java │ │ ├── configure │ │ └── PickerOptions.java │ │ ├── listener │ │ ├── CustomListener.java │ │ ├── ISelectTimeCallback.java │ │ ├── OnDismissListener.java │ │ ├── OnOptionsSelectChangeListener.java │ │ ├── OnOptionsSelectListener.java │ │ ├── OnTimeSelectChangeListener.java │ │ └── OnTimeSelectListener.java │ │ ├── utils │ │ ├── ChinaDate.java │ │ ├── LunarCalendar.java │ │ └── PickerViewAnimateUtil.java │ │ └── view │ │ ├── BasePickerView.java │ │ ├── OptionsPickerView.java │ │ ├── TimePickerView.java │ │ ├── WheelOptions.java │ │ └── WheelTime.java │ └── res │ ├── anim │ ├── pickerview_dialog_scale_in.xml │ ├── pickerview_dialog_scale_out.xml │ ├── pickerview_slide_in_bottom.xml │ └── pickerview_slide_out_bottom.xml │ ├── drawable │ └── selector_pickerview_btn.xml │ ├── layout │ ├── include_pickerview_topbar.xml │ ├── layout_basepickerview.xml │ ├── pickerview_options.xml │ └── pickerview_time.xml │ ├── values-en │ └── strings.xml │ └── values │ ├── dimens.xml │ ├── integers.xml │ ├── strings.xml │ └── styles.xml ├── preview ├── CustomLayout.gif ├── JsonData.gif ├── Screen Shot 2017-11-09 at 4.25.02 PM.png ├── lunar.gif ├── pickerdemo.gif ├── pickerdemo1x.gif ├── pickerdemo_zhangshangshenghuo.gif ├── timepicker.gif └── timepicker_night.gif ├── settings.gradle └── wheelview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── test │ └── wheelview │ └── ExampleInstrumentedTest.java └── main ├── AndroidManifest.xml ├── java └── com │ └── contrarywind │ ├── adapter │ └── WheelAdapter.java │ ├── interfaces │ └── IPickerViewData.java │ ├── listener │ ├── LoopViewGestureListener.java │ └── OnItemSelectedListener.java │ ├── timer │ ├── InertiaTimerTask.java │ ├── MessageHandler.java │ └── SmoothScrollTimerTask.java │ └── view │ └── WheelView.java └── res └── values ├── attrs.xml ├── colors.xml ├── dimens.xml └── strings.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Eclipse project files 19 | .classpath 20 | .project 21 | 22 | # Android Studio 23 | .idea/ 24 | .gradle 25 | /*/local.properties 26 | /*/out 27 | build 28 | /*/*/production 29 | *.iml 30 | *.iws 31 | *.ipr 32 | *~ 33 | *.swp -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README-en.md: -------------------------------------------------------------------------------- 1 | 2 | # Android-PickerView 3 | 4 | 5 | 6 | [![API](https://img.shields.io/badge/API-9%2B-brightgreen.svg)](https://android-arsenal.com/api?level=9) 7 | [![license](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0) 8 | 9 | #### Show some :heart: and :stars: the repo to support the project 10 | [![GitHub stars](https://img.shields.io/github/stars/Bigkoo/Android-PickerView.svg?style=social)](https://github.com/Bigkoo/Android-PickerView/stargazers) [![GitHub forks](https://img.shields.io/github/forks/Bigkoo/Android-PickerView.svg?style=social)](https://github.com/Bigkoo/Android-PickerView/network) [![GitHub watchers](https://img.shields.io/github/watchers/Bigkoo/Android-PickerView.svg?style=social)](https://github.com/Bigkoo/Android-PickerView/watchers) 11 | 12 | #### [中文文档](https://github.com/Bigkoo/Android-PickerView/blob/master/README.md) 13 | 14 | ## Introduction 15 | 16 | This is a library for android to pick date or options like IOS system WheelView widget. 17 | and support for the linkage, dialog . It's very easy to use , you also can customize layout, which make it very customizable. 18 | 19 | 20 | * there are two options called OptionsPickerView and TimePickerView 21 | 22 | * OptionsPickerView supports three levels of linkage 23 | 24 | * TimePickerView support selection date range 25 | 26 | * support "year, month, day, hour, minute, second", "provincial, city, district" and other options of the unit (label) show or hide and customize label. 27 | 28 | * supports custom text, color, text size, etc. 29 | 30 | * If Item text length is too long, it will be adapted to the length of the Item to avoid the problem of incomplete display 31 | 32 | 33 | 34 | # How to use 35 | 36 | 37 | ## 1.Add the dependency: 38 | 39 | ### Gradle 40 | 41 | ```java 42 | compile 'com.contrarywind:Android-PickerView:4.1.9' 43 | ``` 44 | 45 | ### Maven 46 | 47 | ``` 48 | 49 | com.contrarywind 50 | Android-PickerView 51 | 4.1.8 52 | pom 53 | 54 | ``` 55 | 56 | ## 2.Add the following code in your Activity: 57 | 58 | ```java 59 | //TimePicker 60 | pvTime = new TimePickerBuilder(this, new OnTimeSelectListener() { 61 | @Override 62 | public void onTimeSelect(Date date,View v) {//Callback 63 | tvTime.setText(getTime(date)); 64 | } 65 | }) 66 | .build(); 67 | pvTime.show(); 68 | ``` 69 | 70 | ```java 71 | //OptionsPicker 72 | pvOptions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() { 73 | @Override 74 | public void onOptionsSelect(int options1, int option2, int options3 ,View v) { 75 | ////Callback 76 | String tx = options1Items.get(options1).getPickerViewText() 77 | + options2Items.get(options1).get(option2) 78 | + options3Items.get(options1).get(option2).get(options3).getPickerViewText(); 79 | tvOptions.setText(tx); 80 | } 81 | }).build(); 82 | 83 | //pvOptions.setPicker(options1Items); 84 | pvOptions.setPicker(options1Items, options2Items); 85 | //pvOptions.setPicker(options1Items, options2Items, options3Items); 86 | pvOptions.show(); 87 | ``` 88 | ## Just so easy ~ 89 | 90 | 91 | ### Notes(2017-7-10) 92 | - when we start setting the date, we need to pay special attention. 93 | 94 | - reason: the internal component of the Calendar adds 1 processing, which made the month's number of count reduced one. 95 | - error usage case: 96 | 97 | >StartDate.set (2013,1,1); 98 | 99 | >EndDate.set (2020,12,31); 100 | 101 | - correct use case: 102 | 103 | >StartDate.set (2013,0,1); 104 | 105 | >EndDate.set (2020,11,31); 106 |
107 | 108 | 109 | If the default style does not meet your expectations, You can also customize attributes to apply 110 | 111 | ## Customize Useage: 112 | ```java 113 | Calendar selectedDate = Calendar.getInstance(); 114 | Calendar startDate = Calendar.getInstance(); 115 | startDate.set(2013,0,1); 116 | Calendar endDate = Calendar.getInstance(); 117 | endDate.set(2020,11,1); 118 | 119 | pvTime = new TimePickerBuilder(this, new OnTimeSelectListener() { 120 | @Override 121 | public void onTimeSelect(Date date,View v) {//callback 122 | tvTime.setText(getTime(date)); 123 | } 124 | }) 125 | .setType(new boolean[]{false, false, false, true, true, false})// type of date 126 | .setCancelText("Cancel") 127 | .setSubmitText("Sure") 128 | .setContentSize(18) 129 | .setTitleSize(20) 130 | .setTitleText("Title") 131 | .setOutSideCancelable(false)// default is true 132 | .isCyclic(true)// default is false 133 | .setTitleColor(Color.BLACK) 134 | .setSubmitColor(Color.BLUE) 135 | .setCancelColor(Color.BLUE) 136 | .setTitleBgColor(0xFF666666)//night mode 137 | .setBgColor(0xFF333333)//night mode 138 | .setRangDate(startDate,endDate) 139 | .setLabel("year","month","day","hours","mins","seconds") 140 | .build(); 141 | ``` 142 | 143 | ```java 144 | pvOptions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() { 145 | @Override 146 | public void onOptionsSelect(int options1, int option2, int options3 ,View v) { 147 | ////Callback 148 | String tx = options1Items.get(options1).getPickerViewText() 149 | + options2Items.get(options1).get(option2) 150 | + options3Items.get(options1).get(option2).get(options3).getPickerViewText(); 151 | tvOptions.setText(tx); 152 | } 153 | }) 154 | .setSubmitText("sure") 155 | .setCancelText("cancel") 156 | .setTitleText("title") 157 | .setSubCalSize(18) 158 | .setTitleSize(20) 159 | .setTitleColor(Color.BLACK) 160 | .setSubmitColor(Color.BLUE) 161 | .setCancelColor(Color.BLUE) 162 | .setTitleBgColor(0xFF666666)//night mode 163 | .setBgColor(0xFF444444)//night mode 164 | .setContentTextSize(18) 165 | .setLinkage(false) 166 | .isCenterLabel(false) //default is true , if you choose false , the label text will add to all item ContentText right 167 | .setLabels("province", "city", "district") 168 | .setCyclic(false, false, false) 169 | .setSelectOptions(0, 0, 0) //default options 170 | .setOutSideCancelable(false)//dismiss, default is true 171 | .isRestoreItem(true)// restore option with first item when select changed。 172 | .build(); 173 | 174 | pvOptions.setPicker(options1Items, options2Items, options3Items); 175 | ``` 176 | ## Customize Layout: 177 | ```java 178 | private void initCustomTimePicker() { 179 | // be careful:In the custom layout, the layout of the ID for optionspicker 180 | // or TimePicker and its child widget must not be modified, 181 | // otherwise will be reported NullPointerException 182 | // For more details, Please refer to the two custom layouts in demo 183 | 184 | Calendar selectedDate = Calendar.getInstance();//System current time 185 | Calendar startDate = Calendar.getInstance(); 186 | startDate.set(2013,1,23); 187 | Calendar endDate = Calendar.getInstance(); 188 | endDate.set(2019,2,28); 189 | 190 | pvCustomTime = new TimePickerBuilder(this, new OnTimeSelectListener() { 191 | @Override 192 | public void onTimeSelect(Date date, View v) {//call back 193 | btn_CustomTime.setText(getTime(date)); 194 | } 195 | }) .setType(new boolean[]{true, true, true, false, false, false})// year - month - day 196 | .setDate(selectedDate) 197 | .setRangDate(startDate,endDate) 198 | .setLayoutRes(R.layout.pickerview_custom_time, new CustomListener() { 199 | 200 | @Override 201 | public void customLayout(View v) { 202 | final TextView tvSubmit = (TextView) v.findViewById(R.id.tv_finish); 203 | ImageView ivCancel = (ImageView) v.findViewById(R.id.iv_cancel); 204 | tvSubmit.setOnClickListener(new View.OnClickListener() { 205 | @Override 206 | public void onClick(View v) { 207 | pvCustomTime.returnData(tvSubmit); 208 | } 209 | }); 210 | ivCancel.setOnClickListener(new View.OnClickListener() { 211 | @Override 212 | public void onClick(View v) { 213 | pvCustomTime.dismiss(); 214 | } 215 | }); 216 | } 217 | }) 218 | .setDividerColor(Color.BLACK) 219 | .build(); 220 | 221 | } 222 | ``` 223 | 224 | ## If you need to set the non-linkage data: 225 | 226 | ```java 227 | pvNoLinkOptions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() { 228 | 229 | @Override 230 | public void onOptionsSelect(int options1, int options2, int options3, View v) { 231 | 232 | String str = "food:"+food.get(options1) 233 | +"\nclothes:"+clothes.get(options2) 234 | +"\ncomputer:"+computer.get(options3); 235 | 236 | Toast.makeText(MainActivity.this,str,Toast.LENGTH_SHORT).show(); 237 | } 238 | }).build(); 239 | pvNoLinkOptions.setNPicker(food,clothes,computer); 240 | pvNoLinkOptions.show(); 241 | ``` 242 | 243 | ## For more detail, please refer to the Demo code, If there is still doubt about you, please [New Issue](https://github.com/Bigkoo/Android-PickerView/issues) 244 | 245 | ### [Here is demo code](https://github.com/Bigkoo/Android-PickerView/blob/master/app/src/main/java/com/bigkoo/pickerviewdemo/MainActivity.java) 246 | 247 | ### [Methods-and-parameters](https://github.com/Bigkoo/Android-PickerView/wiki/Methods-and-parameters) 248 | 249 | 250 | ## Thanks 251 | 252 | - [WheelView](https://github.com/venshine/WheelView) 253 | - [androidWheelView](https://github.com/weidongjian/androidWheelView/) 254 | 255 | # License 256 | 257 | ``` 258 | Copyright 2014 Bigkoo 259 | Licensed under the Apache License, Version 2.0 (the "License"); 260 | you may not use this file except in compliance with the License. 261 | You may obtain a copy of the License at 262 | 263 | http://www.apache.org/licenses/LICENSE-2.0 264 | 265 | Unless required by applicable law or agreed to in writing, software 266 | distributed under the License is distributed on an "AS IS" BASIS, 267 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 268 | See the License for the specific language governing permissions and 269 | limitations under the License. 270 | ``` 271 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 注意⚠️:已停止更新,原有版本jcenter库可以继续使用。建议直接下载源码引入 module 到自己项目改造。 2 | 3 | ## Android-PickerView 4 | [![API](https://img.shields.io/badge/API-9%2B-brightgreen.svg)](https://android-arsenal.com/api?level=9) 5 | [![License](https://img.shields.io/badge/license-Apache%202-green.svg)](https://www.apache.org/licenses/LICENSE-2.0) 6 | [![Download](https://api.bintray.com/packages/contrarywind/maven/Android-PickerView/images/download.svg) ](https://bintray.com/contrarywind/maven/Android-PickerView/_latestVersion) 7 | 8 | [![GitHub stars](https://img.shields.io/github/stars/Bigkoo/Android-PickerView.svg?style=social)](https://github.com/Bigkoo/Android-PickerView/stargazers) [![GitHub forks](https://img.shields.io/github/forks/Bigkoo/Android-PickerView.svg?style=social)](https://github.com/Bigkoo/Android-PickerView/network) [![GitHub watchers](https://img.shields.io/github/watchers/Bigkoo/Android-PickerView.svg?style=social)](https://github.com/Bigkoo/Android-PickerView/watchers) 9 | 10 | ### [English Document](https://github.com/Bigkoo/Android-PickerView/blob/master/README-en.md) 11 | 12 | ### 注意事项、详请使用方式、更新日志等,请查看 [Wiki文档](https://github.com/Bigkoo/Android-PickerView/wiki) 13 | **Wiki文档,Wiki文档,Wiki文档 !~ 重要的事情说三遍** 14 | 15 | #### 对于使用上有任何疑问或优化建议等,欢迎加入QQ群讨论交流技术问题。 16 | 17 | 交流群1: 387051294(已满) 18 | 19 | 交流群2: 219962328(已满) 20 | 21 | ## 介绍 22 | 23 | 这是一款仿iOS的PickerView控件,有时间选择器和选项选择器,新版本的详细特性如下: 24 | 25 | ——TimePickerView 时间选择器,支持年月日时分,年月日,年月,时分等格式。 26 | ——OptionsPickerView 选项选择器,支持一,二,三级选项选择,并且可以设置是否联动 。 27 | 28 | * 支持三级联动 29 | * 设置是否联动 30 | * 设置循环模式 31 | * 支持自定义布局。 32 | * 支持item的分隔线设置。 33 | * 支持item间距设置。 34 | * 时间选择器支持起始和终止日期设定。 35 | * 支持“年,月,日,时,分,秒”,“省,市,区”等选项的单位(label)显示、隐藏和自定义。 36 | * 支持自定义文字、颜色、文字大小等属性 37 | * Item的文字长度过长时,文字会自适应缩放到Item的长度,避免显示不完全的问题 38 | * 支持Dialog 模式。 39 | * 支持自定义设置容器。 40 | * 实时回调。 41 | 42 | 43 | ![TimePicker.gif](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/timepicker.gif) 44 | ![TimePickerNight.gif](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/timepicker_night.gif) 45 | ![lunar.gif](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/lunar.gif) 46 | ![XOffset.png](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/Screen%20Shot%202017-11-09%20at%204.25.02%20PM.png) 47 | ![Province.gif](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/JsonData.gif) 48 | ![CustomLayout.gif](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/CustomLayout.gif) 49 | 50 | 51 | ### 有兴趣研究3D滚轮效果的实现机制,希望把源码研究透彻的可以看看这篇博客: 52 | ### [Android-PickerView系列之源码解析篇(二)](http://blog.csdn.net/qq_22393017/article/details/59488906) 53 | 54 | ### 使用注意事项 55 | * 注意:当我们进行设置时间的启始位置时,需要特别注意月份的设定 56 | * 原因:Calendar组件内部的月份,是从0开始的,即0-11代表1-12月份 57 | * 错误使用案例: 58 | startDate.set(2013,1,1); 59 |  endDate.set(2020,12,1); 60 | * 正确使用案例: 61 | startDate.set(2013,0,1); 62 |  endDate.set(2020,11,1); 63 | 64 | #### V4.1.9 版本更新说明(2019-10-20) 65 | - 修复: 农历 day 偶现越界的问题。 66 | - 优化: 显示布局中英文默认大写问题。 67 | - 新增: 最大可见项的数目提供API给开发者设置。(setItemVisibleCount()) 68 | - 新增: 滚轮从中间到两边透明度渐变,提供开关API设置。(isAlphaGradient(true)) 69 | - 新增: 选中项圆形分割线样式。(DividerType.CIRCLE) 70 | 71 | #### V4.1.8 版本更新说明(2019-4-24) 72 | - 更新gradle版本, wheelview基础库由 compile 改为 api 依赖,避免gradle 5.0+版本无法引入。 73 | - 修复 setTextXOffset 赋值问题。 74 | 75 | #### V4.1.7 版本更新说明(2019-1-10) 76 | - 修复 WheelView在初始化时,数据为空导致height=0,造成一直显示不出来的问题。 77 | - 新增取消按钮的点击事件监听入口。 78 | - 参数注解添加,规范数据类型。 79 | - 废弃setBackgroundId方法, 更新方法命名为 setOutSideColor。 80 | 81 | 82 | #### 更多历史版本详情,请查阅:[更新日志(4.x版本)](https://github.com/Bigkoo/Android-PickerView/wiki/更新日志(4.x版本)) 83 | 84 | #### 方法名与参数请查阅:[方法名与参数说明文档](https://github.com/Bigkoo/Android-PickerView/wiki/%E6%96%B9%E6%B3%95%E5%90%8D%E4%B8%8E%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E%EF%BC%883.x%E7%89%88%E6%9C%AC%EF%BC%89) 85 | 86 |
87 | 88 | ### **如何使用:** 89 | 90 | #### Android-PickerView 库使用示例: 91 | 92 | #### 1.添加Jcenter仓库 Gradle依赖: 93 | ```java 94 | compile 'com.contrarywind:Android-PickerView:4.1.9' 95 | ``` 96 | 或者 97 | 98 | #### Maven 99 | ``` 100 | 101 | com.contrarywind 102 | Android-PickerView 103 | 4.1.9 104 | pom 105 | 106 | ``` 107 | 108 | #### 2.在项目中添加如下代码: 109 | 110 | ```java 111 | //时间选择器 112 | TimePickerView pvTime = new TimePickerBuilder(MainActivity.this, new OnTimeSelectListener() { 113 | @Override 114 | public void onTimeSelect(Date date, View v) { 115 | Toast.makeText(MainActivity.this, getTime(date), Toast.LENGTH_SHORT).show(); 116 | } 117 | }).build(); 118 | ``` 119 | 120 | ```java 121 | //条件选择器 122 | OptionsPickerView pvOptions = new OptionsPickerBuilder(MainActivity.this, new OnOptionsSelectListener() { 123 | @Override 124 | public void onOptionsSelect(int options1, int option2, int options3 ,View v) { 125 | //返回的分别是三个级别的选中位置 126 | String tx = options1Items.get(options1).getPickerViewText() 127 | + options2Items.get(options1).get(option2) 128 | + options3Items.get(options1).get(option2).get(options3).getPickerViewText(); 129 | tvOptions.setText(tx); 130 | } 131 | }).build(); 132 | pvOptions.setPicker(options1Items, options2Items, options3Items); 133 | pvOptions.show(); 134 | ``` 135 | #### 大功告成~ 136 | 137 | #### 3.如果默认样式不符合你的口味,可以自定义各种属性: 138 | ```java 139 | Calendar selectedDate = Calendar.getInstance(); 140 | Calendar startDate = Calendar.getInstance(); 141 | //startDate.set(2013,1,1); 142 | Calendar endDate = Calendar.getInstance(); 143 | //endDate.set(2020,1,1); 144 | 145 | //正确设置方式 原因:注意事项有说明 146 |  startDate.set(2013,0,1); 147 |  endDate.set(2020,11,31); 148 | 149 | pvTime = new TimePickerBuilder(this, new OnTimeSelectListener() { 150 | @Override 151 | public void onTimeSelect(Date date,View v) {//选中事件回调 152 | tvTime.setText(getTime(date)); 153 | } 154 | }) 155 | .setType(new boolean[]{true, true, true, true, true, true})// 默认全部显示 156 | .setCancelText("Cancel")//取消按钮文字 157 | .setSubmitText("Sure")//确认按钮文字 158 | .setContentSize(18)//滚轮文字大小 159 | .setTitleSize(20)//标题文字大小 160 | .setTitleText("Title")//标题文字 161 | .setOutSideCancelable(false)//点击屏幕,点在控件外部范围时,是否取消显示 162 | .isCyclic(true)//是否循环滚动 163 | .setTitleColor(Color.BLACK)//标题文字颜色 164 | .setSubmitColor(Color.BLUE)//确定按钮文字颜色 165 | .setCancelColor(Color.BLUE)//取消按钮文字颜色 166 | .setTitleBgColor(0xFF666666)//标题背景颜色 Night mode 167 | .setBgColor(0xFF333333)//滚轮背景颜色 Night mode 168 | .setDate(selectedDate)// 如果不设置的话,默认是系统时间*/ 169 | .setRangDate(startDate,endDate)//起始终止年月日设定 170 | .setLabel("年","月","日","时","分","秒")//默认设置为年月日时分秒 171 | .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 172 | .isDialog(true)//是否显示为对话框样式 173 | .build(); 174 | ``` 175 | 176 | ```java 177 | pvOptions = new OptionsPickerBuilder(this, new OptionsPickerView.OnOptionsSelectListener() { 178 | @Override 179 | public void onOptionsSelect(int options1, int option2, int options3 ,View v) { 180 | //返回的分别是三个级别的选中位置 181 | String tx = options1Items.get(options1).getPickerViewText() 182 | + options2Items.get(options1).get(option2) 183 | + options3Items.get(options1).get(option2).get(options3).getPickerViewText(); 184 | tvOptions.setText(tx); 185 | } 186 | }) .setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() { 187 | @Override 188 | public void onOptionsSelectChanged(int options1, int options2, int options3) { 189 | String str = "options1: " + options1 + "\noptions2: " + options2 + "\noptions3: " + options3; 190 | Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); 191 | } 192 | }) 193 | .setSubmitText("确定")//确定按钮文字 194 | .setCancelText("取消")//取消按钮文字 195 | .setTitleText("城市选择")//标题 196 | .setSubCalSize(18)//确定和取消文字大小 197 | .setTitleSize(20)//标题文字大小 198 | .setTitleColor(Color.BLACK)//标题文字颜色 199 | .setSubmitColor(Color.BLUE)//确定按钮文字颜色 200 | .setCancelColor(Color.BLUE)//取消按钮文字颜色 201 | .setTitleBgColor(0xFF333333)//标题背景颜色 Night mode 202 | .setBgColor(0xFF000000)//滚轮背景颜色 Night mode 203 | .setContentTextSize(18)//滚轮文字大小 204 | .setLinkage(false)//设置是否联动,默认true 205 | .setLabels("省", "市", "区")//设置选择的三级单位 206 | .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 207 | .setCyclic(false, false, false)//循环与否 208 | .setSelectOptions(1, 1, 1) //设置默认选中项 209 | .setOutSideCancelable(false)//点击外部dismiss default true 210 | .isDialog(true)//是否显示为对话框样式 211 | .isRestoreItem(true)//切换时是否还原,设置默认选中第一项。 212 | .build(); 213 | 214 | pvOptions.setPicker(options1Items, options2Items, options3Items);//添加数据源 215 | ``` 216 | #### 4.如果需要自定义布局: 217 | 218 | ```java 219 | // 注意:自定义布局中,id为 optionspicker 或者 timepicker 的布局以及其子控件必须要有,否则会报空指针 220 | // 具体可参考demo 里面的两个自定义布局 221 | pvCustomOptions = new OptionsPickerBuilder(this, new OptionsPickerView.OnOptionsSelectListener() { 222 | @Override 223 | public void onOptionsSelect(int options1, int option2, int options3, View v) { 224 | //返回的分别是三个级别的选中位置 225 | String tx = cardItem.get(options1).getPickerViewText(); 226 | btn_CustomOptions.setText(tx); 227 | } 228 | }) 229 | .setLayoutRes(R.layout.pickerview_custom_options, new CustomListener() { 230 | @Override 231 | public void customLayout(View v) { 232 | //自定义布局中的控件初始化及事件处理 233 | final TextView tvSubmit = (TextView) v.findViewById(R.id.tv_finish); 234 | final TextView tvAdd = (TextView) v.findViewById(R.id.tv_add); 235 | ImageView ivCancel = (ImageView) v.findViewById(R.id.iv_cancel); 236 | tvSubmit.setOnClickListener(new View.OnClickListener() { 237 | @Override 238 | public void onClick(View v) { 239 | pvCustomOptions.returnData(tvSubmit); 240 | } 241 | }); 242 | ivCancel.setOnClickListener(new View.OnClickListener() { 243 | @Override 244 | public void onClick(View v) { 245 | pvCustomOptions.dismiss(); 246 | } 247 | }); 248 | 249 | tvAdd.setOnClickListener(new View.OnClickListener() { 250 | @Override 251 | public void onClick(View v) { 252 | getData(); 253 | pvCustomOptions.setPicker(cardItem); 254 | } 255 | }); 256 | 257 | } 258 | }) 259 | .build(); 260 | pvCustomOptions.setPicker(cardItem);//添加数据 261 | ``` 262 | 263 | #### 5.对使用还有疑问的话,可参考demo代码 264 | [请戳我查看demo代码](https://github.com/Bigkoo/Android-PickerView/blob/master/app/src/main/java/com/bigkoo/pickerviewdemo/MainActivity.java) 265 | 266 | 267 | 268 | #### 6.若只需要WheelView基础控件自行扩展实现逻辑,可直接添加基础控件库,Gradle 依赖: 269 | 270 | ```java 271 | compile 'com.contrarywind:wheelview:4.1.0' 272 | ``` 273 | 274 | #### WheelView 使用代码示例: 275 | 276 | xml布局: 277 | ```xml 278 | 282 | ``` 283 | 284 | Java 代码: 285 | ```java 286 | WheelView wheelView = findViewById(R.id.wheelview); 287 | 288 | wheelView.setCyclic(false); 289 | 290 | final List mOptionsItems = new ArrayList<>(); 291 | mOptionsItems.add("item0"); 292 | mOptionsItems.add("item1"); 293 | mOptionsItems.add("item2"); 294 | 295 | wheelView.setAdapter(new ArrayWheelAdapter(mOptionsItems)); 296 | wheelView.setOnItemSelectedListener(new OnItemSelectedListener() { 297 | @Override 298 | public void onItemSelected(int index) { 299 | Toast.makeText(MainActivity.this, "" + mOptionsItems.get(index), Toast.LENGTH_SHORT).show(); 300 | } 301 | }); 302 | ``` 303 | 304 | 305 | ### 效果图(招行信用卡的“掌上生活”里面条件选择器他们用的就是我这个库,大家可以当实际项目参考) 306 | ![](https://github.com/saiwu-bigkoo/Android-PickerView/blob/master/preview/pickerdemo_zhangshangshenghuo.gif) 307 | 308 | 309 | ### Thanks 310 | 311 | - WheelView 312 | - [androidWheelView](https://github.com/weidongjian/androidWheelView/) 313 | 314 | ## License 315 | 316 | ``` 317 | Copyright 2014 Bigkoo 318 | Licensed under the Apache License, Version 2.0 (the "License"); 319 | you may not use this file except in compliance with the License. 320 | You may obtain a copy of the License at 321 | 322 | http://www.apache.org/licenses/LICENSE-2.0 323 | 324 | Unless required by applicable law or agreed to in writing, software 325 | distributed under the License is distributed on an "AS IS" BASIS, 326 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 327 | See the License for the specific language governing permissions and 328 | limitations under the License. 329 | ``` 330 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | 6 | defaultConfig { 7 | applicationId "com.bigkoo.pickerviewdemo" 8 | minSdkVersion 14 9 | targetSdkVersion 26 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | lintOptions{ 20 | checkReleaseBuilds false 21 | abortOnError false 22 | } 23 | } 24 | 25 | dependencies { 26 | // compile fileTree(dir: 'libs', include: ['*.jar']) 27 | implementation project(':pickerview') 28 | // implementation 'com.contrarywind:Android-PickerView:4.1.9' 29 | // implementation 'com.contrarywind:wheelview:4.1.0' 30 | implementation 'com.android.support:appcompat-v7:26.1.0' 31 | implementation 'com.google.code.gson:gson:2.7' 32 | } 33 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/Sai/Documents/software/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/bigkoo/pickerviewdemo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.pickerviewdemo; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/pickerviewdemo/FragmentTestActivity.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.pickerviewdemo; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.FragmentManager; 7 | import android.support.v4.app.FragmentTransaction; 8 | import android.support.v7.app.AppCompatActivity; 9 | 10 | public class FragmentTestActivity extends AppCompatActivity { 11 | private FragmentManager mFragmentManager; 12 | 13 | @Override 14 | protected void onCreate(@Nullable Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_fragmenttest); 17 | mFragmentManager = getSupportFragmentManager(); 18 | FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction(); 19 | fragmentTransaction.replace(R.id.frame_activity_main, new TestFragment()); 20 | fragmentTransaction.commitAllowingStateLoss(); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/pickerviewdemo/GetJsonDataUtil.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.pickerviewdemo; 2 | 3 | import android.content.Context; 4 | import android.content.res.AssetManager; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | 10 | /** 11 | * <读取Json文件的工具类> 12 | * 13 | * @author: 小嵩 14 | * @date: 2017/3/16 16:22 15 | 16 | */ 17 | 18 | public class GetJsonDataUtil { 19 | 20 | 21 | public String getJson(Context context,String fileName) { 22 | 23 | StringBuilder stringBuilder = new StringBuilder(); 24 | try { 25 | AssetManager assetManager = context.getAssets(); 26 | BufferedReader bf = new BufferedReader(new InputStreamReader( 27 | assetManager.open(fileName))); 28 | String line; 29 | while ((line = bf.readLine()) != null) { 30 | stringBuilder.append(line); 31 | } 32 | } catch (IOException e) { 33 | e.printStackTrace(); 34 | } 35 | return stringBuilder.toString(); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/pickerviewdemo/JsonDataActivity.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.pickerviewdemo; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.os.Handler; 7 | import android.os.Message; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.view.View; 10 | import android.widget.Toast; 11 | 12 | import com.bigkoo.pickerview.builder.OptionsPickerBuilder; 13 | import com.bigkoo.pickerview.listener.OnOptionsSelectListener; 14 | import com.bigkoo.pickerview.view.OptionsPickerView; 15 | import com.bigkoo.pickerviewdemo.bean.JsonBean; 16 | import com.google.gson.Gson; 17 | 18 | import org.json.JSONArray; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | /** 24 | * 解析省市区数据示例 25 | * 26 | * @author 小嵩 27 | * @date 2017-3-16 28 | */ 29 | public class JsonDataActivity extends AppCompatActivity implements View.OnClickListener { 30 | 31 | 32 | private List options1Items = new ArrayList<>(); 33 | private ArrayList> options2Items = new ArrayList<>(); 34 | private ArrayList>> options3Items = new ArrayList<>(); 35 | private Thread thread; 36 | private static final int MSG_LOAD_DATA = 0x0001; 37 | private static final int MSG_LOAD_SUCCESS = 0x0002; 38 | private static final int MSG_LOAD_FAILED = 0x0003; 39 | 40 | private static boolean isLoaded = false; 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | setContentView(R.layout.activity_json_data); 46 | initView(); 47 | } 48 | 49 | @SuppressLint("HandlerLeak") 50 | private Handler mHandler = new Handler() { 51 | public void handleMessage(Message msg) { 52 | switch (msg.what) { 53 | case MSG_LOAD_DATA: 54 | if (thread == null) {//如果已创建就不再重新创建子线程了 55 | 56 | Toast.makeText(JsonDataActivity.this, "Begin Parse Data", Toast.LENGTH_SHORT).show(); 57 | thread = new Thread(new Runnable() { 58 | @Override 59 | public void run() { 60 | // 子线程中解析省市区数据 61 | initJsonData(); 62 | } 63 | }); 64 | thread.start(); 65 | } 66 | break; 67 | 68 | case MSG_LOAD_SUCCESS: 69 | Toast.makeText(JsonDataActivity.this, "Parse Succeed", Toast.LENGTH_SHORT).show(); 70 | isLoaded = true; 71 | break; 72 | 73 | case MSG_LOAD_FAILED: 74 | Toast.makeText(JsonDataActivity.this, "Parse Failed", Toast.LENGTH_SHORT).show(); 75 | break; 76 | } 77 | } 78 | }; 79 | 80 | private void initView() { 81 | findViewById(R.id.btn_data).setOnClickListener(this); 82 | findViewById(R.id.btn_show).setOnClickListener(this); 83 | } 84 | 85 | @Override 86 | public void onClick(View v) { 87 | switch (v.getId()) { 88 | case R.id.btn_data: 89 | mHandler.sendEmptyMessage(MSG_LOAD_DATA); 90 | break; 91 | case R.id.btn_show: 92 | if (isLoaded) { 93 | showPickerView(); 94 | } else { 95 | Toast.makeText(JsonDataActivity.this, "Please waiting until the data is parsed", Toast.LENGTH_SHORT).show(); 96 | } 97 | break; 98 | } 99 | } 100 | 101 | 102 | private void showPickerView() {// 弹出选择器 103 | 104 | OptionsPickerView pvOptions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() { 105 | @Override 106 | public void onOptionsSelect(int options1, int options2, int options3, View v) { 107 | //返回的分别是三个级别的选中位置 108 | String opt1tx = options1Items.size() > 0 ? 109 | options1Items.get(options1).getPickerViewText() : ""; 110 | 111 | String opt2tx = options2Items.size() > 0 112 | && options2Items.get(options1).size() > 0 ? 113 | options2Items.get(options1).get(options2) : ""; 114 | 115 | String opt3tx = options2Items.size() > 0 116 | && options3Items.get(options1).size() > 0 117 | && options3Items.get(options1).get(options2).size() > 0 ? 118 | options3Items.get(options1).get(options2).get(options3) : ""; 119 | 120 | String tx = opt1tx + opt2tx + opt3tx; 121 | Toast.makeText(JsonDataActivity.this, tx, Toast.LENGTH_SHORT).show(); 122 | } 123 | }) 124 | 125 | .setTitleText("城市选择") 126 | .setDividerColor(Color.BLACK) 127 | .setTextColorCenter(Color.BLACK) //设置选中项文字颜色 128 | .setContentTextSize(20) 129 | .build(); 130 | 131 | /*pvOptions.setPicker(options1Items);//一级选择器 132 | pvOptions.setPicker(options1Items, options2Items);//二级选择器*/ 133 | pvOptions.setPicker(options1Items, options2Items, options3Items);//三级选择器 134 | pvOptions.show(); 135 | } 136 | 137 | private void initJsonData() {//解析数据 138 | 139 | /** 140 | * 注意:assets 目录下的Json文件仅供参考,实际使用可自行替换文件 141 | * 关键逻辑在于循环体 142 | * 143 | * */ 144 | String JsonData = new GetJsonDataUtil().getJson(this, "province.json");//获取assets目录下的json文件数据 145 | 146 | ArrayList jsonBean = parseData(JsonData);//用Gson 转成实体 147 | 148 | /** 149 | * 添加省份数据 150 | * 151 | * 注意:如果是添加的JavaBean实体,则实体类需要实现 IPickerViewData 接口, 152 | * PickerView会通过getPickerViewText方法获取字符串显示出来。 153 | */ 154 | options1Items = jsonBean; 155 | 156 | for (int i = 0; i < jsonBean.size(); i++) {//遍历省份 157 | ArrayList cityList = new ArrayList<>();//该省的城市列表(第二级) 158 | ArrayList> province_AreaList = new ArrayList<>();//该省的所有地区列表(第三极) 159 | 160 | for (int c = 0; c < jsonBean.get(i).getCityList().size(); c++) {//遍历该省份的所有城市 161 | String cityName = jsonBean.get(i).getCityList().get(c).getName(); 162 | cityList.add(cityName);//添加城市 163 | ArrayList city_AreaList = new ArrayList<>();//该城市的所有地区列表 164 | 165 | //如果无地区数据,建议添加空字符串,防止数据为null 导致三个选项长度不匹配造成崩溃 166 | /*if (jsonBean.get(i).getCityList().get(c).getArea() == null 167 | || jsonBean.get(i).getCityList().get(c).getArea().size() == 0) { 168 | city_AreaList.add(""); 169 | } else { 170 | city_AreaList.addAll(jsonBean.get(i).getCityList().get(c).getArea()); 171 | }*/ 172 | city_AreaList.addAll(jsonBean.get(i).getCityList().get(c).getArea()); 173 | province_AreaList.add(city_AreaList);//添加该省所有地区数据 174 | } 175 | 176 | /** 177 | * 添加城市数据 178 | */ 179 | options2Items.add(cityList); 180 | 181 | /** 182 | * 添加地区数据 183 | */ 184 | options3Items.add(province_AreaList); 185 | } 186 | 187 | mHandler.sendEmptyMessage(MSG_LOAD_SUCCESS); 188 | 189 | } 190 | 191 | 192 | public ArrayList parseData(String result) {//Gson 解析 193 | ArrayList detail = new ArrayList<>(); 194 | try { 195 | JSONArray data = new JSONArray(result); 196 | Gson gson = new Gson(); 197 | for (int i = 0; i < data.length(); i++) { 198 | JsonBean entity = gson.fromJson(data.optJSONObject(i).toString(), JsonBean.class); 199 | detail.add(entity); 200 | } 201 | } catch (Exception e) { 202 | e.printStackTrace(); 203 | mHandler.sendEmptyMessage(MSG_LOAD_FAILED); 204 | } 205 | return detail; 206 | } 207 | 208 | 209 | @Override 210 | protected void onDestroy() { 211 | super.onDestroy(); 212 | if (mHandler != null) { 213 | mHandler.removeCallbacksAndMessages(null); 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/pickerviewdemo/TestCircleWheelViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.pickerviewdemo; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.widget.Toast; 7 | 8 | import com.bigkoo.pickerview.adapter.ArrayWheelAdapter; 9 | import com.contrarywind.listener.OnItemSelectedListener; 10 | import com.contrarywind.view.WheelView; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * desc: 17 | * author: Created by lixiaotong on 2019-07-30 18 | * e-mail: 516030811@qq.com 19 | */ 20 | public class TestCircleWheelViewActivity extends AppCompatActivity { 21 | 22 | @Override 23 | protected void onCreate(@Nullable Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_test_circle_wheelview); 26 | 27 | WheelView wheelView = findViewById(R.id.wheelview); 28 | wheelView.setTextSize(20); 29 | wheelView.setLineSpacingMultiplier(2f); 30 | // wheelView.setDividerWidth(6); 31 | wheelView.setDividerType(WheelView.DividerType.CIRCLE); 32 | 33 | final List mOptionsItems = new ArrayList<>(); 34 | mOptionsItems.add("10"); 35 | mOptionsItems.add("20"); 36 | mOptionsItems.add("30"); 37 | mOptionsItems.add("40"); 38 | mOptionsItems.add("50"); 39 | mOptionsItems.add("60"); 40 | mOptionsItems.add("70"); 41 | 42 | wheelView.setAdapter(new ArrayWheelAdapter(mOptionsItems)); 43 | wheelView.setOnItemSelectedListener(new OnItemSelectedListener() { 44 | @Override 45 | public void onItemSelected(int index) { 46 | Toast.makeText(TestCircleWheelViewActivity.this, "" + mOptionsItems.get(index), Toast.LENGTH_SHORT).show(); 47 | } 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/pickerviewdemo/TestFragment.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.pickerviewdemo; 2 | 3 | 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.Button; 12 | import android.widget.FrameLayout; 13 | import android.widget.ImageView; 14 | import android.widget.TextView; 15 | 16 | import com.bigkoo.pickerview.builder.TimePickerBuilder; 17 | import com.bigkoo.pickerview.listener.CustomListener; 18 | import com.bigkoo.pickerview.listener.OnTimeSelectListener; 19 | import com.bigkoo.pickerview.view.TimePickerView; 20 | 21 | import java.text.SimpleDateFormat; 22 | import java.util.Calendar; 23 | import java.util.Date; 24 | 25 | public class TestFragment extends Fragment implements View.OnClickListener { 26 | private View mView; 27 | private Button btnShow; 28 | private TimePickerView pvTime; 29 | private FrameLayout mFrameLayout; 30 | 31 | @Nullable 32 | @Override 33 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 34 | mView = inflater.inflate(R.layout.fragment_test, null); 35 | return mView; 36 | } 37 | 38 | 39 | @Override 40 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 41 | super.onActivityCreated(savedInstanceState); 42 | btnShow = (Button) mView.findViewById(R.id.btn_show); 43 | btnShow.setOnClickListener(this); 44 | mFrameLayout = (FrameLayout) mView.findViewById(R.id.fragmen_fragment); 45 | initTimePicker(); 46 | } 47 | 48 | private void initTimePicker() { 49 | //控制时间范围(如果不设置范围,则使用默认时间1900-2100年,此段代码可注释) 50 | //因为系统Calendar的月份是从0-11的,所以如果是调用Calendar的set方法来设置时间,月份的范围也要是从0-11 51 | Calendar selectedDate = Calendar.getInstance(); 52 | 53 | Calendar startDate = Calendar.getInstance(); 54 | startDate.set(2013, 0, 23); 55 | 56 | Calendar endDate = Calendar.getInstance(); 57 | endDate.set(2019, 11, 28); 58 | //时间选择器 59 | pvTime = new TimePickerBuilder(getActivity(), new OnTimeSelectListener() { 60 | @Override 61 | public void onTimeSelect(Date date, View v) {//选中事件回调 62 | // 这里回调过来的v,就是show()方法里面所添加的 View 参数,如果show的时候没有添加参数,v则为null 63 | /*btn_Time.setText(getTime(date));*/ 64 | Button btn = (Button) v; 65 | btn.setText(getTime(date)); 66 | } 67 | }) 68 | .setLayoutRes(R.layout.pickerview_custom_time, new CustomListener() { 69 | 70 | @Override 71 | public void customLayout(View v) { 72 | final TextView tvSubmit = (TextView) v.findViewById(R.id.tv_finish); 73 | ImageView ivCancel = (ImageView) v.findViewById(R.id.iv_cancel); 74 | tvSubmit.setOnClickListener(new View.OnClickListener() { 75 | @Override 76 | public void onClick(View v) { 77 | pvTime.returnData(); 78 | /*pvTime.dismiss();*/ 79 | } 80 | }); 81 | ivCancel.setOnClickListener(new View.OnClickListener() { 82 | @Override 83 | public void onClick(View v) { 84 | /*pvTime.dismiss();*/ 85 | } 86 | }); 87 | } 88 | }) 89 | .setType(new boolean[]{true, true, true, false, false, false}) 90 | .setLabel("", "", "", "", "", "") //设置空字符串以隐藏单位提示 hide label 91 | .setDividerColor(Color.DKGRAY) 92 | .setContentTextSize(20) 93 | .setDate(selectedDate) 94 | .setRangDate(startDate, selectedDate) 95 | .setDecorView(mFrameLayout)//非dialog模式下,设置ViewGroup, pickerView将会添加到这个ViewGroup中 96 | .setOutSideColor(0x00000000) 97 | .setOutSideCancelable(false) 98 | .build(); 99 | 100 | pvTime.setKeyBackCancelable(false);//系统返回键监听屏蔽掉 101 | } 102 | 103 | @Override 104 | public void onClick(View v) { 105 | pvTime.show(v, false);//弹出时间选择器,传递参数过去,回调的时候则可以绑定此view 106 | } 107 | 108 | private String getTime(Date date) {//可根据需要自行截取数据显示 109 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 110 | return format.format(date); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/pickerviewdemo/bean/CardBean.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.pickerviewdemo.bean; 2 | 3 | 4 | import com.contrarywind.interfaces.IPickerViewData; 5 | 6 | /** 7 | * Created by KyuYi on 2017/3/2. 8 | * E-Mail:kyu_yi@sina.com 9 | * 功能: 10 | */ 11 | 12 | public class CardBean implements IPickerViewData { 13 | int id; 14 | String cardNo; 15 | 16 | public CardBean(int id, String cardNo) { 17 | this.id = id; 18 | this.cardNo = cardNo; 19 | } 20 | 21 | public int getId() { 22 | return id; 23 | } 24 | 25 | public void setId(int id) { 26 | this.id = id; 27 | } 28 | 29 | public String getCardNo() { 30 | return cardNo; 31 | } 32 | 33 | public void setCardNo(String cardNo) { 34 | this.cardNo = cardNo; 35 | } 36 | 37 | @Override 38 | public String getPickerViewText() { 39 | return cardNo; 40 | } 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/pickerviewdemo/bean/JsonBean.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.pickerviewdemo.bean; 2 | 3 | 4 | import com.contrarywind.interfaces.IPickerViewData; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * TODO 10 | * 11 | * @author: 小嵩 12 | * @date: 2017/3/16 15:36 13 | */ 14 | 15 | public class JsonBean implements IPickerViewData { 16 | 17 | 18 | /** 19 | * name : 省份 20 | * city : [{"name":"北京市","area":["东城区","西城区","崇文区","宣武区","朝阳区"]}] 21 | */ 22 | 23 | private String name; 24 | private List city; 25 | 26 | public String getName() { 27 | return name; 28 | } 29 | 30 | public void setName(String name) { 31 | this.name = name; 32 | } 33 | 34 | public List getCityList() { 35 | return city; 36 | } 37 | 38 | public void setCityList(List city) { 39 | this.city = city; 40 | } 41 | 42 | // 实现 IPickerViewData 接口, 43 | // 这个用来显示在PickerView上面的字符串, 44 | // PickerView会通过IPickerViewData获取getPickerViewText方法显示出来。 45 | @Override 46 | public String getPickerViewText() { 47 | return this.name; 48 | } 49 | 50 | 51 | public static class CityBean { 52 | /** 53 | * name : 城市 54 | * area : ["东城区","西城区","崇文区","昌平区"] 55 | */ 56 | 57 | private String name; 58 | private List area; 59 | 60 | public String getName() { 61 | return name; 62 | } 63 | 64 | public void setName(String name) { 65 | this.name = name; 66 | } 67 | 68 | public List getArea() { 69 | return area; 70 | } 71 | 72 | public void setArea(List area) { 73 | this.area = area; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/pickerviewdemo/bean/ProvinceBean.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.pickerviewdemo.bean; 2 | 3 | 4 | import com.contrarywind.interfaces.IPickerViewData; 5 | 6 | /** 7 | * Created by Sai on 15/11/22. 8 | */ 9 | public class ProvinceBean implements IPickerViewData { 10 | private long id; 11 | private String name; 12 | private String description; 13 | private String others; 14 | 15 | public ProvinceBean(long id,String name,String description,String others){ 16 | this.id = id; 17 | this.name = name; 18 | this.description = description; 19 | this.others = others; 20 | } 21 | 22 | public long getId() { 23 | return id; 24 | } 25 | 26 | public void setId(long id) { 27 | this.id = id; 28 | } 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public void setName(String name) { 35 | this.name = name; 36 | } 37 | 38 | public String getDescription() { 39 | return description; 40 | } 41 | 42 | public void setDescription(String description) { 43 | this.description = description; 44 | } 45 | 46 | public String getOthers() { 47 | return others; 48 | } 49 | 50 | public void setOthers(String others) { 51 | this.others = others; 52 | } 53 | 54 | //这个用来显示在PickerView上面的字符串,PickerView会通过getPickerViewText方法获取字符串显示出来。 55 | @Override 56 | public String getPickerViewText() { 57 | return name; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bigkoo/Android-PickerView/e200d8c063aa2568d728854c048340ad2e4e0c0b/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bigkoo/Android-PickerView/e200d8c063aa2568d728854c048340ad2e4e0c0b/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bigkoo/Android-PickerView/e200d8c063aa2568d728854c048340ad2e4e0c0b/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/to_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bigkoo/Android-PickerView/e200d8c063aa2568d728854c048340ad2e4e0c0b/app/src/main/res/drawable-xhdpi/to_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bigkoo/Android-PickerView/e200d8c063aa2568d728854c048340ad2e4e0c0b/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_fragmenttest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_json_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 |