PickerViewModule.java 17.8 KB
Newer Older
xwenliang's avatar
xwenliang committed
1 2 3
package com.beefe.picker;

import android.app.Activity;
4
import android.app.Dialog;
xwenliang's avatar
xwenliang committed
5
import android.graphics.Color;
6
import android.graphics.PixelFormat;
xwenliang's avatar
xwenliang committed
7 8
import android.support.annotation.Nullable;
import android.text.TextUtils;
xwenliang's avatar
xwenliang committed
9
import android.util.Log;
xwenliang's avatar
xwenliang committed
10 11
import android.view.Gravity;
import android.view.View;
12
import android.view.Window;
xwenliang's avatar
xwenliang committed
13 14 15 16 17 18 19
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.beefe.picker.view.OnSelectedListener;
import com.beefe.picker.view.PickerViewAlone;
import com.beefe.picker.view.PickerViewLinkage;
xwenliang's avatar
xwenliang committed
20
import com.beefe.picker.view.ReturnData;
xwenliang's avatar
xwenliang committed
21 22
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
xwenliang's avatar
xwenliang committed
23
import com.facebook.react.bridge.LifecycleEventListener;
xwenliang's avatar
xwenliang committed
24 25 26 27 28 29 30 31 32 33 34 35
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.util.ArrayList;

xwenliang's avatar
xwenliang committed
36 37
import static android.graphics.Color.argb;

xwenliang's avatar
xwenliang committed
38
/**
xwenliang's avatar
xwenliang committed
39
 * Author: <a href="https://github.com/shexiaoheng">heng</a>
40
 * <p>
xwenliang's avatar
xwenliang committed
41
 * Created by heng on 16/9/5.
42
 * <p>
xwenliang's avatar
xwenliang committed
43
 * Edited by heng on 16/9/22.
44 45
 * 1. PopupWindow height : full screen -> assignation
 * 2. Added pickerToolBarHeight support
46
 * <p>
47 48 49
 * Edited by heng on 2016/10/19.
 * 1. Added weights support
 * 2. Fixed return data bug
50 51 52 53 54 55 56 57 58
 * <p>
 * Edited by heng on 2016/11/16.
 * 1. Used WindowManager replace PopupWindow
 * 2. Removed method initOK() toggle() show() isPickerShow()
 * 3. Implements Application.ActivityLifecycleCallbacks
 * <p>
 * Edited by heng on 2016/11/17
 * 1. Used Dialog replace WindowManger
 * 2. Restore method show() isPickerShow()
xwenliang's avatar
xwenliang committed
59 60 61 62 63 64 65 66 67 68 69
 * <p>
 * Edited by heng on 2016/12/23
 * 1. Changed returnData type
 * 2. Added pickerToolBarFontSize
 *
 * Edited by heng on 2016/12/26
 * 1. Fixed returnData bug
 * 2. Added pickerFontColor
 * 3. Added pickerFontSize
 * 4. Used LifecycleEventListener replace Application.ActivityLifecycleCallbacks
 * 5. Fixed other bug
xwenliang's avatar
xwenliang committed
70 71
 */

xwenliang's avatar
xwenliang committed
72
public class PickerViewModule extends ReactContextBaseJavaModule implements LifecycleEventListener {
xwenliang's avatar
xwenliang committed
73 74 75 76 77

    private static final String REACT_CLASS = "BEEPickerManager";

    private static final String PICKER_DATA = "pickerData";
    private static final String SELECTED_VALUE = "selectedValue";
78

xwenliang's avatar
xwenliang committed
79
    private static final String IS_LOOP = "isLoop";
80 81 82

    private static final String WEIGHTS = "wheelFlex";

xwenliang's avatar
xwenliang committed
83
    private static final String PICKER_BG_COLOR = "pickerBg";
84

xwenliang's avatar
xwenliang committed
85 86 87
    private static final String PICKER_TOOL_BAR_BG = "pickerToolBarBg";
    private static final String PICKER_TOOL_BAR_HEIGHT = "pickerToolBarHeight";
    private static final String PICKER_TOOL_BAR_TEXT_SIZE = "pickerToolBarFontSize";
88

xwenliang's avatar
xwenliang committed
89 90
    private static final String PICKER_CONFIRM_BTN_TEXT = "pickerConfirmBtnText";
    private static final String PICKER_CONFIRM_BTN_COLOR = "pickerConfirmBtnColor";
91

xwenliang's avatar
xwenliang committed
92 93
    private static final String PICKER_CANCEL_BTN_TEXT = "pickerCancelBtnText";
    private static final String PICKER_CANCEL_BTN_COLOR = "pickerCancelBtnColor";
94

xwenliang's avatar
xwenliang committed
95 96 97 98 99
    private static final String PICKER_TITLE_TEXT = "pickerTitleText";
    private static final String PICKER_TITLE_TEXT_COLOR = "pickerTitleColor";

