├── .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 ├── customHMS.jpeg ├── 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 | ## 基于`v4.1.9`支持自定义时分秒,实现时间范围、时间间隔效果 2 |
3 | 4 | ![](https://github.com/princekin-f/Android-PickerView/blob/master/preview/customHMS.jpeg) 5 | 6 | **实现上图效果仅需:** 7 | ``` 8 | .setHourList(new ArrayList<>(Arrays.asList(9, 10, 11, 12, 13, 14, 15, 16, 17, 18))) 9 | .setMinuteList(new ArrayList<>(Arrays.asList(0, 10, 20, 30, 40, 50))) 10 | ``` 11 | 12 | **总共添加了三个API:** 13 | ``` 14 | setHourList(List hourList) // 范围:0-23 15 | setMinuteList(List minuteList) // 范围:0-59 16 | setSecondList(List secondList) // 范围:0-59 17 | ``` 18 | ### 把原有地址换成下面的即可,其他内容一模一样: 19 | ``` 20 | compile 'com.github.princekin-f:Android-PickerView:0.0.1' 21 | ``` 22 | **以下是原文档,向大佬致敬!** 23 | 24 |
25 | 26 | --- 27 | 28 |
29 |
30 | 31 | 32 | ## Android-PickerView 33 | 34 | [![API](https://img.shields.io/badge/API-9%2B-brightgreen.svg)](https://android-arsenal.com/api?level=9) 35 | [![License](https://img.shields.io/badge/license-Apache%202-green.svg)](https://www.apache.org/licenses/LICENSE-2.0) 36 | [![Download](https://api.bintray.com/packages/contrarywind/maven/Android-PickerView/images/download.svg) ](https://bintray.com/contrarywind/maven/Android-PickerView/_latestVersion) 37 | 38 | [![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) 39 | 40 | ### [English Document](https://github.com/Bigkoo/Android-PickerView/blob/master/README-en.md) 41 | 42 | ### 注意事项、详请使用方式、更新日志等,请查看 [Wiki文档](https://github.com/Bigkoo/Android-PickerView/wiki) 43 | **Wiki文档,Wiki文档,Wiki文档 !~ 重要的事情说三遍** 44 | 45 | #### 对于使用上有任何疑问或优化建议等,欢迎加入QQ群讨论交流技术问题。 46 | 47 | 交流群1: 387051294(推荐) 48 | 49 | 交流群2: 219962328(已满) 50 | 51 | ## 介绍 52 | 53 | 这是一款仿iOS的PickerView控件,有时间选择器和选项选择器,新版本的详细特性如下: 54 | 55 | ——TimePickerView 时间选择器,支持年月日时分,年月日,年月,时分等格式。 56 | ——OptionsPickerView 选项选择器,支持一,二,三级选项选择,并且可以设置是否联动 。 57 | 58 | * 支持三级联动 59 | * 设置是否联动 60 | * 设置循环模式 61 | * 支持自定义布局。 62 | * 支持item的分隔线设置。 63 | * 支持item间距设置。 64 | * 时间选择器支持起始和终止日期设定。 65 | * 支持“年,月,日,时,分,秒”,“省,市,区”等选项的单位(label)显示、隐藏和自定义。 66 | * 支持自定义文字、颜色、文字大小等属性 67 | * Item的文字长度过长时,文字会自适应缩放到Item的长度,避免显示不完全的问题 68 | * 支持Dialog 模式。 69 | * 支持自定义设置容器。 70 | * 实时回调。 71 | 72 | 73 | ![TimePicker.gif](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/timepicker.gif) 74 | ![TimePickerNight.gif](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/timepicker_night.gif) 75 | ![lunar.gif](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/lunar.gif) 76 | ![XOffset.png](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/Screen%20Shot%202017-11-09%20at%204.25.02%20PM.png) 77 | ![Province.gif](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/JsonData.gif) 78 | ![CustomLayout.gif](https://github.com/Bigkoo/Android-PickerView/blob/master/preview/CustomLayout.gif) 79 | 80 | 81 | ### 有兴趣研究3D滚轮效果的实现机制,希望把源码研究透彻的可以看看这篇博客: 82 | ### [Android-PickerView系列之源码解析篇(二)](http://blog.csdn.net/qq_22393017/article/details/59488906) 83 | 84 | ### 使用注意事项 85 | * 注意:当我们进行设置时间的启始位置时,需要特别注意月份的设定 86 | * 原因:Calendar组件内部的月份,是从0开始的,即0-11代表1-12月份 87 | * 错误使用案例: 88 | startDate.set(2013,1,1); 89 |  endDate.set(2020,12,1); 90 | * 正确使用案例: 91 | startDate.set(2013,0,1); 92 |  endDate.set(2020,11,1); 93 | 94 | #### V4.1.9 版本更新说明(2019-10-20) 95 | - 修复: 农历 day 偶现越界的问题。 96 | - 优化: 显示布局中英文默认大写问题。 97 | - 新增: 最大可见项的数目提供API给开发者设置。(setItemVisibleCount()) 98 | - 新增: 滚轮从中间到两边透明度渐变,提供开关API设置。(isAlphaGradient(true)) 99 | - 新增: 选中项圆形分割线样式。(DividerType.CIRCLE) 100 | 101 | #### V4.1.8 版本更新说明(2019-4-24) 102 | - 更新gradle版本, wheelview基础库由 compile 改为 api 依赖,避免gradle 5.0+版本无法引入。 103 | - 修复 setTextXOffset 赋值问题。 104 | 105 | #### V4.1.7 版本更新说明(2019-1-10) 106 | - 修复 WheelView在初始化时,数据为空导致height=0,造成一直显示不出来的问题。 107 | - 新增取消按钮的点击事件监听入口。 108 | - 参数注解添加,规范数据类型。 109 | - 废弃setBackgroundId方法, 更新方法命名为 setOutSideColor。 110 | 111 | 112 | #### 更多历史版本详情,请查阅:[更新日志(4.x版本)](https://github.com/Bigkoo/Android-PickerView/wiki/更新日志(4.x版本)) 113 | 114 | #### 方法名与参数请查阅:[方法名与参数说明文档](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) 115 | 116 |
117 | 118 | ### **如何使用:** 119 | 120 | #### Android-PickerView 库使用示例: 121 | 122 | #### 1.添加Jcenter仓库 Gradle依赖: 123 | ```java 124 | compile 'com.contrarywind:Android-PickerView:4.1.9' 125 | ``` 126 | 或者 127 | 128 | #### Maven 129 | ``` 130 | 131 | com.contrarywind 132 | Android-PickerView 133 | 4.1.9 134 | pom 135 | 136 | ``` 137 | 138 | #### 2.在项目中添加如下代码: 139 | 140 | ```java 141 | //时间选择器 142 | TimePickerView pvTime = new TimePickerBuilder(MainActivity.this, new OnTimeSelectListener() { 143 | @Override 144 | public void onTimeSelect(Date date, View v) { 145 | Toast.makeText(MainActivity.this, getTime(date), Toast.LENGTH_SHORT).show(); 146 | } 147 | }).build(); 148 | ``` 149 | 150 | ```java 151 | //条件选择器 152 | OptionsPickerView pvOptions = new OptionsPickerBuilder(MainActivity.this, new OnOptionsSelectListener() { 153 | @Override 154 | public void onOptionsSelect(int options1, int option2, int options3 ,View v) { 155 | //返回的分别是三个级别的选中位置 156 | String tx = options1Items.get(options1).getPickerViewText() 157 | + options2Items.get(options1).get(option2) 158 | + options3Items.get(options1).get(option2).get(options3).getPickerViewText(); 159 | tvOptions.setText(tx); 160 | } 161 | }).build(); 162 | pvOptions.setPicker(options1Items, options2Items, options3Items); 163 | pvOptions.show(); 164 | ``` 165 | #### 大功告成~ 166 | 167 | #### 3.如果默认样式不符合你的口味,可以自定义各种属性: 168 | ```java 169 | Calendar selectedDate = Calendar.getInstance(); 170 | Calendar startDate = Calendar.getInstance(); 171 | //startDate.set(2013,1,1); 172 | Calendar endDate = Calendar.getInstance(); 173 | //endDate.set(2020,1,1); 174 | 175 | //正确设置方式 原因:注意事项有说明 176 |  startDate.set(2013,0,1); 177 |  endDate.set(2020,11,31); 178 | 179 | pvTime = new TimePickerBuilder(this, new OnTimeSelectListener() { 180 | @Override 181 | public void onTimeSelect(Date date,View v) {//选中事件回调 182 | tvTime.setText(getTime(date)); 183 | } 184 | }) 185 | .setType(new boolean[]{true, true, true, true, true, true})// 默认全部显示 186 | .setCancelText("Cancel")//取消按钮文字 187 | .setSubmitText("Sure")//确认按钮文字 188 | .setContentSize(18)//滚轮文字大小 189 | .setTitleSize(20)//标题文字大小 190 | .setTitleText("Title")//标题文字 191 | .setOutSideCancelable(false)//点击屏幕,点在控件外部范围时,是否取消显示 192 | .isCyclic(true)//是否循环滚动 193 | .setTitleColor(Color.BLACK)//标题文字颜色 194 | .setSubmitColor(Color.BLUE)//确定按钮文字颜色 195 | .setCancelColor(Color.BLUE)//取消按钮文字颜色 196 | .setTitleBgColor(0xFF666666)//标题背景颜色 Night mode 197 | .setBgColor(0xFF333333)//滚轮背景颜色 Night mode 198 | .setDate(selectedDate)// 如果不设置的话,默认是系统时间*/ 199 | .setRangDate(startDate,endDate)//起始终止年月日设定 200 | .setLabel("年","月","日","时","分","秒")//默认设置为年月日时分秒 201 | .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 202 | .isDialog(true)//是否显示为对话框样式 203 | .build(); 204 | ``` 205 | 206 | ```java 207 | pvOptions = new OptionsPickerBuilder(this, new OptionsPickerView.OnOptionsSelectListener() { 208 | @Override 209 | public void onOptionsSelect(int options1, int option2, int options3 ,View v) { 210 | //返回的分别是三个级别的选中位置 211 | String tx = options1Items.get(options1).getPickerViewText() 212 | + options2Items.get(options1).get(option2) 213 | + options3Items.get(options1).get(option2).get(options3).getPickerViewText(); 214 | tvOptions.setText(tx); 215 | } 216 | }) .setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() { 217 | @Override 218 | public void onOptionsSelectChanged(int options1, int options2, int options3) { 219 | String str = "options1: " + options1 + "\noptions2: " + options2 + "\noptions3: " + options3; 220 | Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); 221 | } 222 | }) 223 | .setSubmitText("确定")//确定按钮文字 224 | .setCancelText("取消")//取消按钮文字 225 | .setTitleText("城市选择")//标题 226 | .setSubCalSize(18)//确定和取消文字大小 227 | .setTitleSize(20)//标题文字大小 228 | .setTitleColor(Color.BLACK)//标题文字颜色 229 | .setSubmitColor(Color.BLUE)//确定按钮文字颜色 230 | .setCancelColor(Color.BLUE)//取消按钮文字颜色 231 | .setTitleBgColor(0xFF333333)//标题背景颜色 Night mode 232 | .setBgColor(0xFF000000)//滚轮背景颜色 Night mode 233 | .setContentTextSize(18)//滚轮文字大小 234 | .setLinkage(false)//设置是否联动,默认true 235 | .setLabels("省", "市", "区")//设置选择的三级单位 236 | .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 237 | .setCyclic(false, false, false)//循环与否 238 | .setSelectOptions(1, 1, 1) //设置默认选中项 239 | .setOutSideCancelable(false)//点击外部dismiss default true 240 | .isDialog(true)//是否显示为对话框样式 241 | .isRestoreItem(true)//切换时是否还原,设置默认选中第一项。 242 | .build(); 243 | 244 | pvOptions.setPicker(options1Items, options2Items, options3Items);//添加数据源 245 | ``` 246 | #### 4.如果需要自定义布局: 247 | 248 | ```java 249 | // 注意:自定义布局中,id为 optionspicker 或者 timepicker 的布局以及其子控件必须要有,否则会报空指针 250 | // 具体可参考demo 里面的两个自定义布局 251 | pvCustomOptions = new OptionsPickerBuilder(this, new OptionsPickerView.OnOptionsSelectListener() { 252 | @Override 253 | public void onOptionsSelect(int options1, int option2, int options3, View v) { 254 | //返回的分别是三个级别的选中位置 255 | String tx = cardItem.get(options1).getPickerViewText(); 256 | btn_CustomOptions.setText(tx); 257 | } 258 | }) 259 | .setLayoutRes(R.layout.pickerview_custom_options, new CustomListener() { 260 | @Override 261 | public void customLayout(View v) { 262 | //自定义布局中的控件初始化及事件处理 263 | final TextView tvSubmit = (TextView) v.findViewById(R.id.tv_finish); 264 | final TextView tvAdd = (TextView) v.findViewById(R.id.tv_add); 265 | ImageView ivCancel = (ImageView) v.findViewById(R.id.iv_cancel); 266 | tvSubmit.setOnClickListener(new View.OnClickListener() { 267 | @Override 268 | public void onClick(View v) { 269 | pvCustomOptions.returnData(tvSubmit); 270 | } 271 | }); 272 | ivCancel.setOnClickListener(new View.OnClickListener() { 273 | @Override 274 | public void onClick(View v) { 275 | pvCustomOptions.dismiss(); 276 | } 277 | }); 278 | 279 | tvAdd.setOnClickListener(new View.OnClickListener() { 280 | @Override 281 | public void onClick(View v) { 282 | getData(); 283 | pvCustomOptions.setPicker(cardItem); 284 | } 285 | }); 286 | 287 | } 288 | }) 289 | .build(); 290 | pvCustomOptions.setPicker(cardItem);//添加数据 291 | ``` 292 | 293 | #### 5.对使用还有疑问的话,可参考demo代码 294 | [请戳我查看demo代码](https://github.com/Bigkoo/Android-PickerView/blob/master/app/src/main/java/com/bigkoo/pickerviewdemo/MainActivity.java) 295 | 296 | 297 | 298 | #### 6.若只需要WheelView基础控件自行扩展实现逻辑,可直接添加基础控件库,Gradle 依赖: 299 | 300 | ```java 301 | compile 'com.contrarywind:wheelview:4.1.0' 302 | ``` 303 | 304 | #### WheelView 使用代码示例: 305 | 306 | xml布局: 307 | ```xml 308 | 312 | ``` 313 | 314 | Java 代码: 315 | ```java 316 | WheelView wheelView = findViewById(R.id.wheelview); 317 | 318 | wheelView.setCyclic(false); 319 | 320 | final List mOptionsItems = new ArrayList<>(); 321 | mOptionsItems.add("item0"); 322 | mOptionsItems.add("item1"); 323 | mOptionsItems.add("item2"); 324 | 325 | wheelView.setAdapter(new ArrayWheelAdapter(mOptionsItems)); 326 | wheelView.setOnItemSelectedListener(new OnItemSelectedListener() { 327 | @Override 328 | public void onItemSelected(int index) { 329 | Toast.makeText(MainActivity.this, "" + mOptionsItems.get(index), Toast.LENGTH_SHORT).show(); 330 | } 331 | }); 332 | ``` 333 | 334 | 335 | ### 效果图(招行信用卡的“掌上生活”里面条件选择器他们用的就是我这个库,大家可以当实际项目参考) 336 | ![](https://github.com/saiwu-bigkoo/Android-PickerView/blob/master/preview/pickerdemo_zhangshangshenghuo.gif) 337 | 338 | 339 | ### Thanks 340 | 341 | - WheelView 342 | - [androidWheelView](https://github.com/weidongjian/androidWheelView/) 343 | 344 | ## License 345 | 346 | ``` 347 | Copyright 2014 Bigkoo 348 | Licensed under the Apache License, Version 2.0 (the "License"); 349 | you may not use this file except in compliance with the License. 350 | You may obtain a copy of the License at 351 | 352 | http://www.apache.org/licenses/LICENSE-2.0 353 | 354 | Unless required by applicable law or agreed to in writing, software 355 | distributed under the License is distributed on an "AS IS" BASIS, 356 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 357 | See the License for the specific language governing permissions and 358 | limitations under the License. 359 | ``` 360 | -------------------------------------------------------------------------------- /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/princekin-f/Android-PickerView/fa8839401072af247c42856640f7c52b6a662d04/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/princekin-f/Android-PickerView/fa8839401072af247c42856640f7c52b6a662d04/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/princekin-f/Android-PickerView/fa8839401072af247c42856640f7c52b6a662d04/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/to_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/princekin-f/Android-PickerView/fa8839401072af247c42856640f7c52b6a662d04/app/src/main/res/drawable-xhdpi/to_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/princekin-f/Android-PickerView/fa8839401072af247c42856640f7c52b6a662d04/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 |