├── .gitignore
├── .npmignore
├── Picker.podspec
├── README.md
├── android
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── beefe
│ │ └── picker
│ │ ├── PickerViewModule.java
│ │ ├── PickerViewPackage.java
│ │ ├── util
│ │ ├── BuildProperties.java
│ │ └── MIUIUtils.java
│ │ └── view
│ │ ├── InertiaTimerTask.java
│ │ ├── LoopView.java
│ │ ├── LoopViewGestureListener.java
│ │ ├── MessageHandler.java
│ │ ├── OnItemSelectedListener.java
│ │ ├── OnItemSelectedRunnable.java
│ │ ├── OnSelectedListener.java
│ │ ├── PickerViewAlone.java
│ │ ├── PickerViewLinkage.java
│ │ ├── ReturnData.java
│ │ └── SmoothScrollTimerTask.java
│ └── res
│ ├── anim
│ ├── picker_enter.xml
│ └── picker_exit.xml
│ ├── layout
│ ├── picker_view.xml
│ ├── picker_view_alone.xml
│ └── picker_view_linkage.xml
│ └── values
│ ├── strings.xml
│ └── styles.xml
├── doc
├── ui3.jpg
└── ui4.jpg
├── example
└── PickerTest
│ ├── .babelrc
│ ├── .buckconfig
│ ├── .flowconfig
│ ├── .gitattributes
│ ├── .gitignore
│ ├── .watchmanconfig
│ ├── PickerTest.js
│ ├── __tests__
│ └── App.js
│ ├── android
│ ├── app
│ │ ├── BUCK
│ │ ├── build.gradle
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── pickertest
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── MainApplication.java
│ │ │ └── res
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ └── values
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── keystores
│ │ ├── BUCK
│ │ └── debug.keystore.properties
│ └── settings.gradle
│ ├── app.json
│ ├── area.json
│ ├── index.js
│ ├── ios
│ ├── PickerTest-tvOS
│ │ └── Info.plist
│ ├── PickerTest-tvOSTests
│ │ └── Info.plist
│ ├── PickerTest.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ ├── PickerTest-tvOS.xcscheme
│ │ │ └── PickerTest.xcscheme
│ ├── PickerTest
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── Base.lproj
│ │ │ └── LaunchScreen.xib
│ │ ├── Images.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ └── main.m
│ └── PickerTestTests
│ │ ├── Info.plist
│ │ └── PickerTestTests.m
│ └── package.json
├── index.d.ts
├── index.js
├── ios
├── RCTBEEPickerManager.xcodeproj
│ └── project.pbxproj
└── RCTBEEPickerManager
│ ├── BzwPicker.h
│ ├── BzwPicker.m
│ ├── RCTBEEPickerManager.h
│ └── RCTBEEPickerManager.m
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 |
25 | # Android/IJ
26 | #
27 | .idea
28 | .gradle
29 | local.properties
30 |
31 | # node.js
32 | #
33 | node_modules/
34 | npm-debug.log
35 |
36 | # BUCK
37 | buck-out/
38 | \.buckd/
39 | android/app/libs
40 | android/keystores/debug.keystore
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | demo
2 | doc
3 | example
4 | .gitignore
5 |
--------------------------------------------------------------------------------
/Picker.podspec:
--------------------------------------------------------------------------------
1 | require 'json'
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4 |
5 | Pod::Spec.new do |s|
6 |
7 | s.name = 'Picker'
8 | s.version = package['version'].gsub(/v|-beta/, '')
9 | s.summary = package['description']
10 | s.author = package['author']
11 | s.license = package['license']
12 | s.homepage = package['homepage']
13 | s.source = { :git => 'https://github.com/beefe/react-native-picker.git', :tag => "v#{s.version}"}
14 | s.platform = :ios, '7.0'
15 | s.preserve_paths = '*.js'
16 |
17 | s.subspec 'Core' do |ss|
18 | ss.dependency 'React'
19 | ss.source_files = 'ios/RCTBEEPickerManager/*.{h,m}'
20 | ss.public_header_files = ['ios/RCTBEEPickerManager/*.h']
21 | end
22 |
23 | end
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-picker
2 |
3 | [](https://www.npmjs.com/package/react-native-picker)
4 |
5 | 
6 | 
7 |
8 | ### Documentation
9 |
10 | #### Params
11 |
12 | |Key | Type | Default| Support | Description |
13 | | --- | --- | ---- | ------ | ----------- |
14 | |isLoop | Boolean | false | Android | |
15 | |pickerTextEllipsisLen | number | 6 | Android | |
16 | |pickerConfirmBtnText | string | confirm | iOS/Android | |
17 | |pickerCancelBtnText | string | cancel | iOS/Android | |
18 | |pickerTitleText | string | pls select | iOS/Android | |
19 | |pickerConfirmBtnColor | array | [1, 186, 245, 1] | iOS/Android | |
20 | |pickerCancelBtnColor | array | [1, 186, 245, 1] | iOS/Android | |
21 | |pickerTitleColor | array | [20, 20, 20, 1] | iOS/Android | |
22 | |pickerToolBarBg | array | [232, 232, 232, 1] | iOS/Android | |
23 | |pickerBg | array | [196, 199, 206, 1] | iOS/Android | |
24 | |pickerToolBarFontSize | number | 16 | iOS/Android | |
25 | |wheelFlex | array | [1, 1, 1] | iOS/Android | |
26 | |pickerFontSize | number | 16 | iOS/Android | |
27 | |pickerFontColor | array | [31, 31, 31, 1] | iOS/Android | |
28 | |pickerFontFamily | string | | iOS/Android | |
29 | |pickerRowHeight | number | 24 | iOS | |
30 | |pickerData | array | | iOS/Android | |
31 | |selectedValue | array | | iOS/Android | |
32 | |onPickerConfirm | function| | iOS/Android | |
33 | |onPickerCancel | function| | iOS/Android | |
34 | |onPickerSelect | function| | iOS/Android | |
35 |
36 | #### Methods
37 |
38 | |Key | Support | Description |
39 | | --- | ---- | ----------- |
40 | |init | iOS/Android |init and pass parameters to picker |
41 | |toggle | iOS/Android |show or hide picker |
42 | |show | iOS/Android |show picker |
43 | |hide | iOS/Android |hide picker |
44 | |select | iOS/Android |select a row |
45 | |isPickerShow | iOS/Android |get status of picker, return a boolean |
46 |
47 |
48 | ### Usage
49 |
50 | #### Step 1 - install
51 |
52 | ```javascript
53 | npm install react-native-picker --save
54 | ```
55 |
56 | #### Step 2 - link
57 |
58 | ```
59 | react-native link
60 | ```
61 |
62 | #### Step 3 - import and use in project
63 |
64 | ```javascript
65 | import Picker from 'react-native-picker';
66 | let data = [];
67 | for(var i=0;i<100;i++){
68 | data.push(i);
69 | }
70 |
71 | Picker.init({
72 | pickerData: data,
73 | selectedValue: [59],
74 | onPickerConfirm: data => {
75 | console.log(data);
76 | },
77 | onPickerCancel: data => {
78 | console.log(data);
79 | },
80 | onPickerSelect: data => {
81 | console.log(data);
82 | }
83 | });
84 | Picker.show();
85 |
86 | ```
87 |
88 | ### Integration With Existing Apps (`iOS`)
89 | The `Podfile` will like below:
90 | ``` ruby
91 | platform :ios, '8.0'
92 | target 'YourTarget' do
93 | pod 'React', :path => '../YOUR_REACT_NATIVE_PROJECT/node_modules/react-native', :subspecs => [
94 | 'Core',
95 | ...
96 | ]
97 | pod 'Picker', :path => '../YOUR_REACT_NATIVE_PROJECT/node_modules/react-native-picker'
98 | end
99 | ```
100 | After you have updated the `Podfile` of the existing app, you can install `react-native-picker` like below:
101 | ``` bash
102 | $ pod install
103 | ```
104 |
105 | ### Notice
106 |
107 | #### support two modes:
108 |
109 | 1. parallel: such as time picker, wheels have no connection with each other
110 |
111 | 2. cascade: such as date picker, address picker .etc, when front wheel changed, the behind wheels will all be reset
112 |
113 | #### parallel:
114 |
115 | - single wheel:
116 |
117 | ```javascript
118 | pickerData = [1,2,3,4];
119 | selectedValue = 3;
120 | ```
121 |
122 | - two or more wheel:
123 |
124 | ```javascript
125 | pickerData = [
126 | [1,2,3,4],
127 | [5,6,7,8],
128 | ...
129 | ];
130 | selectedValue = [1, 5];
131 | ```
132 |
133 | #### cascade:
134 |
135 | - two wheel
136 |
137 | ```javascript
138 | pickerData = [
139 | {
140 | a: [1, 2, 3, 4]
141 | },
142 | {
143 | b: [5, 6, 7, 8]
144 | },
145 | ...
146 | ];
147 | selectedValue = ['a', 2];
148 | ```
149 |
150 | - three wheel
151 |
152 | ```javascript
153 | pickerData = [
154 | {
155 | a: [
156 | {
157 | a1: [1, 2, 3, 4]
158 | },
159 | {
160 | a2: [5, 6, 7, 8]
161 | },
162 | {
163 | a3: [9, 10, 11, 12]
164 | }
165 | ]
166 | },
167 | {
168 | b: [
169 | {
170 | b1: [11, 22, 33, 44]
171 | },
172 | {
173 | b2: [55, 66, 77, 88]
174 | },
175 | {
176 | b3: [99, 1010, 1111, 1212]
177 | }
178 | ]
179 | },
180 | {
181 | c: [
182 | {
183 | c1: ['a', 'b', 'c']
184 | },
185 | {
186 | c2: ['aa', 'bb', 'cc']
187 | },
188 | {
189 | c3: ['aaa', 'bbb', 'ccc']
190 | }
191 | ]
192 | },
193 | ...
194 | ]
195 | ```
196 |
197 | ### For pure javascript version -> [v3.0.5](https://github.com/beefe/react-native-picker/tree/pure-javascript-version)
198 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 27
5 | buildToolsVersion "23.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 16
9 | targetSdkVersion 27
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 |
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | implementation fileTree(include: ['*.jar'], dir: 'libs')
26 | implementation 'com.facebook.react:react-native:+'
27 | }
28 |
--------------------------------------------------------------------------------
/android/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/heng/Desktop/android-sdk-macosx/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 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/android/src/main/java/com/beefe/picker/PickerViewModule.java:
--------------------------------------------------------------------------------
1 | package com.beefe.picker;
2 |
3 | import android.content.res.AssetManager;
4 | import android.app.Activity;
5 | import android.app.Dialog;
6 | import android.graphics.Color;
7 | import android.graphics.PixelFormat;
8 | import android.graphics.Typeface;
9 | import android.support.annotation.Nullable;
10 | import android.text.TextUtils;
11 | import android.view.Gravity;
12 | import android.view.View;
13 | import android.view.Window;
14 | import android.view.WindowManager;
15 | import android.widget.RelativeLayout;
16 | import android.widget.TextView;
17 | import android.os.Build;
18 |
19 | import com.beefe.picker.util.MIUIUtils;
20 | import com.beefe.picker.view.OnSelectedListener;
21 | import com.beefe.picker.view.PickerViewAlone;
22 | import com.beefe.picker.view.PickerViewLinkage;
23 | import com.beefe.picker.view.ReturnData;
24 | import com.facebook.react.bridge.Arguments;
25 | import com.facebook.react.bridge.Callback;
26 | import com.facebook.react.bridge.LifecycleEventListener;
27 | import com.facebook.react.bridge.ReactApplicationContext;
28 | import com.facebook.react.bridge.ReactContext;
29 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
30 | import com.facebook.react.bridge.ReactMethod;
31 | import com.facebook.react.bridge.ReadableArray;
32 | import com.facebook.react.bridge.ReadableMap;
33 | import com.facebook.react.bridge.WritableArray;
34 | import com.facebook.react.bridge.WritableMap;
35 | import com.facebook.react.modules.core.DeviceEventManagerModule;
36 |
37 | import java.util.ArrayList;
38 |
39 | import static android.graphics.Color.argb;
40 |
41 | /**
42 | * Author: heng
43 | *
44 | * Created by heng on 16/9/5.
45 | *
46 | * Edited by heng on 16/9/22.
47 | * 1. PopupWindow height : full screen -> assignation
48 | * 2. Added pickerToolBarHeight support
49 | *
50 | * Edited by heng on 2016/10/19.
51 | * 1. Added weights support
52 | * 2. Fixed return data bug
53 | *
54 | * Edited by heng on 2016/11/16.
55 | * 1. Used WindowManager replace PopupWindow
56 | * 2. Removed method initOK() toggle() show() isPickerShow()
57 | * 3. Implements Application.ActivityLifecycleCallbacks
58 | *
59 | * Edited by heng on 2016/11/17
60 | * 1. Used Dialog replace WindowManger
61 | * 2. Restore method show() isPickerShow()
62 | *
63 | * Edited by heng on 2016/12/23
64 | * 1. Changed returnData type
65 | * 2. Added pickerToolBarFontSize
66 | *
67 | * Edited by heng on 2016/12/26
68 | * 1. Fixed returnData bug
69 | * 2. Added pickerFontColor
70 | * 3. Added pickerFontSize
71 | * 4. Used LifecycleEventListener replace Application.ActivityLifecycleCallbacks
72 | * 5. Fixed other bug
73 | *
74 | * Edited by heng on 2017/01/17
75 | * 1. Added select(ReadableArray array, Callback callback)
76 | * 2. Optimization code
77 | */
78 |
79 | public class PickerViewModule extends ReactContextBaseJavaModule implements LifecycleEventListener {
80 |
81 | private static final String FONTS = "fonts/";
82 | private static final String OTF = ".otf";
83 | private static final String TTF = ".ttf";
84 |
85 | private static final String REACT_CLASS = "BEEPickerManager";
86 |
87 | private static final String PICKER_DATA = "pickerData";
88 | private static final String SELECTED_VALUE = "selectedValue";
89 |
90 | private static final String IS_LOOP = "isLoop";
91 |
92 | private static final String WEIGHTS = "wheelFlex";
93 |
94 | private static final String PICKER_BG_COLOR = "pickerBg";
95 |
96 | private static final String PICKER_TOOL_BAR_BG = "pickerToolBarBg";
97 | private static final String PICKER_TOOL_BAR_HEIGHT = "pickerToolBarHeight";
98 | private static final String PICKER_TOOL_BAR_TEXT_SIZE = "pickerToolBarFontSize";
99 |
100 | private static final String PICKER_CONFIRM_BTN_TEXT = "pickerConfirmBtnText";
101 | private static final String PICKER_CONFIRM_BTN_COLOR = "pickerConfirmBtnColor";
102 |
103 | private static final String PICKER_CANCEL_BTN_TEXT = "pickerCancelBtnText";
104 | private static final String PICKER_CANCEL_BTN_COLOR = "pickerCancelBtnColor";
105 |
106 | private static final String PICKER_TITLE_TEXT = "pickerTitleText";
107 | private static final String PICKER_TITLE_TEXT_COLOR = "pickerTitleColor";
108 |
109 | private static final String PICKER_TEXT_COLOR = "pickerFontColor";
110 | private static final String PICKER_TEXT_SIZE = "pickerFontSize";
111 | private static final String PICKER_TEXT_ELLIPSIS_LEN = "pickerTextEllipsisLen";
112 |
113 | private static final String PICKER_FONT_FAMILY = "pickerFontFamily";
114 |
115 | private static final String PICKER_EVENT_NAME = "pickerEvent";
116 | private static final String EVENT_KEY_CONFIRM = "confirm";
117 | private static final String EVENT_KEY_CANCEL = "cancel";
118 | private static final String EVENT_KEY_SELECTED = "select";
119 |
120 | private static final String ERROR_NOT_INIT = "please initialize the component first";
121 |
122 | private Dialog dialog = null;
123 |
124 | private boolean isLoop = true;
125 |
126 | private String confirmText;
127 | private String cancelText;
128 | private String titleText;
129 | private int pickerTextEllipsisLen;
130 |
131 | private double[] weights;
132 |
133 | private ArrayList returnData;
134 |
135 | private int curStatus;
136 |
137 | private PickerViewLinkage pickerViewLinkage;
138 | private PickerViewAlone pickerViewAlone;
139 |
140 | public PickerViewModule(ReactApplicationContext reactContext) {
141 | super(reactContext);
142 | reactContext.addLifecycleEventListener(this);
143 | }
144 |
145 | @Override
146 | public String getName() {
147 | return REACT_CLASS;
148 | }
149 |
150 | @ReactMethod
151 | public void _init(ReadableMap options) {
152 | Activity activity = getCurrentActivity();
153 | if (activity != null && options.hasKey(PICKER_DATA)) {
154 | View view = activity.getLayoutInflater().inflate(R.layout.picker_view, null);
155 | RelativeLayout barLayout = (RelativeLayout) view.findViewById(R.id.barLayout);
156 | TextView cancelTV = (TextView) view.findViewById(R.id.cancel);
157 | TextView titleTV = (TextView) view.findViewById(R.id.title);
158 | TextView confirmTV = (TextView) view.findViewById(R.id.confirm);
159 | RelativeLayout pickerLayout = (RelativeLayout) view.findViewById(R.id.pickerLayout);
160 | pickerViewLinkage = (PickerViewLinkage) view.findViewById(R.id.pickerViewLinkage);
161 | pickerViewAlone = (PickerViewAlone) view.findViewById(R.id.pickerViewAlone);
162 |
163 | int barViewHeight;
164 | if (options.hasKey(PICKER_TOOL_BAR_HEIGHT)) {
165 | try {
166 | barViewHeight = options.getInt(PICKER_TOOL_BAR_HEIGHT);
167 | } catch (Exception e) {
168 | barViewHeight = (int) options.getDouble(PICKER_TOOL_BAR_HEIGHT);
169 | }
170 | } else {
171 | barViewHeight = (int) (activity.getResources().getDisplayMetrics().density * 40);
172 | }
173 | RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
174 | RelativeLayout.LayoutParams.MATCH_PARENT,
175 | barViewHeight);
176 | barLayout.setLayoutParams(params);
177 |
178 | if (options.hasKey(PICKER_TOOL_BAR_BG)) {
179 | ReadableArray array = options.getArray(PICKER_TOOL_BAR_BG);
180 | int[] colors = getColor(array);
181 | barLayout.setBackgroundColor(argb(colors[3], colors[0], colors[1], colors[2]));
182 | }
183 |
184 | if (options.hasKey(PICKER_TOOL_BAR_TEXT_SIZE)) {
185 | int toolBarTextSize = options.getInt(PICKER_TOOL_BAR_TEXT_SIZE);
186 | cancelTV.setTextSize(toolBarTextSize);
187 | titleTV.setTextSize(toolBarTextSize);
188 | confirmTV.setTextSize(toolBarTextSize);
189 | }
190 |
191 | if (options.hasKey(PICKER_CONFIRM_BTN_TEXT)) {
192 | confirmText = options.getString(PICKER_CONFIRM_BTN_TEXT);
193 | }
194 | confirmTV.setText(!TextUtils.isEmpty(confirmText) ? confirmText : "");
195 |
196 | if (options.hasKey(PICKER_CONFIRM_BTN_COLOR)) {
197 | ReadableArray array = options.getArray(PICKER_CONFIRM_BTN_COLOR);
198 | int[] colors = getColor(array);
199 | confirmTV.setTextColor(argb(colors[3], colors[0], colors[1], colors[2]));
200 | }
201 | confirmTV.setOnClickListener(new View.OnClickListener() {
202 | @Override
203 | public void onClick(View v) {
204 | switch (curStatus) {
205 | case 0:
206 | returnData = pickerViewAlone.getSelectedData();
207 | break;
208 | case 1:
209 | returnData = pickerViewLinkage.getSelectedData();
210 | break;
211 | }
212 | commonEvent(EVENT_KEY_CONFIRM);
213 | hide();
214 | }
215 | });
216 |
217 |
218 | if (options.hasKey(PICKER_TITLE_TEXT)) {
219 | titleText = options.getString(PICKER_TITLE_TEXT);
220 | }
221 | titleTV.setText(!TextUtils.isEmpty(titleText) ? titleText : "");
222 | if (options.hasKey(PICKER_TITLE_TEXT_COLOR)) {
223 | ReadableArray array = options.getArray(PICKER_TITLE_TEXT_COLOR);
224 | int[] colors = getColor(array);
225 | titleTV.setTextColor(argb(colors[3], colors[0], colors[1], colors[2]));
226 | }
227 |
228 | if (options.hasKey(PICKER_CANCEL_BTN_TEXT)) {
229 | cancelText = options.getString(PICKER_CANCEL_BTN_TEXT);
230 | }
231 | cancelTV.setText(!TextUtils.isEmpty(cancelText) ? cancelText : "");
232 | if (options.hasKey(PICKER_CANCEL_BTN_COLOR)) {
233 | ReadableArray array = options.getArray(PICKER_CANCEL_BTN_COLOR);
234 | int[] colors = getColor(array);
235 | cancelTV.setTextColor(argb(colors[3], colors[0], colors[1], colors[2]));
236 | }
237 | cancelTV.setOnClickListener(new View.OnClickListener() {
238 | @Override
239 | public void onClick(View v) {
240 | switch (curStatus) {
241 | case 0:
242 | returnData = pickerViewAlone.getSelectedData();
243 | break;
244 | case 1:
245 | returnData = pickerViewLinkage.getSelectedData();
246 | break;
247 | }
248 | commonEvent(EVENT_KEY_CANCEL);
249 | hide();
250 | }
251 | });
252 |
253 | if(options.hasKey(PICKER_TEXT_ELLIPSIS_LEN)){
254 | pickerTextEllipsisLen = options.getInt(PICKER_TEXT_ELLIPSIS_LEN);
255 | }
256 |
257 | if (options.hasKey(IS_LOOP)) {
258 | isLoop = options.getBoolean(IS_LOOP);
259 | }
260 |
261 | if (options.hasKey(WEIGHTS)) {
262 | ReadableArray array = options.getArray(WEIGHTS);
263 | weights = new double[array.size()];
264 | for (int i = 0; i < array.size(); i++) {
265 | switch (array.getType(i).name()) {
266 | case "Number":
267 | try {
268 | weights[i] = array.getInt(i);
269 | } catch (Exception e) {
270 | weights[i] = array.getDouble(i);
271 | }
272 | break;
273 | case "String":
274 | try {
275 | weights[i] = Double.parseDouble(array.getString(i));
276 | } catch (Exception e) {
277 | weights[i] = 1.0;
278 | }
279 | break;
280 | default:
281 | weights[i] = 1.0;
282 | break;
283 | }
284 | }
285 | }
286 |
287 | int pickerTextColor = 0xff000000;
288 | if (options.hasKey(PICKER_TEXT_COLOR)) {
289 | ReadableArray array = options.getArray(PICKER_TEXT_COLOR);
290 | int[] colors = getColor(array);
291 | pickerTextColor = Color.argb(colors[3], colors[0], colors[1], colors[2]);
292 | }
293 |
294 | int pickerTextSize = 16;
295 | if (options.hasKey(PICKER_TEXT_SIZE)) {
296 | try {
297 | pickerTextSize = options.getInt(PICKER_TEXT_SIZE);
298 | } catch (Exception e) {
299 | pickerTextSize = (int) options.getDouble(PICKER_TEXT_SIZE);
300 | }
301 | }
302 |
303 | ReadableArray pickerData = options.getArray(PICKER_DATA);
304 |
305 | int pickerViewHeight;
306 | String name = pickerData.getType(0).name();
307 | switch (name) {
308 | case "Map":
309 | curStatus = 1;
310 | pickerViewLinkage.setVisibility(View.VISIBLE);
311 | pickerViewAlone.setVisibility(View.GONE);
312 |
313 | pickerViewLinkage.setPickerData(pickerData, weights);
314 | pickerViewLinkage.setTextColor(pickerTextColor);
315 | pickerViewLinkage.setTextSize(pickerTextSize);
316 | pickerViewLinkage.setTextEllipsisLen(pickerTextEllipsisLen);
317 | pickerViewLinkage.setIsLoop(isLoop);
318 |
319 | pickerViewLinkage.setOnSelectListener(new OnSelectedListener() {
320 | @Override
321 | public void onSelected(ArrayList selectedList) {
322 | returnData = selectedList;
323 | commonEvent(EVENT_KEY_SELECTED);
324 | }
325 | });
326 | pickerViewHeight = pickerViewLinkage.getViewHeight();
327 | break;
328 | default:
329 | curStatus = 0;
330 | pickerViewAlone.setVisibility(View.VISIBLE);
331 | pickerViewLinkage.setVisibility(View.GONE);
332 |
333 | pickerViewAlone.setPickerData(pickerData, weights);
334 | pickerViewAlone.setTextColor(pickerTextColor);
335 | pickerViewAlone.setTextSize(pickerTextSize);
336 | pickerViewAlone.setTextEllipsisLen(pickerTextEllipsisLen);
337 | pickerViewAlone.setIsLoop(isLoop);
338 |
339 | pickerViewAlone.setOnSelectedListener(new OnSelectedListener() {
340 | @Override
341 | public void onSelected(ArrayList selectedList) {
342 | returnData = selectedList;
343 | commonEvent(EVENT_KEY_SELECTED);
344 | }
345 | });
346 |
347 | pickerViewHeight = pickerViewAlone.getViewHeight();
348 | break;
349 | }
350 |
351 | if (options.hasKey(PICKER_FONT_FAMILY)) {
352 | Typeface typeface = null;
353 | AssetManager assetManager = activity.getApplicationContext().getAssets();
354 | final String fontFamily = options.getString(PICKER_FONT_FAMILY);
355 | try {
356 | String path = FONTS + fontFamily + TTF;
357 | typeface = Typeface.createFromAsset(assetManager, path);
358 | } catch (Exception ignored) {
359 | try {
360 | String path = FONTS + fontFamily + OTF;
361 | typeface = Typeface.createFromAsset(assetManager, path);
362 | } catch (Exception ignored2) {
363 | try {
364 | typeface = Typeface.create(fontFamily, Typeface.NORMAL);
365 | } catch (Exception ignored3) {
366 | }
367 | }
368 | }
369 | cancelTV.setTypeface(typeface);
370 | titleTV.setTypeface(typeface);
371 | confirmTV.setTypeface(typeface);
372 |
373 | pickerViewAlone.setTypeface(typeface);
374 | pickerViewLinkage.setTypeface(typeface);
375 | }
376 |
377 | if (options.hasKey(SELECTED_VALUE)) {
378 | ReadableArray array = options.getArray(SELECTED_VALUE);
379 | String[] selectedValue = getSelectedValue(array);
380 | select(selectedValue);
381 | }
382 |
383 | if (options.hasKey(PICKER_BG_COLOR)) {
384 | ReadableArray array = options.getArray(PICKER_BG_COLOR);
385 | int[] colors = getColor(array);
386 | pickerLayout.setBackgroundColor(argb(colors[3], colors[0], colors[1], colors[2]));
387 | }
388 |
389 | int height = barViewHeight + pickerViewHeight;
390 | if (dialog == null) {
391 | dialog = new Dialog(activity, R.style.Dialog_Full_Screen);
392 | dialog.setContentView(view);
393 | WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
394 | Window window = dialog.getWindow();
395 | if (window != null) {
396 | if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
397 | window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
398 | }else{
399 | if (MIUIUtils.isMIUI()) {
400 | layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION;
401 | }else {
402 | //layoutParams.type = WindowManager.LayoutParams.TYPE_TOAST;
403 | }
404 | }
405 | layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
406 | layoutParams.format = PixelFormat.TRANSPARENT;
407 | layoutParams.windowAnimations = R.style.PickerAnim;
408 | layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
409 | layoutParams.height = height;
410 | layoutParams.gravity = Gravity.BOTTOM;
411 | window.setAttributes(layoutParams);
412 | }
413 | } else {
414 | dialog.dismiss();
415 | dialog.setContentView(view);
416 | }
417 | }
418 | }
419 |
420 | @ReactMethod
421 | public void select(ReadableArray array, Callback callback) {
422 | if (dialog == null) {
423 | if (callback != null) {
424 | callback.invoke(ERROR_NOT_INIT);
425 | }
426 | return;
427 | }
428 | String[] selectedValue = getSelectedValue(array);
429 | select(selectedValue);
430 | }
431 |
432 | @ReactMethod
433 | public void show() {
434 | if (dialog == null) {
435 | return;
436 | }
437 | if (!dialog.isShowing()) {
438 | dialog.show();
439 | }
440 | }
441 |
442 | @ReactMethod
443 | public void hide() {
444 | if (dialog == null) {
445 | return;
446 | }
447 | if (dialog.isShowing()) {
448 | dialog.dismiss();
449 | }
450 | }
451 |
452 | @ReactMethod
453 | public void isPickerShow(Callback callback) {
454 | if (callback == null)
455 | return;
456 | if (dialog == null) {
457 | callback.invoke(ERROR_NOT_INIT);
458 | } else {
459 | callback.invoke(null, dialog.isShowing());
460 | }
461 | }
462 |
463 | private int[] getColor(ReadableArray array) {
464 | int[] colors = new int[4];
465 | for (int i = 0; i < array.size(); i++) {
466 | switch (i) {
467 | case 0:
468 | case 1:
469 | case 2:
470 | colors[i] = array.getInt(i);
471 | break;
472 | case 3:
473 | colors[i] = (int) (array.getDouble(i) * 255);
474 | break;
475 | default:
476 | break;
477 | }
478 | }
479 | return colors;
480 | }
481 |
482 | private String[] getSelectedValue(ReadableArray array) {
483 | String[] selectValue = new String[array.size()];
484 | String value = "";
485 | for (int i = 0; i < array.size(); i++) {
486 | switch (array.getType(i).name()) {
487 | case "Boolean":
488 | value = String.valueOf(array.getBoolean(i));
489 | break;
490 | case "Number":
491 | try {
492 | value = String.valueOf(array.getInt(i));
493 | } catch (Exception e) {
494 | value = String.valueOf(array.getDouble(i));
495 | }
496 | break;
497 | case "String":
498 | value = array.getString(i);
499 | break;
500 | }
501 | selectValue[i] = value;
502 | }
503 | return selectValue;
504 | }
505 |
506 | private void select(String[] selectedValue) {
507 | switch (curStatus) {
508 | case 0:
509 | pickerViewAlone.setSelectValue(selectedValue);
510 | break;
511 | case 1:
512 | pickerViewLinkage.setSelectValue(selectedValue);
513 | break;
514 | }
515 | }
516 |
517 | private void commonEvent(String eventKey) {
518 | WritableMap map = Arguments.createMap();
519 | map.putString("type", eventKey);
520 | WritableArray indexes = Arguments.createArray();
521 | WritableArray values = Arguments.createArray();
522 | for (ReturnData data : returnData) {
523 | indexes.pushInt(data.getIndex());
524 | values.pushString(data.getItem());
525 | }
526 | map.putArray("selectedValue", values);
527 | map.putArray("selectedIndex", indexes);
528 | sendEvent(getReactApplicationContext(), PICKER_EVENT_NAME, map);
529 | }
530 |
531 | private void sendEvent(ReactContext reactContext,
532 | String eventName,
533 | @Nullable WritableMap params) {
534 | reactContext
535 | .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
536 | .emit(eventName, params);
537 | }
538 |
539 | @Override
540 | public void onHostResume() {
541 |
542 | }
543 |
544 | @Override
545 | public void onHostPause() {
546 | hide();
547 | dialog = null;
548 | }
549 |
550 | @Override
551 | public void onHostDestroy() {
552 | hide();
553 | dialog = null;
554 | }
555 | }
556 |
--------------------------------------------------------------------------------
/android/src/main/java/com/beefe/picker/PickerViewPackage.java:
--------------------------------------------------------------------------------
1 | package com.beefe.picker;
2 |
3 | import com.facebook.react.ReactPackage;
4 | import com.facebook.react.bridge.JavaScriptModule;
5 | import com.facebook.react.bridge.NativeModule;
6 | import com.facebook.react.bridge.ReactApplicationContext;
7 | import com.facebook.react.uimanager.ViewManager;
8 |
9 | import java.util.Arrays;
10 | import java.util.Collections;
11 | import java.util.List;
12 |
13 | /**
14 | * Created by heng on 16/9/5.
15 | */
16 |
17 | public class PickerViewPackage implements ReactPackage {
18 |
19 | @Override
20 | public List createNativeModules(ReactApplicationContext reactContext) {
21 | return Arrays.asList(new PickerViewModule(reactContext));
22 | }
23 |
24 | // Deprecated RN 0.47
25 | public List> createJSModules() {
26 | return Collections.emptyList();
27 | }
28 |
29 | @Override
30 | public List createViewManagers(ReactApplicationContext reactContext) {
31 | return Collections.emptyList();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/android/src/main/java/com/beefe/picker/util/BuildProperties.java:
--------------------------------------------------------------------------------
1 | package com.beefe.picker.util;
2 |
3 | /**
4 | * Created by geezer. on 2017/9/21.
5 | */
6 |
7 | import android.os.Environment;
8 |
9 | import java.io.File;
10 | import java.io.FileInputStream;
11 | import java.io.IOException;
12 | import java.util.Collection;
13 | import java.util.Enumeration;
14 | import java.util.Map.Entry;
15 | import java.util.Properties;
16 | import java.util.Set;
17 |
18 |
19 | public class BuildProperties {
20 |
21 | private final Properties properties;
22 |
23 | private BuildProperties() throws IOException {
24 | properties = new Properties();
25 | properties.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));
26 | }
27 |
28 | public boolean containsKey(final Object key) {
29 | return properties.containsKey(key);
30 | }
31 |
32 | public boolean containsValue(final Object value) {
33 | return properties.containsValue(value);
34 | }
35 |
36 | public Set> entrySet() {
37 | return properties.entrySet();
38 | }
39 |
40 | public String getProperty(final String name) {
41 | return properties.getProperty(name);
42 | }
43 |
44 | public String getProperty(final String name, final String defaultValue) {
45 | return properties.getProperty(name, defaultValue);
46 | }
47 |
48 | public boolean isEmpty() {
49 | return properties.isEmpty();
50 | }
51 |
52 | public Enumeration