    private static final String PICKER_TEXT_COLOR = "pickerFontColor";
    private static final String PICKER_TEXT_SIZE = "pickerFontSize";
xwenliang's avatar
xwenliang committed
100 101 102 103 104 105 106 107

    private static final String PICKER_EVENT_NAME = "pickerEvent";
    private static final String EVENT_KEY_CONFIRM = "confirm";
    private static final String EVENT_KEY_CANCEL = "cancel";
    private static final String EVENT_KEY_SELECTED = "select";

    private static final String ERROR_NOT_INIT = "please initialize";

108
    private Dialog dialog = null;
xwenliang's avatar
xwenliang committed
109 110 111 112 113 114 115

    private boolean isLoop = true;

    private String confirmText;
    private String cancelText;
    private String titleText;

116 117
    private double[] weights;

xwenliang's avatar
xwenliang committed
118
    private ArrayList<ReturnData> returnData;
xwenliang's avatar
xwenliang committed
119

120
    private int curStatus;
xwenliang's avatar
xwenliang committed
121

xwenliang's avatar
xwenliang committed
122 123
    public PickerViewModule(ReactApplicationContext reactContext) {
        super(reactContext);
xwenliang's avatar
xwenliang committed
124
        reactContext.addLifecycleEventListener(this);
xwenliang's avatar
xwenliang committed
125 126 127 128 129 130 131 132 133 134 135
    }

    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @ReactMethod
    public void _init(ReadableMap options) {
        Activity activity = getCurrentActivity();
        if (activity != null && options.hasKey(PICKER_DATA)) {
136
            View view = activity.getLayoutInflater().inflate(R.layout.picker_view, null);
137 138 139 140
            RelativeLayout barLayout = (RelativeLayout) view.findViewById(R.id.barLayout);
            TextView cancelTV = (TextView) view.findViewById(R.id.cancel);
            TextView titleTV = (TextView) view.findViewById(R.id.title);
            TextView confirmTV = (TextView) view.findViewById(R.id.confirm);
141
            RelativeLayout pickerLayout = (RelativeLayout) view.findViewById(R.id.pickerLayout);
142 143 144 145
            final PickerViewLinkage pickerViewLinkage = (PickerViewLinkage) view.findViewById(R.id.pickerViewLinkage);
            final PickerViewAlone pickerViewAlone = (PickerViewAlone) view.findViewById(R.id.pickerViewAlone);

            int barViewHeight;
xwenliang's avatar
xwenliang committed
146
            if (options.hasKey(PICKER_TOOL_BAR_HEIGHT)) {
xwenliang's avatar
xwenliang committed
147
                try {
xwenliang's avatar
xwenliang committed
148
                    barViewHeight = options.getInt(PICKER_TOOL_BAR_HEIGHT);
xwenliang's avatar
xwenliang committed
149
                } catch (Exception e) {
xwenliang's avatar
xwenliang committed
150
                    barViewHeight = (int) options.getDouble(PICKER_TOOL_BAR_HEIGHT);
xwenliang's avatar
xwenliang committed
151
                }
xwenliang's avatar
xwenliang committed
152 153 154 155 156 157 158
            } else {
                barViewHeight = (int) (activity.getResources().getDisplayMetrics().density * 40);
            }
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
                    RelativeLayout.LayoutParams.MATCH_PARENT,
                    barViewHeight);
            barLayout.setLayoutParams(params);
xwenliang's avatar
xwenliang committed
159

xwenliang's avatar
xwenliang committed
160 161
            if (options.hasKey(PICKER_TOOL_BAR_BG)) {
                ReadableArray array = options.getArray(PICKER_TOOL_BAR_BG);
162
                int[] colors = getColor(array);
xwenliang's avatar
xwenliang committed
163
                barLayout.setBackgroundColor(argb(colors[3], colors[0], colors[1], colors[2]));
xwenliang's avatar
xwenliang committed
164 165
            }

xwenliang's avatar
xwenliang committed
166 167 168 169 170 171
            if (options.hasKey(PICKER_TOOL_BAR_TEXT_SIZE)) {
                int toolBarTextSize = options.getInt(PICKER_TOOL_BAR_TEXT_SIZE);
                cancelTV.setTextSize(toolBarTextSize);
                titleTV.setTextSize(toolBarTextSize);
                confirmTV.setTextSize(toolBarTextSize);
            }
xwenliang's avatar
xwenliang committed
172

xwenliang's avatar
xwenliang committed
173 174
            if (options.hasKey(PICKER_CONFIRM_BTN_TEXT)) {
                confirmText = options.getString(PICKER_CONFIRM_BTN_TEXT);
xwenliang's avatar
xwenliang committed
175 176 177
            }
            confirmTV.setText(!TextUtils.isEmpty(confirmText) ? confirmText : "");

xwenliang's avatar
xwenliang committed
178 179
            if (options.hasKey(PICKER_CONFIRM_BTN_COLOR)) {
                ReadableArray array = options.getArray(PICKER_CONFIRM_BTN_COLOR);
180
                int[] colors = getColor(array);
xwenliang's avatar
xwenliang committed
181
                confirmTV.setTextColor(argb(colors[3], colors[0], colors[1], colors[2]));
xwenliang's avatar
xwenliang committed
182 183 184 185
            }
            confirmTV.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
186
                    switch (curStatus) {
187 188 189 190 191 192 193
                        case 0:
                            returnData = pickerViewAlone.getSelectedData();
                            break;
                        case 1:
                            returnData = pickerViewLinkage.getSelectedData();
                            break;
                    }
xwenliang's avatar
xwenliang committed
194 195 196 197 198 199
                    commonEvent(EVENT_KEY_CONFIRM);
                    hide();
                }
            });


