PickerViewModule.java 19 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

jinlongtao's avatar
jinlongtao committed
110 111 112 113
    private PickerViewLinkage pickerViewLinkage;
    private PickerViewAlone pickerViewAlone;
    private boolean isAlone = true;

xwenliang's avatar
xwenliang committed
114 115 116 117 118 119
    private boolean isLoop = true;

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

120 121
    private double[] weights;

xwenliang's avatar
xwenliang committed
122
    private ArrayList<ReturnData> returnData;
xwenliang's avatar
xwenliang committed
123

124
    private int curStatus;
xwenliang's avatar
xwenliang committed
125

xwenliang's avatar
xwenliang committed
126 127
    public PickerViewModule(ReactApplicationContext reactContext) {
        super(reactContext);
xwenliang's avatar
xwenliang committed
128
        reactContext.addLifecycleEventListener(this);
xwenliang's avatar
xwenliang committed
129 130 131 132 133 134 135 136 137 138 139
    }

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

    @ReactMethod
    public void _init(ReadableMap options) {
        Activity activity = getCurrentActivity();
        if (activity != null && options.hasKey(PICKER_DATA)) {
140
            View view = activity.getLayoutInflater().inflate(R.layout.picker_view, null);
141 142 143 144
            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);
145
            RelativeLayout pickerLayout = (RelativeLayout) view.findViewById(R.id.pickerLayout);
jinlongtao's avatar
jinlongtao committed
146 147
            pickerViewLinkage = (PickerViewLinkage) view.findViewById(R.id.pickerViewLinkage);
            pickerViewAlone = (PickerViewAlone) view.findViewById(R.id.pickerViewAlone);
148 149

            int barViewHeight;
xwenliang's avatar
xwenliang committed
150
            if (options.hasKey(PICKER_TOOL_BAR_HEIGHT)) {
xwenliang's avatar
xwenliang committed
151
                try {
xwenliang's avatar
xwenliang committed
152
                    barViewHeight = options.getInt(PICKER_TOOL_BAR_HEIGHT);
xwenliang's avatar
xwenliang committed
153
                } catch (Exception e) {
xwenliang's avatar
xwenliang committed
154
                    barViewHeight = (int) options.getDouble(PICKER_TOOL_BAR_HEIGHT);
xwenliang's avatar
xwenliang committed
155
                }
xwenliang's avatar
xwenliang committed
156 157 158 159 160 161 162
            } 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
163

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

xwenliang's avatar
xwenliang committed
170 171 172 173 174 175
            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
176

xwenliang's avatar
xwenliang committed
177 178
            if (options.hasKey(PICKER_CONFIRM_BTN_TEXT)) {
                confirmText = options.getString(PICKER_CONFIRM_BTN_TEXT);
xwenliang's avatar
xwenliang committed
179 180 181
            }
            confirmTV.setText(!TextUtils.isEmpty(confirmText) ? confirmText : "");

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


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

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

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

243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
            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
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
            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
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
            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
310 311
            ReadableArray pickerData = options.getArray(PICKER_DATA);

312
            int pickerViewHeight;
xwenliang's avatar
xwenliang committed
313 314
            String name = pickerData.getType(0).name();
            switch (name) {
xwenliang's avatar
xwenliang committed
315
                case "Map":
jinlongtao's avatar
jinlongtao committed
316
                    isAlone = false;
317
                    curStatus = 1;
xwenliang's avatar
xwenliang committed
318 319
                    pickerViewLinkage.setVisibility(View.VISIBLE);
                    pickerViewAlone.setVisibility(View.GONE);
320

321
                    pickerViewLinkage.setPickerData(pickerData, weights);
xwenliang's avatar
xwenliang committed
322 323
                    pickerViewLinkage.setTextColor(pickerTextColor);
                    pickerViewLinkage.setTextSize(pickerTextSize);
xwenliang's avatar
xwenliang committed
324
                    pickerViewLinkage.setIsLoop(isLoop);
325

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

341
                    pickerViewAlone.setPickerData(pickerData, weights);
xwenliang's avatar
xwenliang committed
342 343
                    pickerViewAlone.setTextColor(pickerTextColor);
                    pickerViewAlone.setTextSize(pickerTextSize);
xwenliang's avatar
xwenliang committed
344 345 346 347
                    pickerViewAlone.setIsLoop(isLoop);

                    pickerViewAlone.setOnSelectedListener(new OnSelectedListener() {
                        @Override
xwenliang's avatar
xwenliang committed
348
                        public void onSelected(ArrayList<ReturnData> selectedList) {
349
                            returnData = selectedList;
xwenliang's avatar
xwenliang committed
350 351 352 353
                            commonEvent(EVENT_KEY_SELECTED);
                        }
                    });

354
                    pickerViewAlone.setSelectValue(selectValue);
xwenliang's avatar
xwenliang committed
355
                    pickerViewHeight = pickerViewAlone.getViewHeight();
xwenliang's avatar
xwenliang committed
356 357 358
                    break;
            }

359 360 361
            if (options.hasKey(PICKER_BG_COLOR)) {
                ReadableArray array = options.getArray(PICKER_BG_COLOR);
                int[] colors = getColor(array);
xwenliang's avatar
xwenliang committed
362
                pickerLayout.setBackgroundColor(argb(colors[3], colors[0], colors[1], colors[2]));
363 364
            }

xwenliang's avatar
xwenliang committed
365
            Log.d("PickerView", "pickerViewHeight = " + pickerViewHeight);
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
            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);
                }
