├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── bigkoo
│ │ └── pickerviewdemo
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── bigkoo
│ │ └── pickerviewdemo
│ │ ├── DataModel.java
│ │ ├── Util.java
│ │ ├── activity
│ │ ├── MainActivity.java
│ │ └── TestActivity.java
│ │ └── bean
│ │ ├── ProvinceBean.java
│ │ └── TypeBean.java
│ └── res
│ ├── drawable-hdpi
│ └── ic_launcher.png
│ ├── drawable-mdpi
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ └── ic_launcher.png
│ ├── layout
│ ├── activity_main.xml
│ ├── activity_test.xml
│ ├── activity_wheelview_test.xml
│ └── layout_bottom_wheel_option.xml
│ ├── menu
│ └── menu_main.xml
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── 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
│ │ └── lvfq
│ │ └── pickerview
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── lvfq
│ │ └── pickerview
│ │ ├── OptionsPickerView.java
│ │ ├── TimePickerView.java
│ │ ├── adapter
│ │ ├── ArrayWheelAdapter.java
│ │ ├── NumericWheelAdapter.java
│ │ └── WheelAdapter.java
│ │ ├── lib
│ │ ├── InertiaTimerTask.java
│ │ ├── LoopViewGestureListener.java
│ │ ├── MessageHandler.java
│ │ ├── OnItemSelectedRunnable.java
│ │ ├── SmoothScrollTimerTask.java
│ │ └── WheelView.java
│ │ ├── listener
│ │ ├── OnDismissListener.java
│ │ └── OnItemSelectedListener.java
│ │ ├── utils
│ │ └── PickerViewAnimateUtil.java
│ │ └── view
│ │ ├── BasePickerView.java
│ │ ├── WheelOptions.java
│ │ └── WheelTime.java
│ └── res
│ ├── anim
│ ├── slide_in_bottom.xml
│ └── slide_out_bottom.xml
│ ├── drawable
│ └── selector_pickerview_btn.xml
│ ├── layout
│ ├── include_pickerview_topbar.xml
│ ├── layout_basepickerview.xml
│ ├── pickerview_options.xml
│ └── pickerview_time.xml
│ └── values
│ ├── attrs.xml
│ ├── bools.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── integers.xml
│ └── strings.xml
├── preview
├── pickerdemo.gif
├── pickerdemo1x.gif
├── pickerdemo_zhangshangshenghuo.gif
└── update_picker_demo.gif
└── settings.gradle
/.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
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 源码来自于:https://github.com/saiwu-bigkoo/Android-PickerView
2 |
3 | 站着巨人的肩膀上,做了一些调整 , 调整后效果图
4 |
5 | 
6 |
7 | 博客地址:http://blog.csdn.net/lv_fq/article/details/52338513
8 |
9 | Demo 下载之后把 pickerview 作为 Module 引入到项目中,
10 |
11 | 添加工具类:
12 | ```
13 | public class Util {
14 |
15 | /**
16 | * 时间选择回调
17 | */
18 | public interface TimerPickerCallBack {
19 | void onTimeSelect(String date);
20 | }
21 |
22 | /**
23 | * 弹出时间选择
24 | *
25 | * @param context
26 | * @param type TimerPickerView 中定义的 选择时间类型
27 | * @param format 时间格式化
28 | * @param callBack 时间选择回调
29 | */
30 | public static void alertTimerPicker(Context context, TimePickerView.Type type, final String format, final TimerPickerCallBack callBack) {
31 | TimePickerView pvTime = new TimePickerView(context, type);
32 | //控制时间范围
33 | // Calendar calendar = Calendar.getInstance();
34 | // pvTime.setRange(calendar.get(Calendar.YEAR) - 20, calendar.get(Calendar.YEAR));
35 | pvTime.setTime(new Date());
36 | pvTime.setCyclic(false);
37 | pvTime.setCancelable(true);
38 | //时间选择后回调
39 | pvTime.setOnTimeSelectListener(new TimePickerView.OnTimeSelectListener() {
40 |
41 | @Override
42 | public void onTimeSelect(Date date) {
43 | // tvTime.setText(getTime(date));
44 | SimpleDateFormat sdf = new SimpleDateFormat(format);
45 | callBack.onTimeSelect(sdf.format(date));
46 | }
47 | });
48 | pvTime.setTextSize(16);
49 | //弹出时间选择器
50 | pvTime.show();
51 | }
52 |
53 |
54 | /**
55 | * 底部滚轮点击事件回调
56 | */
57 | public interface OnWheelViewClick {
58 | void onClick(View view, int postion);
59 | }
60 |
61 | /**
62 | * 弹出底部滚轮选择
63 | *
64 | * @param context
65 | * @param list
66 | * @param click
67 | */
68 | public static void alertBottomWheelOption(Context context, ArrayList> list, final OnWheelViewClick click) {
69 |
70 | final PopupWindow popupWindow = new PopupWindow();
71 |
72 | View view = LayoutInflater.from(context).inflate(R.layout.layout_bottom_wheel_option, null);
73 | TextView tv_confirm = (TextView) view.findViewById(R.id.btnSubmit);
74 | final WheelView wv_option = (WheelView) view.findViewById(R.id.wv_option);
75 | wv_option.setAdapter(new ArrayWheelAdapter(list));
76 | wv_option.setCyclic(false);
77 | wv_option.setTextSize(16);
78 | tv_confirm.setOnClickListener(new View.OnClickListener() {
79 | @Override
80 | public void onClick(View view) {
81 | popupWindow.dismiss();
82 | click.onClick(view, wv_option.getCurrentItem());
83 | }
84 | });
85 |
86 | view.findViewById(R.id.btnCancel).setOnClickListener(new View.OnClickListener() {
87 | @Override
88 | public void onClick(View view) {
89 | // TODO: 2016/8/11 0011 取消
90 | popupWindow.dismiss();
91 | }
92 | });
93 | view.setOnTouchListener(new View.OnTouchListener() {
94 | @Override
95 | public boolean onTouch(View view, MotionEvent motionEvent) {
96 | int top = view.findViewById(R.id.ll_container).getTop();
97 | if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
98 | int y = (int) motionEvent.getY();
99 | if (y < top) {
100 | popupWindow.dismiss();
101 | }
102 | }
103 | return true;
104 | }
105 | });
106 | popupWindow.setContentView(view);
107 | popupWindow.setOutsideTouchable(true);
108 | popupWindow.setFocusable(true);
109 | popupWindow.setBackgroundDrawable(new BitmapDrawable());
110 | popupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
111 | popupWindow.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
112 | popupWindow.showAtLocation(((ViewGroup) ((Activity) context).findViewById(android.R.id.content)).getChildAt(0), Gravity.CENTER, 0, 0);
113 | }
114 | ```
115 | 具体调用方法请参考 Demo。
116 |
117 | 此外,后面把该项目中的 底部弹出效果做了一下整理,详情参考 http://blog.csdn.net/lv_fq/article/details/53154026
118 |
119 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "22.0.0"
6 |
7 | defaultConfig {
8 | applicationId "com.lvfq.pickerviewdemo"
9 | minSdkVersion 14
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | compile project(':pickerview')
25 | // compile 'com.bigkoo:pickerview:2.0.8'
26 | compile 'com.android.support:appcompat-v7:23.1.0'
27 | }
28 |
--------------------------------------------------------------------------------
/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 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/bigkoo/pickerviewdemo/DataModel.java:
--------------------------------------------------------------------------------
1 | package com.bigkoo.pickerviewdemo;
2 |
3 | import com.bigkoo.pickerviewdemo.bean.ProvinceBean;
4 |
5 | import java.util.ArrayList;
6 |
7 | /**
8 | * --------------------------------------------
9 | * auther : Lvfq
10 | * 2016/8/27 16:01
11 | * description :
12 | * -------------------------------------------
13 | **/
14 | public class DataModel {
15 |
16 | /**
17 | * 初始化三个选项卡数据。
18 | *
19 | * @param options1Items
20 | * @param options2Items
21 | * @param options3Items
22 | */
23 | public static void initData(ArrayList options1Items, ArrayList> options2Items, ArrayList>> options3Items) {
24 |
25 | //选项1
26 | options1Items.add(new ProvinceBean(0, "广东", "广东省,以岭南东道、广南东路得名", "其他数据"));
27 | options1Items.add(new ProvinceBean(1, "湖南", "湖南省地处中国中部、长江中游,因大部分区域处于洞庭湖以南而得名湖南", "芒果TV"));
28 | options1Items.add(new ProvinceBean(3, "广西", "嗯~~", ""));
29 |
30 | //选项2
31 | ArrayList options2Items_01 = new ArrayList();
32 | options2Items_01.add("广州");
33 | options2Items_01.add("佛山");
34 | options2Items_01.add("东莞");
35 | options2Items_01.add("阳江");
36 | options2Items_01.add("珠海");
37 | ArrayList options2Items_02 = new ArrayList();
38 | options2Items_02.add("长沙");
39 | options2Items_02.add("岳阳");
40 | ArrayList options2Items_03 = new ArrayList();
41 | options2Items_03.add("桂林");
42 | options2Items.add(options2Items_01);
43 | options2Items.add(options2Items_02);
44 | options2Items.add(options2Items_03);
45 |
46 | //选项3
47 | ArrayList> options3Items_01 = new ArrayList>();
48 | ArrayList> options3Items_02 = new ArrayList>();
49 | ArrayList> options3Items_03 = new ArrayList>();
50 | ArrayList options3Items_01_01 = new ArrayList();
51 | options3Items_01_01.add("白云");
52 | options3Items_01_01.add("天河");
53 | options3Items_01_01.add("海珠");
54 | options3Items_01_01.add("越秀");
55 | options3Items_01.add(options3Items_01_01);
56 | ArrayList options3Items_01_02 = new ArrayList();
57 | options3Items_01_02.add("南海");
58 | options3Items_01_02.add("高明");
59 | options3Items_01_02.add("顺德");
60 | options3Items_01_02.add("禅城");
61 | options3Items_01.add(options3Items_01_02);
62 | ArrayList options3Items_01_03 = new ArrayList();
63 | options3Items_01_03.add("其他");
64 | options3Items_01_03.add("常平");
65 | options3Items_01_03.add("虎门");
66 | options3Items_01.add(options3Items_01_03);
67 | ArrayList options3Items_01_04 = new ArrayList();
68 | options3Items_01_04.add("其他1");
69 | options3Items_01_04.add("其他2");
70 | options3Items_01_04.add("其他3");
71 | options3Items_01.add(options3Items_01_04);
72 | ArrayList options3Items_01_05 = new ArrayList();
73 | options3Items_01_05.add("其他1");
74 | options3Items_01_05.add("其他2");
75 | options3Items_01_05.add("其他3");
76 | options3Items_01.add(options3Items_01_05);
77 |
78 | ArrayList options3Items_02_01 = new ArrayList();
79 | options3Items_02_01.add("长沙长沙长沙长沙长沙长沙长沙长沙长沙1111111111");
80 | options3Items_02_01.add("长沙2");
81 | options3Items_02_01.add("长沙3");
82 | options3Items_02_01.add("长沙4");
83 | options3Items_02_01.add("长沙5");
84 | options3Items_02_01.add("长沙6");
85 | options3Items_02_01.add("长沙7");
86 | options3Items_02_01.add("长沙8");
87 | options3Items_02.add(options3Items_02_01);
88 | ArrayList options3Items_02_02 = new ArrayList();
89 | options3Items_02_02.add("岳1");
90 | options3Items_02_02.add("岳2");
91 | options3Items_02_02.add("岳3");
92 | options3Items_02_02.add("岳4");
93 | options3Items_02_02.add("岳5");
94 | options3Items_02_02.add("岳6");
95 | options3Items_02_02.add("岳7");
96 | options3Items_02_02.add("岳8");
97 | options3Items_02_02.add("岳9");
98 | options3Items_02.add(options3Items_02_02);
99 | ArrayList options3Items_03_01 = new ArrayList();
100 | options3Items_03_01.add("好山水");
101 | options3Items_03.add(options3Items_03_01);
102 |
103 | options3Items.add(options3Items_01);
104 | options3Items.add(options3Items_02);
105 | options3Items.add(options3Items_03);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/app/src/main/java/com/bigkoo/pickerviewdemo/Util.java:
--------------------------------------------------------------------------------
1 | package com.bigkoo.pickerviewdemo;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.drawable.BitmapDrawable;
6 | import android.view.Gravity;
7 | import android.view.LayoutInflater;
8 | import android.view.MotionEvent;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.PopupWindow;
12 | import android.widget.TextView;
13 |
14 | import com.lvfq.pickerview.TimePickerView;
15 | import com.lvfq.pickerview.adapter.ArrayWheelAdapter;
16 | import com.lvfq.pickerview.lib.WheelView;
17 |
18 | import java.text.SimpleDateFormat;
19 | import java.util.ArrayList;
20 | import java.util.Date;
21 |
22 | /**
23 | * --------------------------------------------
24 | * Create By : Lvfq
25 | * Date : 2016/8/25 0025 下午 5:50
26 | * -------------------------------------------
27 | **/
28 | public class Util {
29 |
30 | /**
31 | * 时间选择回调
32 | */
33 | public interface TimerPickerCallBack {
34 | void onTimeSelect(String date);
35 | }
36 |
37 | /**
38 | * 弹出时间选择
39 | *
40 | * @param context
41 | * @param type TimerPickerView 中定义的 选择时间类型
42 | * @param format 时间格式化
43 | * @param callBack 时间选择回调
44 | */
45 | public static void alertTimerPicker(Context context, TimePickerView.Type type, final String format, final TimerPickerCallBack callBack) {
46 | TimePickerView pvTime = new TimePickerView(context, type);
47 | //控制时间范围
48 | // Calendar calendar = Calendar.getInstance();
49 | // pvTime.setRange(calendar.get(Calendar.YEAR) - 20, calendar.get(Calendar.YEAR));
50 | pvTime.setTime(new Date());
51 | pvTime.setCyclic(false);
52 | pvTime.setCancelable(true);
53 | //时间选择后回调
54 | pvTime.setOnTimeSelectListener(new TimePickerView.OnTimeSelectListener() {
55 |
56 | @Override
57 | public void onTimeSelect(Date date) {
58 | // tvTime.setText(getTime(date));
59 | SimpleDateFormat sdf = new SimpleDateFormat(format);
60 | callBack.onTimeSelect(sdf.format(date));
61 | }
62 | });
63 | pvTime.setTextSize(16);
64 | //弹出时间选择器
65 | pvTime.show();
66 | }
67 |
68 |
69 | /**
70 | * 底部滚轮点击事件回调
71 | */
72 | public interface OnWheelViewClick {
73 | void onClick(View view, int postion);
74 | }
75 |
76 | /**
77 | * 弹出底部滚轮选择
78 | *
79 | * @param context
80 | * @param list
81 | * @param click
82 | */
83 | public static void alertBottomWheelOption(Context context, ArrayList> list, final OnWheelViewClick click) {
84 |
85 | final PopupWindow popupWindow = new PopupWindow();
86 |
87 | View view = LayoutInflater.from(context).inflate(R.layout.layout_bottom_wheel_option, null);
88 | TextView tv_confirm = (TextView) view.findViewById(R.id.btnSubmit);
89 | final WheelView wv_option = (WheelView) view.findViewById(R.id.wv_option);
90 | wv_option.setAdapter(new ArrayWheelAdapter(list));
91 | wv_option.setCyclic(false);
92 | wv_option.setTextSize(16);
93 | tv_confirm.setOnClickListener(new View.OnClickListener() {
94 | @Override
95 | public void onClick(View view) {
96 | popupWindow.dismiss();
97 | click.onClick(view, wv_option.getCurrentItem());
98 | }
99 | });
100 |
101 | view.findViewById(R.id.btnCancel).setOnClickListener(new View.OnClickListener() {
102 | @Override
103 | public void onClick(View view) {
104 | // TODO: 2016/8/11 0011 取消
105 | popupWindow.dismiss();
106 | }
107 | });
108 | view.setOnTouchListener(new View.OnTouchListener() {
109 | @Override
110 | public boolean onTouch(View view, MotionEvent motionEvent) {
111 | int top = view.findViewById(R.id.ll_container).getTop();
112 | if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
113 | int y = (int) motionEvent.getY();
114 | if (y < top) {
115 | popupWindow.dismiss();
116 | }
117 | }
118 | return true;
119 | }
120 | });
121 | popupWindow.setContentView(view);
122 | popupWindow.setOutsideTouchable(true);
123 | popupWindow.setFocusable(true);
124 | popupWindow.setBackgroundDrawable(new BitmapDrawable());
125 | popupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
126 | popupWindow.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
127 | popupWindow.showAtLocation(((ViewGroup) ((Activity) context).findViewById(android.R.id.content)).getChildAt(0), Gravity.CENTER, 0, 0);
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/app/src/main/java/com/bigkoo/pickerviewdemo/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.bigkoo.pickerviewdemo.activity;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.widget.TextView;
8 | import android.widget.Toast;
9 |
10 | import com.bigkoo.pickerviewdemo.DataModel;
11 | import com.bigkoo.pickerviewdemo.R;
12 | import com.bigkoo.pickerviewdemo.Util;
13 | import com.bigkoo.pickerviewdemo.bean.ProvinceBean;
14 | import com.bigkoo.pickerviewdemo.bean.TypeBean;
15 | import com.lvfq.pickerview.OptionsPickerView;
16 |
17 | import java.util.ArrayList;
18 |
19 |
20 | public class MainActivity extends Activity {
21 |
22 | private ArrayList options1Items = new ArrayList();
23 | private ArrayList> options2Items = new ArrayList>();
24 | private ArrayList>> options3Items = new ArrayList>>();
25 |
26 | private ArrayList mList = new ArrayList();
27 | private TextView tvTime, tvOptions;
28 | private TextView tv_single_option;
29 |
30 | OptionsPickerView pvOptions;
31 | View vMasker;
32 |
33 |
34 | @Override
35 | protected void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | setContentView(R.layout.activity_main);
38 |
39 | vMasker = findViewById(R.id.vMasker);
40 | tvTime = (TextView) findViewById(R.id.tvTime);
41 | tvOptions = (TextView) findViewById(R.id.tvOptions);
42 | tv_single_option = (TextView) findViewById(R.id.tv_single_option);
43 |
44 | // 时间选择
45 | tvTime.setOnClickListener(new View.OnClickListener() {
46 |
47 | @Override
48 | public void onClick(View v) {
49 | Intent intent = new Intent(MainActivity.this, TestActivity.class);
50 | startActivity(intent);
51 | }
52 | });
53 |
54 | // 单项选择
55 | for (int i = 0; i <= 10; i++) {
56 | mList.add(new TypeBean(i, "item" + i));
57 | }
58 |
59 | tv_single_option.setOnClickListener(new View.OnClickListener() {
60 | @Override
61 | public void onClick(View v) {
62 | Util.alertBottomWheelOption(MainActivity.this, mList, new Util.OnWheelViewClick() {
63 | @Override
64 | public void onClick(View view, int postion) {
65 | Toast.makeText(MainActivity.this, mList.get(postion).getName(), Toast.LENGTH_SHORT).show();
66 | }
67 | });
68 | }
69 | });
70 |
71 |
72 | showOptions();
73 | }
74 |
75 | private void showOptions() {
76 | //选项选择器
77 | pvOptions = new OptionsPickerView(this);
78 | // 初始化三个列表数据
79 | DataModel.initData(options1Items, options2Items, options3Items);
80 |
81 | //三级联动效果
82 | pvOptions.setPicker(options1Items, options2Items, options3Items, true);
83 | //设置选择的三级单位
84 | // pwOptions.setLabels("省", "市", "区");
85 | pvOptions.setTitle("选择城市");
86 | pvOptions.setCyclic(false, false, false);
87 | //设置默认选中的三级项目
88 | //监听确定选择按钮
89 | pvOptions.setSelectOptions(1, 1, 1);
90 | pvOptions.setTextSize(18);
91 | pvOptions.setOnoptionsSelectListener(new OptionsPickerView.OnOptionsSelectListener() {
92 |
93 | @Override
94 | public void onOptionsSelect(int options1, int option2, int options3) {
95 | //返回的分别是三个级别的选中位置
96 | String tx = options1Items.get(options1).getPickerViewText()
97 | + options2Items.get(options1).get(option2)
98 | + options3Items.get(options1).get(option2).get(options3);
99 | tvOptions.setText(tx);
100 | vMasker.setVisibility(View.GONE);
101 | }
102 | });
103 | //点击弹出选项选择器
104 | tvOptions.setOnClickListener(new View.OnClickListener() {
105 |
106 | @Override
107 | public void onClick(View v) {
108 | pvOptions.show();
109 | }
110 | });
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/app/src/main/java/com/bigkoo/pickerviewdemo/activity/TestActivity.java:
--------------------------------------------------------------------------------
1 | package com.bigkoo.pickerviewdemo.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.FragmentActivity;
6 | import android.view.View;
7 | import android.widget.Toast;
8 |
9 | import com.bigkoo.pickerviewdemo.R;
10 | import com.bigkoo.pickerviewdemo.Util;
11 | import com.lvfq.pickerview.TimePickerView;
12 |
13 | /**
14 | * --------------------------------------------
15 | * Create By : Lvfq
16 | * Date : 2016/8/25 0025 下午 5:36
17 | * -------------------------------------------
18 | **/
19 | public class TestActivity extends FragmentActivity implements View.OnClickListener {
20 |
21 | @Override
22 | protected void onCreate(@Nullable Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 |
25 | setContentView(R.layout.activity_test);
26 |
27 | findViewById(R.id.btn_ymdhm).setOnClickListener(this);
28 | findViewById(R.id.btn_ymdh).setOnClickListener(this);
29 | findViewById(R.id.btn_ymd).setOnClickListener(this);
30 | findViewById(R.id.btn_mdhm).setOnClickListener(this);
31 | findViewById(R.id.btn_hm).setOnClickListener(this);
32 | findViewById(R.id.btn_ym).setOnClickListener(this);
33 |
34 | }
35 |
36 | @Override
37 | public void onClick(View v) {
38 | String format = "";
39 | TimePickerView.Type type = null;
40 | switch (v.getId()) {
41 | case R.id.btn_ymdhm:
42 | type = TimePickerView.Type.ALL;
43 | format = "yyyy-MM-dd HH:mm";
44 | break;
45 | case R.id.btn_ymdh:
46 | type = TimePickerView.Type.YEAR_MONTH_DAY_HOUR;
47 | format = "yyyy-MM-dd HH";
48 | break;
49 | case R.id.btn_ymd:
50 | type = TimePickerView.Type.YEAR_MONTH_DAY;
51 | format = "yyyy-MM-dd";
52 | break;
53 | case R.id.btn_mdhm:
54 | type = TimePickerView.Type.MONTH_DAY_HOUR_MIN;
55 | format = "MM-dd HH:mm";
56 | break;
57 | case R.id.btn_hm:
58 | type = TimePickerView.Type.HOURS_MINS;
59 | format = "HH:mm";
60 | break;
61 | case R.id.btn_ym:
62 | type = TimePickerView.Type.YEAR_MONTH;
63 | format = "yyyy-MM";
64 | break;
65 | }
66 | Util.alertTimerPicker(this, type, format, new Util.TimerPickerCallBack() {
67 | @Override
68 | public void onTimeSelect(String date) {
69 | Toast.makeText(TestActivity.this, date, Toast.LENGTH_SHORT).show();
70 | }
71 | });
72 |
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/bigkoo/pickerviewdemo/bean/ProvinceBean.java:
--------------------------------------------------------------------------------
1 | package com.bigkoo.pickerviewdemo.bean;
2 |
3 | /**
4 | * Created by Sai on 15/11/22.
5 | */
6 | public class ProvinceBean {
7 | private long id;
8 | private String name;
9 | private String description;
10 | private String others;
11 |
12 | public ProvinceBean(long id,String name,String description,String others){
13 | this.id = id;
14 | this.name = name;
15 | this.description = description;
16 | this.others = others;
17 | }
18 |
19 | public long getId() {
20 | return id;
21 | }
22 |
23 | public void setId(long id) {
24 | this.id = id;
25 | }
26 |
27 | public String getName() {
28 | return name;
29 | }
30 |
31 | public void setName(String name) {
32 | this.name = name;
33 | }
34 |
35 | public String getDescription() {
36 | return description;
37 | }
38 |
39 | public void setDescription(String description) {
40 | this.description = description;
41 | }
42 |
43 | public String getOthers() {
44 | return others;
45 | }
46 |
47 | public void setOthers(String others) {
48 | this.others = others;
49 | }
50 |
51 | //这个用来显示在PickerView上面的字符串,PickerView会通过反射获取getPickerViewText方法显示出来。
52 | public String getPickerViewText() {
53 | //这里还可以判断文字超长截断再提供显示
54 | return name;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/bigkoo/pickerviewdemo/bean/TypeBean.java:
--------------------------------------------------------------------------------
1 | package com.bigkoo.pickerviewdemo.bean;
2 |
3 | /**
4 | * --------------------------------------------
5 | * Create By : Lvfq
6 | * Date : 2016/8/28 0028 下午 3:55
7 | * -------------------------------------------
8 | **/
9 | public class TypeBean {
10 |
11 | private int id;
12 | private String name;
13 |
14 | public TypeBean(int id, String name) {
15 | this.id = id;
16 | this.name = name;
17 | }
18 |
19 | public int getId() {
20 | return id;
21 | }
22 |
23 | public void setId(int id) {
24 | this.id = id;
25 | }
26 |
27 | public String getName() {
28 | return name;
29 | }
30 |
31 | public void setName(String name) {
32 | this.name = name;
33 | }
34 |
35 | //这个用来显示在PickerView上面的字符串,PickerView会通过反射获取getPickerViewText方法显示出来。
36 | public String getPickerViewText() {
37 | //这里还可以判断文字超长截断再提供显示
38 | return name;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lvfaqiang/Android-PickerView-master/52ebf7b683c32ff09585250388142ba946995c56/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lvfaqiang/Android-PickerView-master/52ebf7b683c32ff09585250388142ba946995c56/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lvfaqiang/Android-PickerView-master/52ebf7b683c32ff09585250388142ba946995c56/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lvfaqiang/Android-PickerView-master/52ebf7b683c32ff09585250388142ba946995c56/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
21 |
22 |
31 |
32 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
23 |
24 |
30 |
31 |
37 |
38 |
44 |
45 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_wheelview_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_bottom_wheel_option.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
21 |
22 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | PickerViewDemo
5 | Hello world!
6 | Settings
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.1.2'
9 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0'
10 | classpath 'com.github.dcendents:android-maven-plugin:1.2'
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lvfaqiang/Android-PickerView-master/52ebf7b683c32ff09585250388142ba946995c56/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Aug 15 16:08:28 CST 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/pickerview/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/pickerview/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 |
4 | android {
5 | compileSdkVersion 21
6 | buildToolsVersion "20.0.0"
7 |
8 | defaultConfig {
9 | minSdkVersion 14
10 | targetSdkVersion 21
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/pickerview/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 |
--------------------------------------------------------------------------------
/pickerview/src/androidTest/java/com/lvfq/pickerview/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview;
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 | }
--------------------------------------------------------------------------------
/pickerview/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/OptionsPickerView.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.widget.TextView;
7 |
8 | import com.bigkoo.pickerview.R;
9 | import com.lvfq.pickerview.view.BasePickerView;
10 | import com.lvfq.pickerview.view.WheelOptions;
11 |
12 | import java.util.ArrayList;
13 |
14 | /**
15 | * Created by Sai on 15/11/22.
16 | */
17 | public class OptionsPickerView extends BasePickerView implements View.OnClickListener {
18 | WheelOptions wheelOptions;
19 | private View btnSubmit, btnCancel;
20 | private TextView tvTitle;
21 | private OnOptionsSelectListener optionsSelectListener;
22 | private static final String TAG_SUBMIT = "submit";
23 | private static final String TAG_CANCEL = "cancel";
24 |
25 | public OptionsPickerView(Context context) {
26 | super(context);
27 | LayoutInflater.from(context).inflate(R.layout.pickerview_options, contentContainer);
28 | // -----确定和取消按钮
29 | btnSubmit = findViewById(R.id.btnSubmit);
30 | btnSubmit.setTag(TAG_SUBMIT);
31 | btnCancel = findViewById(R.id.btnCancel);
32 | btnCancel.setTag(TAG_CANCEL);
33 | btnSubmit.setOnClickListener(this);
34 | btnCancel.setOnClickListener(this);
35 | //顶部标题
36 | tvTitle = (TextView) findViewById(R.id.tvTitle);
37 | // ----转轮
38 | final View optionspicker = findViewById(R.id.optionspicker);
39 | wheelOptions = new WheelOptions(optionspicker);
40 | }
41 |
42 | public void setPicker(ArrayList optionsItems) {
43 | wheelOptions.setPicker(optionsItems, null, null, false);
44 | }
45 |
46 | public void setPicker(ArrayList options1Items,
47 | ArrayList> options2Items, boolean linkage) {
48 | wheelOptions.setPicker(options1Items, options2Items, null, linkage);
49 | }
50 |
51 | public void setPicker(ArrayList options1Items,
52 | ArrayList> options2Items,
53 | ArrayList>> options3Items,
54 | boolean linkage) {
55 | wheelOptions.setPicker(options1Items, options2Items, options3Items,
56 | linkage);
57 | }
58 |
59 | /**
60 | * 设置选中的item位置
61 | *
62 | * @param option1
63 | */
64 | public void setSelectOptions(int option1) {
65 | wheelOptions.setCurrentItems(option1, 0, 0);
66 | }
67 |
68 | /**
69 | * 设置选中的item位置
70 | *
71 | * @param option1
72 | * @param option2
73 | */
74 | public void setSelectOptions(int option1, int option2) {
75 | wheelOptions.setCurrentItems(option1, option2, 0);
76 | }
77 |
78 | /**
79 | * 设置选中的item位置
80 | *
81 | * @param option1
82 | * @param option2
83 | * @param option3
84 | */
85 | public void setSelectOptions(int option1, int option2, int option3) {
86 | wheelOptions.setCurrentItems(option1, option2, option3);
87 | }
88 |
89 | /**
90 | * 设置选项的单位
91 | *
92 | * @param label1
93 | */
94 | public void setLabels(String label1) {
95 | wheelOptions.setLabels(label1, null, null);
96 | }
97 |
98 | /**
99 | * 设置选项的单位
100 | *
101 | * @param label1
102 | * @param label2
103 | */
104 | public void setLabels(String label1, String label2) {
105 | wheelOptions.setLabels(label1, label2, null);
106 | }
107 |
108 | /**
109 | * 设置选项的单位
110 | *
111 | * @param label1
112 | * @param label2
113 | * @param label3
114 | */
115 | public void setLabels(String label1, String label2, String label3) {
116 | wheelOptions.setLabels(label1, label2, label3);
117 | }
118 |
119 | /**
120 | * 设置是否循环滚动
121 | *
122 | * @param cyclic
123 | */
124 | public void setCyclic(boolean cyclic) {
125 | wheelOptions.setCyclic(cyclic);
126 | }
127 |
128 | public void setCyclic(boolean cyclic1, boolean cyclic2, boolean cyclic3) {
129 | wheelOptions.setCyclic(cyclic1, cyclic2, cyclic3);
130 | }
131 |
132 |
133 | @Override
134 | public void onClick(View v) {
135 | String tag = (String) v.getTag();
136 | if (tag.equals(TAG_CANCEL)) {
137 | dismiss();
138 | return;
139 | } else {
140 | if (optionsSelectListener != null) {
141 | int[] optionsCurrentItems = wheelOptions.getCurrentItems();
142 | optionsSelectListener.onOptionsSelect(optionsCurrentItems[0], optionsCurrentItems[1], optionsCurrentItems[2]);
143 | }
144 | dismiss();
145 | return;
146 | }
147 | }
148 |
149 | public interface OnOptionsSelectListener {
150 | public void onOptionsSelect(int options1, int option2, int options3);
151 | }
152 |
153 | public void setOnoptionsSelectListener(
154 | OnOptionsSelectListener optionsSelectListener) {
155 | this.optionsSelectListener = optionsSelectListener;
156 | }
157 |
158 | public void setTitle(String title) {
159 | tvTitle.setText(title);
160 | }
161 |
162 | /**
163 | * 设置文字大小
164 | * @param textSize
165 | */
166 | public void setTextSize(float textSize) {
167 | wheelOptions.setTextSize(textSize);
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/TimePickerView.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.widget.TextView;
7 |
8 | import com.bigkoo.pickerview.R;
9 | import com.lvfq.pickerview.view.BasePickerView;
10 | import com.lvfq.pickerview.view.WheelTime;
11 |
12 | import java.text.ParseException;
13 | import java.util.Calendar;
14 | import java.util.Date;
15 |
16 | /**
17 | * Created by Sai on 15/11/22.
18 | */
19 | public class TimePickerView extends BasePickerView implements View.OnClickListener {
20 | public enum Type {
21 | ALL, YEAR_MONTH_DAY , YEAR_MONTH_DAY_HOUR , HOURS_MINS, MONTH_DAY_HOUR_MIN , YEAR_MONTH
22 | }// 选择模式,年月日时分,年月日,年月日时 , 时分,月日时分 ,年月
23 |
24 | WheelTime wheelTime;
25 | private View btnSubmit, btnCancel;
26 | private TextView tvTitle;
27 | private static final String TAG_SUBMIT = "submit";
28 | private static final String TAG_CANCEL = "cancel";
29 | private OnTimeSelectListener timeSelectListener;
30 |
31 | public TimePickerView(Context context, Type type) {
32 | super(context);
33 |
34 | LayoutInflater.from(context).inflate(R.layout.pickerview_time, contentContainer);
35 | // -----确定和取消按钮
36 | btnSubmit = findViewById(R.id.btnSubmit);
37 | btnSubmit.setTag(TAG_SUBMIT);
38 | btnCancel = findViewById(R.id.btnCancel);
39 | btnCancel.setTag(TAG_CANCEL);
40 | btnSubmit.setOnClickListener(this);
41 | btnCancel.setOnClickListener(this);
42 | //顶部标题
43 | tvTitle = (TextView) findViewById(R.id.tvTitle);
44 | // ----时间转轮
45 | final View timepickerview = findViewById(R.id.timepicker);
46 | wheelTime = new WheelTime(timepickerview, type);
47 |
48 | //默认选中当前时间
49 | Calendar calendar = Calendar.getInstance();
50 | calendar.setTimeInMillis(System.currentTimeMillis());
51 | int year = calendar.get(Calendar.YEAR);
52 | int month = calendar.get(Calendar.MONTH);
53 | int day = calendar.get(Calendar.DAY_OF_MONTH);
54 | int hours = calendar.get(Calendar.HOUR_OF_DAY);
55 | int minute = calendar.get(Calendar.MINUTE);
56 | wheelTime.setPicker(year, month, day, hours, minute);
57 |
58 | }
59 |
60 | /**
61 | * 设置可以选择的时间范围
62 | *
63 | * @param startYear
64 | * @param endYear
65 | */
66 | public void setRange(int startYear, int endYear) {
67 | wheelTime.setStartYear(startYear);
68 | wheelTime.setEndYear(endYear);
69 | }
70 |
71 | /**
72 | * 设置选中时间
73 | * @param date
74 | */
75 | public void setTime(Date date) {
76 | Calendar calendar = Calendar.getInstance();
77 | if (date == null)
78 | calendar.setTimeInMillis(System.currentTimeMillis());
79 | else
80 | calendar.setTime(date);
81 | int year = calendar.get(Calendar.YEAR);
82 | int month = calendar.get(Calendar.MONTH);
83 | int day = calendar.get(Calendar.DAY_OF_MONTH);
84 | int hours = calendar.get(Calendar.HOUR_OF_DAY);
85 | int minute = calendar.get(Calendar.MINUTE);
86 | wheelTime.setPicker(year, month, day, hours, minute);
87 | }
88 |
89 | // /**
90 | // * 指定选中的时间,显示选择器
91 | // *
92 | // * @param date
93 | // */
94 | // public void show(Date date) {
95 | // Calendar calendar = Calendar.getInstance();
96 | // if (date == null)
97 | // calendar.setTimeInMillis(System.currentTimeMillis());
98 | // else
99 | // calendar.setTime(date);
100 | // int year = calendar.get(Calendar.YEAR);
101 | // int month = calendar.get(Calendar.MONTH);
102 | // int day = calendar.get(Calendar.DAY_OF_MONTH);
103 | // int hours = calendar.get(Calendar.HOUR_OF_DAY);
104 | // int minute = calendar.get(Calendar.MINUTE);
105 | // wheelTime.setPicker(year, month, day, hours, minute);
106 | // show();
107 | // }
108 |
109 | /**
110 | * 设置是否循环滚动
111 | *
112 | * @param cyclic
113 | */
114 | public void setCyclic(boolean cyclic) {
115 | wheelTime.setCyclic(cyclic);
116 | }
117 |
118 | /**
119 | * 设置文字大小
120 | * @param textSize
121 | */
122 | public void setTextSize(float textSize){
123 | wheelTime.setTextSize(textSize);
124 | }
125 |
126 | @Override
127 | public void onClick(View v) {
128 | String tag = (String) v.getTag();
129 | if (tag.equals(TAG_CANCEL)) {
130 | dismiss();
131 | return;
132 | } else {
133 | if (timeSelectListener != null) {
134 | try {
135 | Date date = WheelTime.dateFormat.parse(wheelTime.getTime());
136 | timeSelectListener.onTimeSelect(date);
137 | } catch (ParseException e) {
138 | e.printStackTrace();
139 | }
140 | }
141 | dismiss();
142 | return;
143 | }
144 | }
145 |
146 | public interface OnTimeSelectListener {
147 | public void onTimeSelect(Date date);
148 | }
149 |
150 | public void setOnTimeSelectListener(OnTimeSelectListener timeSelectListener) {
151 | this.timeSelectListener = timeSelectListener;
152 | }
153 |
154 | public void setTitle(String title){
155 | tvTitle.setText(title);
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/adapter/ArrayWheelAdapter.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.adapter;
2 |
3 | import java.util.ArrayList;
4 |
5 | /**
6 | * The simple Array wheel adapter
7 | * @param the element type
8 | */
9 | public class ArrayWheelAdapter implements WheelAdapter {
10 |
11 | /** The default items length */
12 | public static final int DEFAULT_LENGTH = 4;
13 |
14 | // items
15 | private ArrayList items;
16 | // length
17 | private int length;
18 |
19 | /**
20 | * Constructor
21 | * @param items the items
22 | * @param length the max items length
23 | */
24 | public ArrayWheelAdapter(ArrayList items, int length) {
25 | this.items = items;
26 | this.length = length;
27 | }
28 |
29 | /**
30 | * Contructor
31 | * @param items the items
32 | */
33 | public ArrayWheelAdapter(ArrayList items) {
34 | this(items, DEFAULT_LENGTH);
35 | }
36 |
37 | @Override
38 | public Object getItem(int index) {
39 | if (index >= 0 && index < items.size()) {
40 | return items.get(index);
41 | }
42 | return "";
43 | }
44 |
45 | @Override
46 | public int getItemsCount() {
47 | return items.size();
48 | }
49 |
50 | @Override
51 | public int indexOf(Object o){
52 | return items.indexOf(o);
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/adapter/NumericWheelAdapter.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.adapter;
2 |
3 |
4 | /**
5 | * Numeric Wheel adapter.
6 | */
7 | public class NumericWheelAdapter implements WheelAdapter {
8 |
9 | /** The default min value */
10 | public static final int DEFAULT_MAX_VALUE = 9;
11 |
12 | /** The default max value */
13 | private static final int DEFAULT_MIN_VALUE = 0;
14 |
15 | // Values
16 | private int minValue;
17 | private int maxValue;
18 |
19 | /**
20 | * Default constructor
21 | */
22 | public NumericWheelAdapter() {
23 | this(DEFAULT_MIN_VALUE, DEFAULT_MAX_VALUE);
24 | }
25 |
26 | /**
27 | * Constructor
28 | * @param minValue the wheel min value
29 | * @param maxValue the wheel max value
30 | */
31 | public NumericWheelAdapter(int minValue, int maxValue) {
32 | this.minValue = minValue;
33 | this.maxValue = maxValue;
34 | }
35 |
36 | @Override
37 | public Object getItem(int index) {
38 | if (index >= 0 && index < getItemsCount()) {
39 | int value = minValue + index;
40 | return value;
41 | }
42 | return 0;
43 | }
44 |
45 | @Override
46 | public int getItemsCount() {
47 | return maxValue - minValue + 1;
48 | }
49 |
50 | @Override
51 | public int indexOf(Object o){
52 | return (int)o - minValue;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/adapter/WheelAdapter.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.adapter;
2 |
3 | public interface WheelAdapter {
4 | /**
5 | * Gets items count
6 | * @return the count of wheel items
7 | */
8 | public int getItemsCount();
9 |
10 | /**
11 | * Gets a wheel item by index.
12 | *
13 | * @param index the item index
14 | * @return the wheel item text or null
15 | */
16 | public T getItem(int index);
17 |
18 | /**
19 | * Gets maximum item length. It is used to determine the wheel width.
20 | * If -1 is returned there will be used the default wheel width.
21 | *
22 | * @return the maximum item length or -1
23 | */
24 | public int indexOf(T o);
25 | }
26 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/lib/InertiaTimerTask.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.lib;
2 |
3 | import java.util.TimerTask;
4 |
5 | final class InertiaTimerTask extends TimerTask {
6 |
7 | float a;
8 | final float velocityY;
9 | final WheelView loopView;
10 |
11 | InertiaTimerTask(WheelView loopview, float velocityY) {
12 | super();
13 | loopView = loopview;
14 | this.velocityY = velocityY;
15 | a = Integer.MAX_VALUE;
16 | }
17 |
18 | @Override
19 | public final void run() {
20 | if (a == Integer.MAX_VALUE) {
21 | if (Math.abs(velocityY) > 2000F) {
22 | if (velocityY > 0.0F) {
23 | a = 2000F;
24 | } else {
25 | a = -2000F;
26 | }
27 | } else {
28 | a = velocityY;
29 | }
30 | }
31 | if (Math.abs(a) >= 0.0F && Math.abs(a) <= 20F) {
32 | loopView.cancelFuture();
33 | loopView.handler.sendEmptyMessage(MessageHandler.WHAT_SMOOTH_SCROLL);
34 | return;
35 | }
36 | int i = (int) ((a * 10F) / 1000F);
37 | loopView.totalScrollY = loopView.totalScrollY - i;
38 | if (!loopView.isLoop) {
39 | float itemHeight = loopView.itemHeight;
40 | float top = (-loopView.initPosition) * itemHeight;
41 | float bottom = (loopView.getItemsCount() - 1 - loopView.initPosition) * itemHeight;
42 | if(loopView.totalScrollY - itemHeight*0.3 < top){
43 | top = loopView.totalScrollY + i;
44 | }
45 | else if(loopView.totalScrollY + itemHeight*0.3 > bottom){
46 | bottom = loopView.totalScrollY + i;
47 | }
48 |
49 | if (loopView.totalScrollY <= top){
50 | a = 40F;
51 | loopView.totalScrollY = (int)top;
52 | } else if (loopView.totalScrollY >= bottom) {
53 | loopView.totalScrollY = (int)bottom;
54 | a = -40F;
55 | }
56 | }
57 | if (a < 0.0F) {
58 | a = a + 20F;
59 | } else {
60 | a = a - 20F;
61 | }
62 | loopView.handler.sendEmptyMessage(MessageHandler.WHAT_INVALIDATE_LOOP_VIEW);
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/lib/LoopViewGestureListener.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.lib;
2 |
3 | import android.view.MotionEvent;
4 |
5 | final class LoopViewGestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
6 |
7 | final WheelView loopView;
8 |
9 | LoopViewGestureListener(WheelView loopview) {
10 | loopView = loopview;
11 | }
12 |
13 | @Override
14 | public final boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
15 | loopView.scrollBy(velocityY);
16 | return true;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/lib/MessageHandler.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.lib;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 |
6 | final class MessageHandler extends Handler {
7 | public static final int WHAT_INVALIDATE_LOOP_VIEW = 1000;
8 | public static final int WHAT_SMOOTH_SCROLL = 2000;
9 | public static final int WHAT_ITEM_SELECTED = 3000;
10 |
11 | final WheelView loopview;
12 |
13 | MessageHandler(WheelView loopview) {
14 | this.loopview = loopview;
15 | }
16 |
17 | @Override
18 | public final void handleMessage(Message msg) {
19 | switch (msg.what) {
20 | case WHAT_INVALIDATE_LOOP_VIEW:
21 | loopview.invalidate();
22 | break;
23 |
24 | case WHAT_SMOOTH_SCROLL:
25 | loopview.smoothScroll(WheelView.ACTION.FLING);
26 | break;
27 |
28 | case WHAT_ITEM_SELECTED:
29 | loopview.onItemSelected();
30 | break;
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/lib/OnItemSelectedRunnable.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.lib;
2 |
3 | final class OnItemSelectedRunnable implements Runnable {
4 | final WheelView loopView;
5 |
6 | OnItemSelectedRunnable(WheelView loopview) {
7 | loopView = loopview;
8 | }
9 |
10 | @Override
11 | public final void run() {
12 | loopView.onItemSelectedListener.onItemSelected(loopView.getCurrentItem());
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/lib/SmoothScrollTimerTask.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.lib;
2 |
3 | import java.util.TimerTask;
4 |
5 | final class SmoothScrollTimerTask extends TimerTask {
6 |
7 | int realTotalOffset;
8 | int realOffset;
9 | int offset;
10 | final WheelView loopView;
11 |
12 | SmoothScrollTimerTask(WheelView loopview, int offset) {
13 | this.loopView = loopview;
14 | this.offset = offset;
15 | realTotalOffset = Integer.MAX_VALUE;
16 | realOffset = 0;
17 | }
18 |
19 | @Override
20 | public final void run() {
21 | if (realTotalOffset == Integer.MAX_VALUE) {
22 | realTotalOffset = offset;
23 | }
24 | //把要滚动的范围细分成十小份,按是小份单位来重绘
25 | realOffset = (int) ((float) realTotalOffset * 0.1F);
26 |
27 | if (realOffset == 0) {
28 | if (realTotalOffset < 0) {
29 | realOffset = -1;
30 | } else {
31 | realOffset = 1;
32 | }
33 | }
34 |
35 | if (Math.abs(realTotalOffset) <= 1) {
36 | loopView.cancelFuture();
37 | loopView.handler.sendEmptyMessage(MessageHandler.WHAT_ITEM_SELECTED);
38 | } else {
39 | loopView.totalScrollY = loopView.totalScrollY + realOffset;
40 |
41 | //这里如果不是循环模式,则点击空白位置需要回滚,不然就会出现选到-1 item的 情况
42 | if (!loopView.isLoop) {
43 | float itemHeight = loopView.itemHeight;
44 | float top = (float) (-loopView.initPosition) * itemHeight;
45 | float bottom = (float) (loopView.getItemsCount() - 1 - loopView.initPosition) * itemHeight;
46 | if (loopView.totalScrollY <= top||loopView.totalScrollY >= bottom) {
47 | loopView.totalScrollY = loopView.totalScrollY - realOffset;
48 | loopView.cancelFuture();
49 | loopView.handler.sendEmptyMessage(MessageHandler.WHAT_ITEM_SELECTED);
50 | return;
51 | }
52 | }
53 | loopView.handler.sendEmptyMessage(MessageHandler.WHAT_INVALIDATE_LOOP_VIEW);
54 | realTotalOffset = realTotalOffset - realOffset;
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/lib/WheelView.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.lib;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.graphics.Rect;
8 | import android.graphics.Typeface;
9 | import android.os.Handler;
10 | import android.util.AttributeSet;
11 | import android.view.GestureDetector;
12 | import android.view.Gravity;
13 | import android.view.MotionEvent;
14 | import android.view.View;
15 |
16 | import com.bigkoo.pickerview.R;
17 | import com.lvfq.pickerview.adapter.WheelAdapter;
18 | import com.lvfq.pickerview.listener.OnItemSelectedListener;
19 |
20 | import java.lang.reflect.InvocationTargetException;
21 | import java.lang.reflect.Method;
22 | import java.util.concurrent.Executors;
23 | import java.util.concurrent.ScheduledExecutorService;
24 | import java.util.concurrent.ScheduledFuture;
25 | import java.util.concurrent.TimeUnit;
26 |
27 | /**
28 | * 3d滚轮控件
29 | */
30 | public class WheelView extends View {
31 |
32 | public enum ACTION {
33 | // 点击,滑翔(滑到尽头),拖拽事件
34 | CLICK, FLING, DAGGLE
35 | }
36 | Context context;
37 |
38 | Handler handler;
39 | private GestureDetector gestureDetector;
40 | OnItemSelectedListener onItemSelectedListener;
41 |
42 | // Timer mTimer;
43 | ScheduledExecutorService mExecutor = Executors.newSingleThreadScheduledExecutor();
44 | private ScheduledFuture> mFuture;
45 |
46 | Paint paintOuterText;
47 | Paint paintCenterText;
48 | Paint paintIndicator;
49 |
50 | WheelAdapter adapter;
51 |
52 | private String label;//附加单位
53 | int textSize;//选项的文字大小
54 | boolean customTextSize;//自定义文字大小,为true则用于使setTextSize函数无效,只能通过xml修改
55 | int maxTextWidth;
56 | int maxTextHeight;
57 | float itemHeight;//每行高度
58 |
59 | int textColorOut;
60 | int textColorCenter;
61 | int dividerColor;
62 |
63 | // 条目间距倍数
64 | static final float lineSpacingMultiplier = 1.4F;
65 | boolean isLoop;
66 |
67 | // 第一条线Y坐标值
68 | float firstLineY;
69 | //第二条线Y坐标
70 | float secondLineY;
71 | //中间Y坐标
72 | float centerY;
73 |
74 | //滚动总高度y值
75 | int totalScrollY;
76 | //初始化默认选中第几个
77 | int initPosition;
78 | //选中的Item是第几个
79 | private int selectedItem;
80 | int preCurrentIndex;
81 | //滚动偏移值,用于记录滚动了多少个item
82 | int change;
83 |
84 | // 显示几个条目
85 | int itemsVisible = 11;
86 |
87 | int measuredHeight;
88 | int measuredWidth;
89 |
90 | // 半圆周长
91 | int halfCircumference;
92 | // 半径
93 | int radius;
94 |
95 | private int mOffset = 0;
96 | private float previousY = 0;
97 | long startTime = 0;
98 |
99 | // 修改这个值可以改变滑行速度
100 | private static final int VELOCITYFLING = 5;
101 | int widthMeasureSpec;
102 |
103 | private int mGravity = Gravity.CENTER;
104 | private int drawCenterContentStart = 0;//中间选中文字开始绘制位置
105 | private int drawOutContentStart = 0;//非中间文字开始绘制位置
106 | private static final float SCALECONTENT = 0.8F;//非中间文字则用此控制高度,压扁形成3d错觉
107 | private static final float CENTERCONTENTOFFSET = 6;//中间文字文字居中需要此偏移值
108 | private static final String GETPICKERVIEWTEXT = "getPickerViewText";//反射的方法名
109 |
110 | public WheelView(Context context) {
111 | this(context, null);
112 | }
113 |
114 | public WheelView(Context context, AttributeSet attrs) {
115 | super(context, attrs);
116 | textColorOut = getResources().getColor(R.color.pickerview_wheelview_textcolor_out);
117 | textColorCenter = getResources().getColor(R.color.pickerview_wheelview_textcolor_center);
118 | dividerColor = getResources().getColor(R.color.pickerview_wheelview_textcolor_divider);
119 | //配合customTextSize使用,customTextSize为true才会发挥效果
120 | textSize = getResources().getDimensionPixelSize(R.dimen.pickerview_textsize);
121 | customTextSize = getResources().getBoolean(R.bool.pickerview_customTextSize);
122 | if(attrs != null) {
123 | TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.wheelview,0,0);
124 | mGravity = a.getInt(R.styleable.wheelview_gravity, Gravity.CENTER);
125 | textColorOut = a.getColor(R.styleable.wheelview_textColorOut, textColorOut);
126 | textColorCenter = a.getColor(R.styleable.wheelview_textColorCenter,textColorCenter);
127 | dividerColor = a.getColor(R.styleable.wheelview_dividerColor,dividerColor);
128 | textSize = a.getDimensionPixelOffset(R.styleable.wheelview_textSize,textSize);
129 | }
130 | initLoopView(context);
131 | }
132 |
133 | private void initLoopView(Context context) {
134 | this.context = context;
135 | handler = new MessageHandler(this);
136 | gestureDetector = new GestureDetector(context, new LoopViewGestureListener(this));
137 | gestureDetector.setIsLongpressEnabled(false);
138 |
139 | isLoop = true;
140 |
141 | totalScrollY = 0;
142 | initPosition = -1;
143 |
144 | initPaints();
145 |
146 | }
147 |
148 | private void initPaints() {
149 | paintOuterText = new Paint();
150 | paintOuterText.setColor(textColorOut);
151 | paintOuterText.setAntiAlias(true);
152 | paintOuterText.setTypeface(Typeface.MONOSPACE);
153 | paintOuterText.setTextSize(textSize);
154 |
155 | paintCenterText = new Paint();
156 | paintCenterText.setColor(textColorCenter);
157 | paintCenterText.setAntiAlias(true);
158 | paintCenterText.setTextScaleX(1.1F);
159 | paintCenterText.setTypeface(Typeface.MONOSPACE);
160 | paintCenterText.setTextSize(textSize);
161 |
162 | paintIndicator = new Paint();
163 | paintIndicator.setColor(dividerColor);
164 | paintIndicator.setAntiAlias(true);
165 |
166 | if (android.os.Build.VERSION.SDK_INT >= 11) {
167 | setLayerType(LAYER_TYPE_SOFTWARE, null);
168 | }
169 | }
170 |
171 | private void remeasure() {
172 | if (adapter == null) {
173 | return;
174 | }
175 |
176 | measureTextWidthHeight();
177 |
178 | //最大Text的高度乘间距倍数得到 可见文字实际的总高度,半圆的周长
179 | halfCircumference = (int) (itemHeight * (itemsVisible - 1)) ;
180 | //整个圆的周长除以PI得到直径,这个直径用作控件的总高度
181 | measuredHeight = (int) ((halfCircumference * 2) / Math.PI);
182 | //求出半径
183 | radius = (int) (halfCircumference / Math.PI);
184 | //控件宽度,这里支持weight
185 | measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
186 | //计算两条横线和控件中间点的Y位置
187 | firstLineY = (measuredHeight - itemHeight) / 2.0F;
188 | secondLineY = (measuredHeight + itemHeight) / 2.0F;
189 | centerY = (measuredHeight + maxTextHeight) / 2.0F - CENTERCONTENTOFFSET;
190 | //初始化显示的item的position,根据是否loop
191 | if (initPosition == -1) {
192 | if (isLoop) {
193 | initPosition = (adapter.getItemsCount() + 1) / 2;
194 | } else {
195 | initPosition = 0;
196 | }
197 | }
198 |
199 | preCurrentIndex = initPosition;
200 | }
201 |
202 | /**
203 | * 计算最大len的Text的宽高度
204 | */
205 | private void measureTextWidthHeight() {
206 | Rect rect = new Rect();
207 | for (int i = 0; i < adapter.getItemsCount(); i++) {
208 | String s1 = getContentText(adapter.getItem(i));
209 | paintCenterText.getTextBounds(s1, 0, s1.length(), rect);
210 | int textWidth = rect.width();
211 | if (textWidth > maxTextWidth) {
212 | maxTextWidth = textWidth;
213 | }
214 | paintCenterText.getTextBounds("\u661F\u671F", 0, 2, rect); // 星期
215 | int textHeight = rect.height();
216 | if (textHeight > maxTextHeight) {
217 | maxTextHeight = textHeight;
218 | }
219 | }
220 | itemHeight = lineSpacingMultiplier * maxTextHeight;
221 | }
222 |
223 | void smoothScroll(ACTION action) {
224 | cancelFuture();
225 | if (action== ACTION.FLING||action== ACTION.DAGGLE) {
226 | mOffset = (int) ((totalScrollY%itemHeight + itemHeight) % itemHeight);
227 | if ((float) mOffset > itemHeight / 2.0F) {
228 | mOffset = (int) (itemHeight - (float) mOffset);
229 | } else {
230 | mOffset = -mOffset;
231 | }
232 | }
233 | //停止的时候,位置有偏移,不是全部都能正确停止到中间位置的,这里把文字位置挪回中间去
234 | mFuture = mExecutor.scheduleWithFixedDelay(new SmoothScrollTimerTask(this, mOffset), 0, 10, TimeUnit.MILLISECONDS);
235 | }
236 |
237 | protected final void scrollBy(float velocityY) {
238 | cancelFuture();
239 |
240 | mFuture = mExecutor.scheduleWithFixedDelay(new InertiaTimerTask(this, velocityY), 0, VELOCITYFLING, TimeUnit.MILLISECONDS);
241 | }
242 |
243 | public void cancelFuture() {
244 | if (mFuture!=null&&!mFuture.isCancelled()) {
245 | mFuture.cancel(true);
246 | mFuture = null;
247 | }
248 | }
249 |
250 | /**
251 | * 设置是否循环滚动
252 | * @param cyclic
253 | */
254 | public final void setCyclic(boolean cyclic) {
255 | isLoop = cyclic;
256 | }
257 |
258 | public final void setTextSize(float size) {
259 | if (size > 0.0F&&!customTextSize) {
260 | textSize = (int) (context.getResources().getDisplayMetrics().density * size);
261 | paintOuterText.setTextSize(textSize);
262 | paintCenterText.setTextSize(textSize);
263 | }
264 | }
265 |
266 | public final void setCurrentItem(int currentItem) {
267 | this.initPosition = currentItem;
268 | totalScrollY = 0;//回归顶部,不然重设setCurrentItem的话位置会偏移的,就会显示出不对位置的数据
269 | invalidate();
270 | }
271 |
272 | public final void setOnItemSelectedListener(OnItemSelectedListener OnItemSelectedListener) {
273 | this.onItemSelectedListener = OnItemSelectedListener;
274 | }
275 |
276 | public final void setAdapter(WheelAdapter adapter) {
277 | this.adapter = adapter;
278 | remeasure();
279 | invalidate();
280 | }
281 |
282 | public final WheelAdapter getAdapter(){
283 | return adapter;
284 | }
285 |
286 | public final int getCurrentItem() {
287 | return selectedItem;
288 | }
289 |
290 | protected final void onItemSelected() {
291 | if (onItemSelectedListener != null) {
292 | postDelayed(new OnItemSelectedRunnable(this), 200L);
293 | }
294 | }
295 |
296 | @Override
297 | protected void onDraw(Canvas canvas) {
298 | if (adapter == null) {
299 | return;
300 | }
301 | //可见的item数组
302 | Object visibles[] = new Object[itemsVisible];
303 | //滚动的Y值高度除去每行Item的高度,得到滚动了多少个item,即change数
304 | change = (int) (totalScrollY / itemHeight);
305 | try {
306 | //滚动中实际的预选中的item(即经过了中间位置的item) = 滑动前的位置 + 滑动相对位置
307 | preCurrentIndex = initPosition + change % adapter.getItemsCount();
308 | }catch (ArithmeticException e){
309 | System.out.println("出错了!adapter.getItemsCount() == 0,联动数据不匹配");
310 | }
311 | if (!isLoop) {//不循环的情况
312 | if (preCurrentIndex < 0) {
313 | preCurrentIndex = 0;
314 | }
315 | if (preCurrentIndex > adapter.getItemsCount() - 1) {
316 | preCurrentIndex = adapter.getItemsCount() - 1;
317 | }
318 | } else {//循环
319 | if (preCurrentIndex < 0) {//举个例子:如果总数是5,preCurrentIndex = -1,那么preCurrentIndex按循环来说,其实是0的上面,也就是4的位置
320 | preCurrentIndex = adapter.getItemsCount() + preCurrentIndex;
321 | }
322 | if (preCurrentIndex > adapter.getItemsCount() - 1) {//同理上面,自己脑补一下
323 | preCurrentIndex = preCurrentIndex - adapter.getItemsCount();
324 | }
325 | }
326 |
327 | //跟滚动流畅度有关,总滑动距离与每个item高度取余,即并不是一格格的滚动,每个item不一定滚到对应Rect里的,这个item对应格子的偏移值
328 | int itemHeightOffset = (int) (totalScrollY % itemHeight);
329 | // 设置数组中每个元素的值
330 | int counter = 0;
331 | while (counter < itemsVisible) {
332 | int index = preCurrentIndex - (itemsVisible / 2 - counter);//索引值,即当前在控件中间的item看作数据源的中间,计算出相对源数据源的index值
333 |
334 | //判断是否循环,如果是循环数据源也使用相对循环的position获取对应的item值,如果不是循环则超出数据源范围使用""空白字符串填充,在界面上形成空白无数据的item项
335 | if (isLoop) {
336 | index = getLoopMappingIndex(index);
337 | visibles[counter] = adapter.getItem(index);
338 | } else if (index < 0) {
339 | visibles[counter] = "";
340 | } else if (index > adapter.getItemsCount() - 1) {
341 | visibles[counter] = "";
342 | } else {
343 | visibles[counter] = adapter.getItem(index);
344 | }
345 |
346 | counter++;
347 |
348 | }
349 |
350 | //中间两条横线
351 | canvas.drawLine(0.0F, firstLineY, measuredWidth, firstLineY, paintIndicator);
352 | canvas.drawLine(0.0F, secondLineY, measuredWidth, secondLineY, paintIndicator);
353 | //单位的Label
354 | if(label != null) {
355 | int drawRightContentStart = measuredWidth - getTextWidth(paintCenterText,label);
356 | //靠右并留出空隙
357 | canvas.drawText(label, drawRightContentStart - CENTERCONTENTOFFSET, centerY, paintCenterText);
358 | }
359 | counter = 0;
360 | while (counter < itemsVisible) {
361 | canvas.save();
362 | // L(弧长)=α(弧度)* r(半径) (弧度制)
363 | // 求弧度--> (L * π ) / (π * r) (弧长X派/半圆周长)
364 | float itemHeight = maxTextHeight * lineSpacingMultiplier;
365 | double radian = ((itemHeight * counter - itemHeightOffset) * Math.PI) / halfCircumference;
366 | // 弧度转换成角度(把半圆以Y轴为轴心向右转90度,使其处于第一象限及第四象限
367 | float angle = (float) (90D - (radian / Math.PI) * 180D);
368 | // 九十度以上的不绘制
369 | if (angle >= 90F || angle <= -90F) {
370 | canvas.restore();
371 | } else {
372 | String contentText = getContentText(visibles[counter]);
373 |
374 | //计算开始绘制的位置
375 | measuredCenterContentStart(contentText);
376 | measuredOutContentStart(contentText);
377 | float translateY = (float) (radius - Math.cos(radian) * radius - (Math.sin(radian) * maxTextHeight) / 2D);
378 | //根据Math.sin(radian)来更改canvas坐标系原点,然后缩放画布,使得文字高度进行缩放,形成弧形3d视觉差
379 | canvas.translate(0.0F, translateY);
380 | canvas.scale(1.0F, (float) Math.sin(radian));
381 | if (translateY <= firstLineY && maxTextHeight + translateY >= firstLineY) {
382 | // 条目经过第一条线
383 | canvas.save();
384 | canvas.clipRect(0, 0, measuredWidth, firstLineY - translateY);
385 | canvas.scale(1.0F, (float) Math.sin(radian) * SCALECONTENT);
386 | canvas.drawText(contentText, drawOutContentStart, maxTextHeight, paintOuterText);
387 | canvas.restore();
388 | canvas.save();
389 | canvas.clipRect(0, firstLineY - translateY, measuredWidth, (int) (itemHeight));
390 | canvas.scale(1.0F, (float) Math.sin(radian) * 1F);
391 | canvas.drawText(contentText, drawCenterContentStart, maxTextHeight - CENTERCONTENTOFFSET, paintCenterText);
392 | canvas.restore();
393 | } else if (translateY <= secondLineY && maxTextHeight + translateY >= secondLineY) {
394 | // 条目经过第二条线
395 | canvas.save();
396 | canvas.clipRect(0, 0, measuredWidth, secondLineY - translateY);
397 | canvas.scale(1.0F, (float) Math.sin(radian) * 1.0F);
398 | canvas.drawText(contentText, drawCenterContentStart, maxTextHeight - CENTERCONTENTOFFSET, paintCenterText);
399 | canvas.restore();
400 | canvas.save();
401 | canvas.clipRect(0, secondLineY - translateY, measuredWidth, (int) (itemHeight));
402 | canvas.scale(1.0F, (float) Math.sin(radian) * SCALECONTENT);
403 | canvas.drawText(contentText, drawOutContentStart, maxTextHeight, paintOuterText);
404 | canvas.restore();
405 | } else if (translateY >= firstLineY && maxTextHeight + translateY <= secondLineY) {
406 | // 中间条目
407 | canvas.clipRect(0, 0, measuredWidth, (int) (itemHeight));
408 | canvas.drawText(contentText, drawCenterContentStart, maxTextHeight - CENTERCONTENTOFFSET, paintCenterText);
409 | int preSelectedItem = adapter.indexOf(visibles[counter]);
410 | if(preSelectedItem != -1){
411 | selectedItem = preSelectedItem;
412 | }
413 | } else {
414 | // 其他条目
415 | canvas.save();
416 | canvas.clipRect(0, 0, measuredWidth, (int) (itemHeight));
417 | canvas.scale(1.0F, (float) Math.sin(radian) * SCALECONTENT);
418 | canvas.drawText(contentText, drawOutContentStart, maxTextHeight, paintOuterText);
419 | canvas.restore();
420 | }
421 | canvas.restore();
422 | }
423 | counter++;
424 | }
425 | }
426 |
427 | //递归计算出对应的index
428 | private int getLoopMappingIndex(int index){
429 | if(index < 0){
430 | index = index + adapter.getItemsCount();
431 | index = getLoopMappingIndex(index);
432 | }
433 | else if (index > adapter.getItemsCount() - 1) {
434 | index = index - adapter.getItemsCount();
435 | index = getLoopMappingIndex(index);
436 | }
437 | return index;
438 | }
439 |
440 | /**
441 | * 根据传进来的对象反射出getPickerViewText()方法,来获取需要显示的值
442 | * @param item
443 | * @return
444 | */
445 | private String getContentText(Object item) {
446 | String contentText = item.toString();
447 | try {
448 | Class> clz = item.getClass();
449 | Method m = clz.getMethod(GETPICKERVIEWTEXT);
450 | contentText = m.invoke(item, new Object[0]).toString();
451 | } catch (NoSuchMethodException e) {
452 | } catch (InvocationTargetException e) {
453 | } catch (IllegalAccessException e) {
454 | } catch (Exception e){
455 | }
456 | return contentText;
457 | }
458 |
459 | private void measuredCenterContentStart(String content) {
460 | Rect rect = new Rect();
461 | paintCenterText.getTextBounds(content, 0, content.length(), rect);
462 | switch (mGravity){
463 | case Gravity.CENTER:
464 | drawCenterContentStart = (int)((measuredWidth - rect.width()) * 0.5);
465 | break;
466 | case Gravity.LEFT:
467 | drawCenterContentStart = 0;
468 | break;
469 | case Gravity.RIGHT:
470 | drawCenterContentStart = measuredWidth - rect.width();
471 | break;
472 | }
473 | }
474 | private void measuredOutContentStart(String content) {
475 | Rect rect = new Rect();
476 | paintOuterText.getTextBounds(content, 0, content.length(), rect);
477 | switch (mGravity){
478 | case Gravity.CENTER:
479 | drawOutContentStart = (int)((measuredWidth - rect.width()) * 0.5);
480 | break;
481 | case Gravity.LEFT:
482 | drawOutContentStart = 0;
483 | break;
484 | case Gravity.RIGHT:
485 | drawOutContentStart = measuredWidth - rect.width();
486 | break;
487 | }
488 | }
489 |
490 | @Override
491 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
492 | this.widthMeasureSpec = widthMeasureSpec;
493 | remeasure();
494 | setMeasuredDimension(measuredWidth, measuredHeight);
495 | }
496 |
497 | @Override
498 | public boolean onTouchEvent(MotionEvent event) {
499 | boolean eventConsumed = gestureDetector.onTouchEvent(event);
500 | switch (event.getAction()) {
501 | case MotionEvent.ACTION_DOWN:
502 | startTime = System.currentTimeMillis();
503 | cancelFuture();
504 | previousY = event.getRawY();
505 | break;
506 |
507 | case MotionEvent.ACTION_MOVE:
508 | float dy = previousY - event.getRawY();
509 | previousY = event.getRawY();
510 | totalScrollY = (int) (totalScrollY + dy);
511 |
512 | // 边界处理。
513 | if (!isLoop) {
514 | float top = -initPosition * itemHeight;
515 | float bottom = (adapter.getItemsCount() - 1 - initPosition) * itemHeight;
516 | if(totalScrollY - itemHeight*0.3 < top){
517 | top = totalScrollY - dy;
518 | }
519 | else if(totalScrollY + itemHeight*0.3 > bottom){
520 | bottom = totalScrollY - dy;
521 | }
522 |
523 | if (totalScrollY < top) {
524 | totalScrollY = (int) top;
525 | } else if (totalScrollY > bottom) {
526 | totalScrollY = (int) bottom;
527 | }
528 | }
529 | break;
530 |
531 | case MotionEvent.ACTION_UP:
532 | default:
533 | if (!eventConsumed) {
534 | float y = event.getY();
535 | double l = Math.acos((radius - y) / radius) * radius;
536 | int circlePosition = (int) ((l + itemHeight / 2) / itemHeight);
537 |
538 | float extraOffset = (totalScrollY % itemHeight + itemHeight) % itemHeight;
539 | mOffset = (int) ((circlePosition - itemsVisible / 2) * itemHeight - extraOffset);
540 |
541 | if ((System.currentTimeMillis() - startTime) > 120) {
542 | // 处理拖拽事件
543 | smoothScroll(ACTION.DAGGLE);
544 | } else {
545 | // 处理条目点击事件
546 | smoothScroll(ACTION.CLICK);
547 | }
548 | }
549 | break;
550 | }
551 | invalidate();
552 |
553 | return true;
554 | }
555 |
556 | /**
557 | * 获取Item个数
558 | * @return
559 | */
560 | public int getItemsCount() {
561 | return adapter != null ? adapter.getItemsCount() : 0;
562 | }
563 |
564 | /**
565 | * 附加在右边的单位字符串
566 | * @param label
567 | */
568 | public void setLabel(String label){
569 | this.label = label;
570 | }
571 |
572 | public void setGravity(int gravity) {
573 | this.mGravity = gravity;
574 | }
575 |
576 | public int getTextWidth(Paint paint, String str) {
577 | int iRet = 0;
578 | if (str != null && str.length() > 0) {
579 | int len = str.length();
580 | float[] widths = new float[len];
581 | paint.getTextWidths(str, widths);
582 | for (int j = 0; j < len; j++) {
583 | iRet += (int) Math.ceil(widths[j]);
584 | }
585 | }
586 | return iRet;
587 | }
588 | }
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/listener/OnDismissListener.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.listener;
2 |
3 | /**
4 | * Created by Sai on 15/8/9.
5 | */
6 | public interface OnDismissListener {
7 | public void onDismiss(Object o);
8 | }
9 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/listener/OnItemSelectedListener.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.listener;
2 |
3 |
4 | public interface OnItemSelectedListener {
5 | void onItemSelected(int index);
6 | }
7 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/utils/PickerViewAnimateUtil.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.utils;
2 |
3 | import android.view.Gravity;
4 |
5 | import com.bigkoo.pickerview.R;
6 |
7 | /**
8 | * Created by Sai on 15/8/9.
9 | */
10 | public class PickerViewAnimateUtil {
11 | private static final int INVALID = -1;
12 | /**
13 | * Get default animation resource when not defined by the user
14 | *
15 | * @param gravity the gravity of the dialog
16 | * @param isInAnimation determine if is in or out animation. true when is is
17 | * @return the id of the animation resource
18 | */
19 | public static int getAnimationResource(int gravity, boolean isInAnimation) {
20 | switch (gravity) {
21 | case Gravity.BOTTOM:
22 | return isInAnimation ? R.anim.slide_in_bottom : R.anim.slide_out_bottom;
23 | }
24 | return INVALID;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/view/BasePickerView.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.view;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.view.Gravity;
6 | import android.view.LayoutInflater;
7 | import android.view.MotionEvent;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.view.animation.Animation;
11 | import android.view.animation.AnimationUtils;
12 | import android.widget.FrameLayout;
13 |
14 | import com.lvfq.pickerview.utils.PickerViewAnimateUtil;
15 | import com.bigkoo.pickerview.R;
16 | import com.lvfq.pickerview.listener.OnDismissListener;
17 |
18 | /**
19 | * Created by Sai on 15/11/22.
20 | * 精仿iOSPickerViewController控件
21 | */
22 | public class BasePickerView {
23 | private final FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
24 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM
25 | );
26 |
27 | private Context context;
28 | protected ViewGroup contentContainer;
29 | private ViewGroup decorView;//activity的根View
30 | private ViewGroup rootView;//附加View 的 根View
31 |
32 | private OnDismissListener onDismissListener;
33 | private boolean isDismissing;
34 |
35 | private Animation outAnim;
36 | private Animation inAnim;
37 | private int gravity = Gravity.BOTTOM;
38 |
39 | public BasePickerView(Context context){
40 | this.context = context;
41 |
42 | initViews();
43 | init();
44 | initEvents();
45 | }
46 |
47 | protected void initViews(){
48 | LayoutInflater layoutInflater = LayoutInflater.from(context);
49 | decorView = (ViewGroup) ((Activity)context).getWindow().getDecorView().findViewById(android.R.id.content);
50 | rootView = (ViewGroup) layoutInflater.inflate(R.layout.layout_basepickerview, decorView, false);
51 | rootView.setLayoutParams(new FrameLayout.LayoutParams(
52 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
53 | ));
54 | contentContainer = (ViewGroup) rootView.findViewById(R.id.content_container);
55 | contentContainer.setLayoutParams(params);
56 | }
57 |
58 | protected void init() {
59 | inAnim = getInAnimation();
60 | outAnim = getOutAnimation();
61 | }
62 | protected void initEvents() {
63 | }
64 | /**
65 | * show的时候调用
66 | *
67 | * @param view 这个View
68 | */
69 | private void onAttached(View view) {
70 | decorView.addView(view);
71 | contentContainer.startAnimation(inAnim);
72 | }
73 | /**
74 | * 添加这个View到Activity的根视图
75 | */
76 | public void show() {
77 | if (isShowing()) {
78 | return;
79 | }
80 | onAttached(rootView);
81 | }
82 | /**
83 | * 检测该View是不是已经添加到根视图
84 | *
85 | * @return 如果视图已经存在该View返回true
86 | */
87 | public boolean isShowing() {
88 | View view = decorView.findViewById(R.id.outmost_container);
89 | return view != null;
90 | }
91 | public void dismiss() {
92 | if (isDismissing) {
93 | return;
94 | }
95 |
96 | //消失动画
97 | outAnim.setAnimationListener(new Animation.AnimationListener() {
98 | @Override
99 | public void onAnimationStart(Animation animation) {
100 |
101 | }
102 |
103 | @Override
104 | public void onAnimationEnd(Animation animation) {
105 | decorView.post(new Runnable() {
106 | @Override
107 | public void run() {
108 | //从activity根视图移除
109 | decorView.removeView(rootView);
110 | isDismissing = false;
111 | if (onDismissListener != null) {
112 | onDismissListener.onDismiss(BasePickerView.this);
113 | }
114 | }
115 | });
116 | }
117 |
118 | @Override
119 | public void onAnimationRepeat(Animation animation) {
120 |
121 | }
122 | });
123 | contentContainer.startAnimation(outAnim);
124 | isDismissing = true;
125 | }
126 | public Animation getInAnimation() {
127 | int res = PickerViewAnimateUtil.getAnimationResource(this.gravity, true);
128 | return AnimationUtils.loadAnimation(context, res);
129 | }
130 |
131 | public Animation getOutAnimation() {
132 | int res = PickerViewAnimateUtil.getAnimationResource(this.gravity, false);
133 | return AnimationUtils.loadAnimation(context, res);
134 | }
135 |
136 | public BasePickerView setOnDismissListener(OnDismissListener onDismissListener) {
137 | this.onDismissListener = onDismissListener;
138 | return this;
139 | }
140 |
141 | public BasePickerView setCancelable(boolean isCancelable) {
142 | View view = rootView.findViewById(R.id.outmost_container);
143 |
144 | if (isCancelable) {
145 | view.setOnTouchListener(onCancelableTouchListener);
146 | }
147 | else{
148 | view.setOnTouchListener(null);
149 | }
150 | return this;
151 | }
152 | /**
153 | * Called when the user touch on black overlay in order to dismiss the dialog
154 | */
155 | private final View.OnTouchListener onCancelableTouchListener = new View.OnTouchListener() {
156 | @Override
157 | public boolean onTouch(View v, MotionEvent event) {
158 | if (event.getAction() == MotionEvent.ACTION_DOWN) {
159 | dismiss();
160 | }
161 | return false;
162 | }
163 | };
164 |
165 | public View findViewById(int id){
166 | return contentContainer.findViewById(id);
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/view/WheelOptions.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.view;
2 |
3 | import android.view.View;
4 |
5 | import com.bigkoo.pickerview.R;
6 | import com.lvfq.pickerview.adapter.ArrayWheelAdapter;
7 | import com.lvfq.pickerview.lib.WheelView;
8 | import com.lvfq.pickerview.listener.OnItemSelectedListener;
9 |
10 | import java.util.ArrayList;
11 |
12 | public class WheelOptions {
13 | private View view;
14 | private WheelView wv_option1;
15 | private WheelView wv_option2;
16 | private WheelView wv_option3;
17 |
18 | private ArrayList mOptions1Items;
19 | private ArrayList> mOptions2Items;
20 | private ArrayList>> mOptions3Items;
21 |
22 | private boolean linkage = false;
23 | private OnItemSelectedListener wheelListener_option1;
24 | private OnItemSelectedListener wheelListener_option2;
25 |
26 | public View getView() {
27 | return view;
28 | }
29 |
30 | public void setView(View view) {
31 | this.view = view;
32 | }
33 |
34 | public WheelOptions(View view) {
35 | super();
36 | this.view = view;
37 | setView(view);
38 | }
39 |
40 | public void setPicker(ArrayList optionsItems) {
41 | setPicker(optionsItems, null, null, false);
42 | }
43 |
44 | public void setPicker(ArrayList options1Items,
45 | ArrayList> options2Items, boolean linkage) {
46 | setPicker(options1Items, options2Items, null, linkage);
47 | }
48 |
49 | public void setPicker(ArrayList options1Items,
50 | ArrayList> options2Items,
51 | ArrayList>> options3Items,
52 | boolean linkage) {
53 | this.linkage = linkage;
54 | this.mOptions1Items = options1Items;
55 | this.mOptions2Items = options2Items;
56 | this.mOptions3Items = options3Items;
57 | int len = ArrayWheelAdapter.DEFAULT_LENGTH;
58 | if (this.mOptions3Items == null)
59 | len = 8;
60 | if (this.mOptions2Items == null)
61 | len = 12;
62 | // 选项1
63 | wv_option1 = (WheelView) view.findViewById(R.id.options1);
64 | wv_option1.setAdapter(new ArrayWheelAdapter(mOptions1Items, len));// 设置显示数据
65 | wv_option1.setCurrentItem(0);// 初始化时显示的数据
66 | // 选项2
67 | wv_option2 = (WheelView) view.findViewById(R.id.options2);
68 | if (mOptions2Items != null)
69 | wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items.get(0)));// 设置显示数据
70 | wv_option2.setCurrentItem(wv_option1.getCurrentItem());// 初始化时显示的数据
71 | // 选项3
72 | wv_option3 = (WheelView) view.findViewById(R.id.options3);
73 | if (mOptions3Items != null)
74 | wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items.get(0)
75 | .get(0)));// 设置显示数据
76 | wv_option3.setCurrentItem(wv_option3.getCurrentItem());// 初始化时显示的数据
77 |
78 | int textSize = 25;
79 |
80 | wv_option1.setTextSize(textSize);
81 | wv_option2.setTextSize(textSize);
82 | wv_option3.setTextSize(textSize);
83 |
84 | if (this.mOptions2Items == null)
85 | wv_option2.setVisibility(View.GONE);
86 | if (this.mOptions3Items == null)
87 | wv_option3.setVisibility(View.GONE);
88 |
89 | // 联动监听器
90 | wheelListener_option1 = new OnItemSelectedListener() {
91 |
92 | @Override
93 | public void onItemSelected(int index) {
94 | int opt2Select = 0;
95 | if (mOptions2Items != null) {
96 | opt2Select = wv_option2.getCurrentItem();//上一个opt2的选中位置
97 | //新opt2的位置,判断如果旧位置没有超过数据范围,则沿用旧位置,否则选中最后一项
98 | opt2Select = opt2Select >= mOptions2Items.get(index).size() - 1 ? mOptions2Items.get(index).size() - 1 : opt2Select;
99 |
100 | wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items
101 | .get(index)));
102 | wv_option2.setCurrentItem(opt2Select);
103 | }
104 | if (mOptions3Items != null) {
105 | wheelListener_option2.onItemSelected(opt2Select);
106 | }
107 | }
108 | };
109 | wheelListener_option2 = new OnItemSelectedListener() {
110 |
111 | @Override
112 | public void onItemSelected(int index) {
113 | if (mOptions3Items != null) {
114 | int opt1Select = wv_option1.getCurrentItem();
115 | opt1Select = opt1Select >= mOptions3Items.size() - 1 ? mOptions3Items.size() - 1 : opt1Select;
116 | index = index >= mOptions2Items.get(opt1Select).size() - 1 ? mOptions2Items.get(opt1Select).size() - 1 : index;
117 | int opt3 = wv_option3.getCurrentItem();//上一个opt3的选中位置
118 | //新opt3的位置,判断如果旧位置没有超过数据范围,则沿用旧位置,否则选中最后一项
119 | opt3 = opt3 >= mOptions3Items.get(opt1Select).get(index).size() - 1 ? mOptions3Items.get(opt1Select).get(index).size() - 1 : opt3;
120 |
121 | wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items
122 | .get(wv_option1.getCurrentItem()).get(
123 | index)));
124 | wv_option3.setCurrentItem(opt3);
125 |
126 | }
127 | }
128 | };
129 |
130 | // // 添加联动监听
131 | if (options2Items != null && linkage)
132 | wv_option1.setOnItemSelectedListener(wheelListener_option1);
133 | if (options3Items != null && linkage)
134 | wv_option2.setOnItemSelectedListener(wheelListener_option2);
135 | }
136 |
137 | /**
138 | * 设置选项的单位
139 | *
140 | * @param label1
141 | * @param label2
142 | * @param label3
143 | */
144 | public void setLabels(String label1, String label2, String label3) {
145 | if (label1 != null)
146 | wv_option1.setLabel(label1);
147 | if (label2 != null)
148 | wv_option2.setLabel(label2);
149 | if (label3 != null)
150 | wv_option3.setLabel(label3);
151 | }
152 |
153 | /**
154 | * 设置是否循环滚动
155 | *
156 | * @param cyclic
157 | */
158 | public void setCyclic(boolean cyclic) {
159 | wv_option1.setCyclic(cyclic);
160 | wv_option2.setCyclic(cyclic);
161 | wv_option3.setCyclic(cyclic);
162 | }
163 |
164 | /**
165 | * 分别设置第一二三级是否循环滚动
166 | *
167 | * @param cyclic1,cyclic2,cyclic3
168 | */
169 | public void setCyclic(boolean cyclic1, boolean cyclic2, boolean cyclic3) {
170 | wv_option1.setCyclic(cyclic1);
171 | wv_option2.setCyclic(cyclic2);
172 | wv_option3.setCyclic(cyclic3);
173 | }
174 |
175 | /**
176 | * 设置第二级是否循环滚动
177 | *
178 | * @param cyclic
179 | */
180 | public void setOption2Cyclic(boolean cyclic) {
181 | wv_option2.setCyclic(cyclic);
182 | }
183 |
184 | /**
185 | * 设置第三级是否循环滚动
186 | *
187 | * @param cyclic
188 | */
189 | public void setOption3Cyclic(boolean cyclic) {
190 | wv_option3.setCyclic(cyclic);
191 | }
192 |
193 | /**
194 | * 返回当前选中的结果对应的位置数组 因为支持三级联动效果,分三个级别索引,0,1,2
195 | *
196 | * @return
197 | */
198 | public int[] getCurrentItems() {
199 | int[] currentItems = new int[3];
200 | currentItems[0] = wv_option1.getCurrentItem();
201 | currentItems[1] = wv_option2.getCurrentItem();
202 | currentItems[2] = wv_option3.getCurrentItem();
203 | return currentItems;
204 | }
205 |
206 | public void setCurrentItems(int option1, int option2, int option3) {
207 | if (linkage) {
208 | itemSelected(option1, option2, option3);
209 | }
210 | wv_option1.setCurrentItem(option1);
211 | wv_option2.setCurrentItem(option2);
212 | wv_option3.setCurrentItem(option3);
213 | }
214 |
215 | private void itemSelected(int opt1Select, int opt2Select, int opt3Select) {
216 | if (mOptions2Items != null) {
217 | wv_option2.setAdapter(new ArrayWheelAdapter(mOptions2Items
218 | .get(opt1Select)));
219 | wv_option2.setCurrentItem(opt2Select);
220 | }
221 | if (mOptions3Items != null) {
222 | wv_option3.setAdapter(new ArrayWheelAdapter(mOptions3Items
223 | .get(opt1Select).get(
224 | opt2Select)));
225 | wv_option3.setCurrentItem(opt3Select);
226 | }
227 | }
228 |
229 | /**
230 | * 设置单前文字
231 | *
232 | * @param textSize
233 | */
234 | public void setTextSize(float textSize) {
235 | wv_option1.setTextSize(textSize);
236 | wv_option2.setTextSize(textSize);
237 | wv_option3.setTextSize(textSize);
238 | }
239 |
240 | }
241 |
--------------------------------------------------------------------------------
/pickerview/src/main/java/com/lvfq/pickerview/view/WheelTime.java:
--------------------------------------------------------------------------------
1 | package com.lvfq.pickerview.view;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 |
6 | import com.bigkoo.pickerview.R;
7 | import com.lvfq.pickerview.TimePickerView.Type;
8 | import com.lvfq.pickerview.adapter.NumericWheelAdapter;
9 | import com.lvfq.pickerview.lib.WheelView;
10 | import com.lvfq.pickerview.listener.OnItemSelectedListener;
11 |
12 | import java.text.DateFormat;
13 | import java.text.SimpleDateFormat;
14 | import java.util.Arrays;
15 | import java.util.List;
16 |
17 |
18 | public class WheelTime {
19 | public static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
20 | private View view;
21 | private WheelView wv_year;
22 | private WheelView wv_month;
23 | private WheelView wv_day;
24 | private WheelView wv_hours;
25 | private WheelView wv_mins;
26 |
27 | private Type type;
28 | public static final int DEFULT_START_YEAR = 1990;
29 | public static final int DEFULT_END_YEAR = 2100;
30 | private int startYear = DEFULT_START_YEAR;
31 | private int endYear = DEFULT_END_YEAR;
32 |
33 |
34 | public WheelTime(View view) {
35 | super();
36 | this.view = view;
37 | type = Type.ALL;
38 | setView(view);
39 | }
40 |
41 | public WheelTime(View view, Type type) {
42 | super();
43 | this.view = view;
44 | this.type = type;
45 | setView(view);
46 | }
47 |
48 | public void setPicker(int year, int month, int day) {
49 | this.setPicker(year, month, day, 0, 0);
50 | }
51 |
52 | /**
53 | * @Description: TODO 弹出日期时间选择器
54 | */
55 | public void setPicker(int year, int month, int day, int h, int m) {
56 | // 添加大小月月份并将其转换为list,方便之后的判断
57 | String[] months_big = {"1", "3", "5", "7", "8", "10", "12"};
58 | String[] months_little = {"4", "6", "9", "11"};
59 |
60 | final List list_big = Arrays.asList(months_big);
61 | final List list_little = Arrays.asList(months_little);
62 |
63 | Context context = view.getContext();
64 | // 年
65 | wv_year = (WheelView) view.findViewById(R.id.year);
66 | wv_year.setAdapter(new NumericWheelAdapter(startYear, endYear));// 设置"年"的显示数据
67 | wv_year.setLabel(context.getString(R.string.pickerview_year));// 添加文字
68 | wv_year.setCurrentItem(year - startYear);// 初始化时显示的数据
69 |
70 | // 月
71 | wv_month = (WheelView) view.findViewById(R.id.month);
72 | wv_month.setAdapter(new NumericWheelAdapter(1, 12));
73 | wv_month.setLabel(context.getString(R.string.pickerview_month));
74 | wv_month.setCurrentItem(month);
75 |
76 | // 日
77 | wv_day = (WheelView) view.findViewById(R.id.day);
78 | // 判断大小月及是否闰年,用来确定"日"的数据
79 | if (list_big.contains(String.valueOf(month + 1))) {
80 | wv_day.setAdapter(new NumericWheelAdapter(1, 31));
81 | } else if (list_little.contains(String.valueOf(month + 1))) {
82 | wv_day.setAdapter(new NumericWheelAdapter(1, 30));
83 | } else {
84 | // 闰年
85 | if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
86 | wv_day.setAdapter(new NumericWheelAdapter(1, 29));
87 | else
88 | wv_day.setAdapter(new NumericWheelAdapter(1, 28));
89 | }
90 | wv_day.setLabel(context.getString(R.string.pickerview_day));
91 | wv_day.setCurrentItem(day - 1);
92 |
93 |
94 | wv_hours = (WheelView) view.findViewById(R.id.hour);
95 | wv_hours.setAdapter(new NumericWheelAdapter(0, 23));
96 | wv_hours.setLabel(context.getString(R.string.pickerview_hours));// 添加文字
97 | wv_hours.setCurrentItem(h);
98 |
99 | wv_mins = (WheelView) view.findViewById(R.id.min);
100 | wv_mins.setAdapter(new NumericWheelAdapter(0, 59));
101 | wv_mins.setLabel(context.getString(R.string.pickerview_minutes));// 添加文字
102 | wv_mins.setCurrentItem(m);
103 |
104 | // 添加"年"监听
105 | OnItemSelectedListener wheelListener_year = new OnItemSelectedListener() {
106 | @Override
107 | public void onItemSelected(int index) {
108 | int year_num = index + startYear;
109 | // 判断大小月及是否闰年,用来确定"日"的数据
110 | int maxItem = 30;
111 | if (list_big
112 | .contains(String.valueOf(wv_month.getCurrentItem() + 1))) {
113 | wv_day.setAdapter(new NumericWheelAdapter(1, 31));
114 | maxItem = 31;
115 | } else if (list_little.contains(String.valueOf(wv_month
116 | .getCurrentItem() + 1))) {
117 | wv_day.setAdapter(new NumericWheelAdapter(1, 30));
118 | maxItem = 30;
119 | } else {
120 | if ((year_num % 4 == 0 && year_num % 100 != 0)
121 | || year_num % 400 == 0) {
122 | wv_day.setAdapter(new NumericWheelAdapter(1, 29));
123 | maxItem = 29;
124 | } else {
125 | wv_day.setAdapter(new NumericWheelAdapter(1, 28));
126 | maxItem = 28;
127 | }
128 | }
129 | if (wv_day.getCurrentItem() > maxItem - 1) {
130 | wv_day.setCurrentItem(maxItem - 1);
131 | }
132 | }
133 | };
134 | // 添加"月"监听
135 | OnItemSelectedListener wheelListener_month = new OnItemSelectedListener() {
136 | @Override
137 | public void onItemSelected(int index) {
138 | int month_num = index + 1;
139 | int maxItem = 30;
140 | // 判断大小月及是否闰年,用来确定"日"的数据
141 | if (list_big.contains(String.valueOf(month_num))) {
142 | wv_day.setAdapter(new NumericWheelAdapter(1, 31));
143 | maxItem = 31;
144 | } else if (list_little.contains(String.valueOf(month_num))) {
145 | wv_day.setAdapter(new NumericWheelAdapter(1, 30));
146 | maxItem = 30;
147 | } else {
148 | if (((wv_year.getCurrentItem() + startYear) % 4 == 0 && (wv_year
149 | .getCurrentItem() + startYear) % 100 != 0)
150 | || (wv_year.getCurrentItem() + startYear) % 400 == 0) {
151 | wv_day.setAdapter(new NumericWheelAdapter(1, 29));
152 | maxItem = 29;
153 | } else {
154 | wv_day.setAdapter(new NumericWheelAdapter(1, 28));
155 | maxItem = 28;
156 | }
157 | }
158 | if (wv_day.getCurrentItem() > maxItem - 1) {
159 | wv_day.setCurrentItem(maxItem - 1);
160 | }
161 |
162 | }
163 | };
164 | wv_year.setOnItemSelectedListener(wheelListener_year);
165 | wv_month.setOnItemSelectedListener(wheelListener_month);
166 |
167 | // 根据屏幕密度来指定选择器字体的大小(不同屏幕可能不同)
168 | int textSize = 5;
169 | switch (type) {
170 | case ALL:
171 | textSize = textSize * 3;
172 | break;
173 | case YEAR_MONTH_DAY:
174 | textSize = textSize * 4;
175 | wv_hours.setVisibility(View.GONE);
176 | wv_mins.setVisibility(View.GONE);
177 | break;
178 | case YEAR_MONTH_DAY_HOUR:
179 | textSize = textSize * 3;
180 | wv_mins.setVisibility(View.GONE);
181 | break;
182 | case HOURS_MINS:
183 | textSize = textSize * 4;
184 | wv_year.setVisibility(View.GONE);
185 | wv_month.setVisibility(View.GONE);
186 | wv_day.setVisibility(View.GONE);
187 | break;
188 | case MONTH_DAY_HOUR_MIN:
189 | textSize = textSize * 3;
190 | wv_year.setVisibility(View.GONE);
191 | break;
192 | case YEAR_MONTH:
193 | textSize = textSize * 4;
194 | wv_day.setVisibility(View.GONE);
195 | wv_hours.setVisibility(View.GONE);
196 | wv_mins.setVisibility(View.GONE);
197 | }
198 | setTextSize(textSize);
199 |
200 | }
201 |
202 | /**
203 | * 设置时间字体大小
204 | *
205 | * @param textSize
206 | */
207 | public void setTextSize(float textSize) {
208 | wv_day.setTextSize(textSize);
209 | wv_month.setTextSize(textSize);
210 | wv_year.setTextSize(textSize);
211 | wv_hours.setTextSize(textSize);
212 | wv_mins.setTextSize(textSize);
213 | }
214 |
215 | /**
216 | * 设置是否循环滚动
217 | *
218 | * @param cyclic
219 | */
220 | public void setCyclic(boolean cyclic) {
221 | wv_year.setCyclic(cyclic);
222 | wv_month.setCyclic(cyclic);
223 | wv_day.setCyclic(cyclic);
224 | wv_hours.setCyclic(cyclic);
225 | wv_mins.setCyclic(cyclic);
226 | }
227 |
228 | public String getTime() {
229 | StringBuffer sb = new StringBuffer();
230 | sb.append((wv_year.getCurrentItem() + startYear)).append("-")
231 | .append((wv_month.getCurrentItem() + 1)).append("-")
232 | .append((wv_day.getCurrentItem() + 1)).append(" ")
233 | .append(wv_hours.getCurrentItem()).append(":")
234 | .append(wv_mins.getCurrentItem());
235 | return sb.toString();
236 | }
237 |
238 | public View getView() {
239 | return view;
240 | }
241 |
242 | public void setView(View view) {
243 | this.view = view;
244 | }
245 |
246 | public int getStartYear() {
247 | return startYear;
248 | }
249 |
250 | public void setStartYear(int startYear) {
251 | this.startYear = startYear;
252 | }
253 |
254 | public int getEndYear() {
255 | return endYear;
256 | }
257 |
258 | public void setEndYear(int endYear) {
259 | this.endYear = endYear;
260 | }
261 | }
262 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/anim/slide_in_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/anim/slide_out_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/drawable/selector_pickerview_btn.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/layout/include_pickerview_topbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
18 |
19 |
29 |
30 |
42 |
43 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/layout/layout_basepickerview.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/layout/pickerview_options.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
18 |
19 |
25 |
26 |
31 |
32 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/layout/pickerview_time.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
18 |
19 |
24 |
25 |
30 |
31 |
36 |
37 |
42 |
43 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/values/bools.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #057dff
4 | #c2daf5
5 | #f5f5f5
6 | #000000
7 | #a8a8a8
8 | #2a2a2a
9 | #d5d5d5
10 |
11 | #60000000
12 |
13 |
14 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 44dp
4 |
5 | 10dp
6 |
7 | 30dp
8 |
9 | 20sp
10 | 21sp
11 |
12 | 20sp
13 |
14 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 300
5 |
--------------------------------------------------------------------------------
/pickerview/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 取消
4 | 确定
5 | 年
6 | 月
7 | 日
8 | 时
9 | 分
10 | 秒
11 |
12 |
--------------------------------------------------------------------------------
/preview/pickerdemo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lvfaqiang/Android-PickerView-master/52ebf7b683c32ff09585250388142ba946995c56/preview/pickerdemo.gif
--------------------------------------------------------------------------------
/preview/pickerdemo1x.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lvfaqiang/Android-PickerView-master/52ebf7b683c32ff09585250388142ba946995c56/preview/pickerdemo1x.gif
--------------------------------------------------------------------------------
/preview/pickerdemo_zhangshangshenghuo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lvfaqiang/Android-PickerView-master/52ebf7b683c32ff09585250388142ba946995c56/preview/pickerdemo_zhangshangshenghuo.gif
--------------------------------------------------------------------------------
/preview/update_picker_demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lvfaqiang/Android-PickerView-master/52ebf7b683c32ff09585250388142ba946995c56/preview/update_picker_demo.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':pickerview'
2 |
--------------------------------------------------------------------------------