xwenliang's avatar
xwenliang committed
200 201
            if (options.hasKey(PICKER_TITLE_TEXT)) {
                titleText = options.getString(PICKER_TITLE_TEXT);
xwenliang's avatar
xwenliang committed
202 203
            }
            titleTV.setText(!TextUtils.isEmpty(titleText) ? titleText : "");
xwenliang's avatar
xwenliang committed
204 205
            if (options.hasKey(PICKER_TITLE_TEXT_COLOR)) {
                ReadableArray array = options.getArray(PICKER_TITLE_TEXT_COLOR);
206
                int[] colors = getColor(array);
xwenliang's avatar
xwenliang committed
207
                titleTV.setTextColor(argb(colors[3], colors[0], colors[1], colors[2]));
xwenliang's avatar
xwenliang committed
208 209
            }

xwenliang's avatar
xwenliang committed
210 211
            if (options.hasKey(PICKER_CANCEL_BTN_TEXT)) {
                cancelText = options.getString(PICKER_CANCEL_BTN_TEXT);
xwenliang's avatar
xwenliang committed
212 213
            }
            cancelTV.setText(!TextUtils.isEmpty(cancelText) ? cancelText : "");
xwenliang's avatar
xwenliang committed
214 215
            if (options.hasKey(PICKER_CANCEL_BTN_COLOR)) {
                ReadableArray array = options.getArray(PICKER_CANCEL_BTN_COLOR);
216
                int[] colors = getColor(array);
xwenliang's avatar
xwenliang committed
217
                cancelTV.setTextColor(argb(colors[3], colors[0], colors[1], colors[2]));
xwenliang's avatar
xwenliang committed
218 219 220 221
            }
            cancelTV.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
222
                    switch (curStatus) {
223 224 225 226 227 228 229
                        case 0:
                            returnData = pickerViewAlone.getSelectedData();
                            break;
                        case 1:
                            returnData = pickerViewLinkage.getSelectedData();
                            break;
                    }
xwenliang's avatar
xwenliang committed
230 231 232 233 234 235 236 237 238
                    commonEvent(EVENT_KEY_CANCEL);
                    hide();
                }
            });

            if (options.hasKey(IS_LOOP)) {
                isLoop = options.getBoolean(IS_LOOP);
            }

239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
            if (options.hasKey(WEIGHTS)) {
                ReadableArray array = options.getArray(WEIGHTS);
                weights = new double[array.size()];
                for (int i = 0; i < array.size(); i++) {
                    switch (array.getType(i).name()) {
                        case "Number":
                            try {
                                weights[i] = array.getInt(i);
                            } catch (Exception e) {
                                weights[i] = array.getDouble(i);
                            }
                            break;
                        case "String":
                            try {
                                weights[i] = Double.parseDouble(array.getString(i));
                            } catch (Exception e) {
                                weights[i] = 1.0;
                            }
                            break;
                        default:
                            weights[i] = 1.0;
                            break;
                    }
                }
            }