381
            } else {
382 383
                dialog.dismiss();
                dialog.setContentView(view);
xwenliang's avatar
xwenliang committed
384 385 386 387 388
            }
        }
    }

    @ReactMethod
389 390
    public void show() {
        if (dialog == null) {
xwenliang's avatar
xwenliang committed
391 392
            return;
        }
393 394
        if (!dialog.isShowing()) {
            dialog.show();
xwenliang's avatar
xwenliang committed
395 396 397 398 399
        }
    }

    @ReactMethod
    public void hide() {
400 401 402 403 404
        if (dialog == null) {
            return;
        }
        if (dialog.isShowing()) {
            dialog.dismiss();
xwenliang's avatar
xwenliang committed
405 406 407
        }
    }

jinlongtao's avatar
jinlongtao committed
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
    @ReactMethod
    public void select(ReadableArray array) {
        if (dialog != null) {
            String[] 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;
            }
            if(isAlone){
                pickerViewAlone.setSelectValue(selectValue);
            }else{
                pickerViewLinkage.setSelectValue(selectValue);
            }
        }
    }

xwenliang's avatar
xwenliang committed
439 440
    @ReactMethod
    public void isPickerShow(Callback callback) {
xwenliang's avatar
xwenliang committed
441 442
        if (callback == null)
            return;
443
        if (dialog == null) {
xwenliang's avatar
xwenliang committed
444 445
            callback.invoke(ERROR_NOT_INIT);
        } else {
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
            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
465
        }
466
        return colors;
xwenliang's avatar
xwenliang committed
467 468 469 470
    }

    private void commonEvent(String eventKey) {
        WritableMap map = Arguments.createMap();
xwenliang's avatar
xwenliang committed
471 472 473 474 475 476
        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
477
        }
xwenliang's avatar
xwenliang committed
478 479
        map.putArray("selectedValue", values);
        map.putArray("selectedIndex", indexes);
xwenliang's avatar
xwenliang committed
480 481 482 483 484 485 486 487 488 489
        sendEvent(getReactApplicationContext(), PICKER_EVENT_NAME, map);
    }

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

    @Override
xwenliang's avatar
xwenliang committed
492
    public void onHostResume() {
493 494 495 496

    }

    @Override
xwenliang's avatar
xwenliang committed
497
    public void onHostPause() {
498
        hide();
xwenliang's avatar
xwenliang committed
499
        dialog = null;
500 501 502
    }

    @Override
xwenliang's avatar
xwenliang committed
503
    public void onHostDestroy() {
jinlongtao's avatar
jinlongtao committed
504 505
        hide();
        dialog = null;
506
    }
xwenliang's avatar
xwenliang committed
507
}