xwenliang's avatar
xwenliang committed
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
            String[] selectValue = {};
            if (options.hasKey(SELECTED_VALUE)) {
                ReadableArray array = options.getArray(SELECTED_VALUE);
                selectValue = new String[array.size()];
                String value = "";
                for (int i = 0; i < array.size(); i++) {
                    switch (array.getType(i).name()) {
                        case "Boolean":
                            value = String.valueOf(array.getBoolean(i));
                            break;
                        case "Number":
                            try {
                                value = String.valueOf(array.getInt(i));
                            } catch (Exception e) {
                                value = String.valueOf(array.getDouble(i));
                            }
                            break;
                        case "String":
                            value = array.getString(i);
                            break;
                    }
                    selectValue[i] = value;
                }
            }

xwenliang's avatar
xwenliang committed
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
            int pickerTextColor = 0xff000000;
            if (options.hasKey(PICKER_TEXT_COLOR)) {
                ReadableArray array = options.getArray(PICKER_TEXT_COLOR);
                int[] colors = getColor(array);
                pickerTextColor = Color.argb(colors[3], colors[0], colors[1], colors[2]);
            }

            int pickerTextSize = 16;
            if (options.hasKey(PICKER_TEXT_SIZE)) {
                try {
                    pickerTextSize = options.getInt(PICKER_TEXT_SIZE);
                } catch (Exception e) {
                    pickerTextSize = (int) options.getDouble(PICKER_TEXT_SIZE);
                }
            }

xwenliang's avatar
xwenliang committed
306 307
            ReadableArray pickerData = options.getArray(PICKER_DATA);

308
            int pickerViewHeight;
xwenliang's avatar
xwenliang committed
309 310
            String name = pickerData.getType(0).name();
            switch (name) {
xwenliang's avatar
xwenliang committed
311
                case "Map":
312
                    curStatus = 1;
xwenliang's avatar
xwenliang committed
313 314
                    pickerViewLinkage.setVisibility(View.VISIBLE);
                    pickerViewAlone.setVisibility(View.GONE);
315

316
                    pickerViewLinkage.setPickerData(pickerData, weights);
xwenliang's avatar
xwenliang committed
317 318
                    pickerViewLinkage.setTextColor(pickerTextColor);
                    pickerViewLinkage.setTextSize(pickerTextSize);
xwenliang's avatar
xwenliang committed
319
                    pickerViewLinkage.setIsLoop(isLoop);
320

xwenliang's avatar
xwenliang committed
321 322
                    pickerViewLinkage.setOnSelectListener(new OnSelectedListener() {
                        @Override
xwenliang's avatar
xwenliang committed
323
                        public void onSelected(ArrayList<ReturnData> selectedList) {
324
                            returnData = selectedList;
xwenliang's avatar
xwenliang committed
325 326 327
                            commonEvent(EVENT_KEY_SELECTED);
                        }
                    });
328
                    pickerViewLinkage.setSelectValue(selectValue);
xwenliang's avatar
xwenliang committed
329
                    pickerViewHeight = pickerViewLinkage.getViewHeight();
xwenliang's avatar
xwenliang committed
330
                    break;
xwenliang's avatar
xwenliang committed
331
                default:
332
                    curStatus = 0;
xwenliang's avatar
xwenliang committed
333 334
                    pickerViewAlone.setVisibility(View.VISIBLE);
                    pickerViewLinkage.setVisibility(View.GONE);
xwenliang's avatar
xwenliang committed
335

336
                    pickerViewAlone.setPickerData(pickerData, weights);
xwenliang's avatar
xwenliang committed
337 338
                    pickerViewAlone.setTextColor(pickerTextColor);
                    pickerViewAlone.setTextSize(pickerTextSize);
xwenliang's avatar
xwenliang committed
339 340 341 342
                    pickerViewAlone.setIsLoop(isLoop);

                    pickerViewAlone.setOnSelectedListener(new OnSelectedListener() {
                        @Override
xwenliang's avatar
xwenliang committed
343
                        public void onSelected(ArrayList<ReturnData> selectedList) {
344
                            returnData = selectedList;
xwenliang's avatar
xwenliang committed
345 346 347 348
                            commonEvent(EVENT_KEY_SELECTED);
                        }
                    });

349
                    pickerViewAlone.setSelectValue(selectValue);
xwenliang's avatar
xwenliang committed
350
                    pickerViewHeight = pickerViewAlone.getViewHeight();
xwenliang's avatar
xwenliang committed
351 352 353
                    break;
            }

354 355 356
            if (options.hasKey(PICKER_BG_COLOR)) {
                ReadableArray array = options.getArray(PICKER_BG_COLOR);
                int[] colors = getColor(array);
xwenliang's avatar
xwenliang committed
357
                pickerLayout.setBackgroundColor(argb(colors[3], colors[0], colors[1], colors[2]));
358 359
            }

xwenliang's avatar
xwenliang committed
360
            Log.d("PickerView", "pickerViewHeight = " + pickerViewHeight);
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
            int height = barViewHeight + pickerViewHeight;
            if (dialog == null) {
                dialog = new Dialog(activity, R.style.Dialog_Full_Screen);
                dialog.setContentView(view);
                WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
                Window window = dialog.getWindow();
                if (window != null) {
                    layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
                    layoutParams.format = PixelFormat.TRANSPARENT;
                    layoutParams.windowAnimations = R.style.PickerAnim;
                    layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
                    layoutParams.height = height;
                    layoutParams.gravity = Gravity.BOTTOM;
                    window.setAttributes(layoutParams);
                }
376
            } else {
377 378
                dialog.dismiss();
                dialog.setContentView(view);
xwenliang's avatar
xwenliang committed
379 380 381 382 383
            }
        }
    }

    @ReactMethod
384 385
    public void show() {
        if (dialog == null) {
xwenliang's avatar
xwenliang committed
386 387
            return;
        }
388 389
        if (!dialog.isShowing()) {
            dialog.show();
xwenliang's avatar
xwenliang committed
390 391 392 393 394
        }
    }

    @ReactMethod
    public void hide() {
395 396 397 398 399
        if (dialog == null) {
            return;
        }
        if (dialog.isShowing()) {
            dialog.dismiss();
xwenliang's avatar
xwenliang committed
400 401 402 403 404
        }
    }

    @ReactMethod
    public void isPickerShow(Callback callback) {
xwenliang's avatar
xwenliang committed
405 406
        if (callback == null)
            return;
407
        if (dialog == null) {
xwenliang's avatar
xwenliang committed
408 409
            callback.invoke(ERROR_NOT_INIT);
        } else {
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
            callback.invoke(null, dialog.isShowing());
        }
    }

    private int[] getColor(ReadableArray array) {
        int[] colors = new int[4];
        for (int i = 0; i < array.size(); i++) {
            switch (i) {
                case 0:
                case 1:
                case 2:
                    colors[i] = array.getInt(i);
                    break;
                case 3:
                    colors[i] = (int) (array.getDouble(i) * 255);
                    break;
                default:
                    break;
            }
xwenliang's avatar
xwenliang committed
429
        }
430
        return colors;
xwenliang's avatar
xwenliang committed
431 432 433 434
    }

    private void commonEvent(String eventKey) {
        WritableMap map = Arguments.createMap();
xwenliang's avatar
xwenliang committed
435 436 437 438 439 440
        map.putString("type", eventKey);
        WritableArray indexes = Arguments.createArray();
        WritableArray values = Arguments.createArray();
        for (ReturnData data : returnData) {
            indexes.pushInt(data.getIndex());
            values.pushString(data.getItem());
xwenliang's avatar
xwenliang committed
441
        }
xwenliang's avatar
xwenliang committed
442 443
        map.putArray("selectedValue", values);
        map.putArray("selectedIndex", indexes);
xwenliang's avatar
xwenliang committed
444 445 446 447 448 449 450 451 452 453
        sendEvent(getReactApplicationContext(), PICKER_EVENT_NAME, map);
    }

    private void sendEvent(ReactContext reactContext,
                           String eventName,
                           @Nullable WritableMap params) {
        reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(eventName, params);
    }
454 455

    @Override
xwenliang's avatar
xwenliang committed
456
    public void onHostResume() {
457 458 459 460

    }

    @Override
xwenliang's avatar
xwenliang committed
461
    public void onHostPause() {
462
        hide();
xwenliang's avatar
xwenliang committed
463
        dialog = null;
464 465 466
    }

    @Override
xwenliang's avatar
xwenliang committed
467
    public void onHostDestroy() {
468 469

    }
xwenliang's avatar
xwenliang committed
470
}