From e0d3649ba1b3d2f5b0e7361301ac38606a3ec04e Mon Sep 17 00:00:00 2001 From: Daniel Maly Date: Sat, 7 Jan 2017 22:47:06 +0100 Subject: [PATCH 1/4] Fixed to work under new versions React Native (tested on 0.38) --- index.android.js | 5 +- package.json | 6 +- .../RNNumberPicker.java | 85 +++++++++++++++++++ .../RNNumberPickerManager.java | 72 ++++++++++++++++ .../RNNumberPickerPackage.java | 29 +++++++ 5 files changed, 190 insertions(+), 7 deletions(-) create mode 100644 src/main/java/io/fixd/reactnativenumberpicker/RNNumberPicker.java create mode 100644 src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerManager.java create mode 100644 src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerPackage.java diff --git a/index.android.js b/index.android.js index 47b1fe7..281f8f8 100644 --- a/index.android.js +++ b/index.android.js @@ -1,4 +1,4 @@ -import { Component, PropTypes } from 'react'; +import React, { Component, PropTypes } from 'react'; import { requireNativeComponent, View} from 'react-native'; var REF_PICKER = 'numberpicker'; @@ -28,9 +28,6 @@ class NumberPicker extends Component { if (this.props.onSelect) this.props.onSelect(event.nativeEvent.value); - if (this.refs[REF_PICKER] && this.state.selectedIndex !== event.nativeEvent.value) - this.refs[REF_PICKER].setNativeProps({selected: this.state.selectedIndex}); - } render() { diff --git a/package.json b/package.json index fe0af59..9766437 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "react-native-numberpicker", - "version": "0.0.4", + "version": "0.0.5", "description": "React Native Android NumberPicker", "repository": { "type": "git", - "url": "https://github.com/fixd/react-native-numberpicker.git" + "url": "https://github.com/Symphony9/react-native-numberpicker" }, - "author": "Fixd", + "author": "DanielMaly", "license": "MIT" } \ No newline at end of file diff --git a/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPicker.java b/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPicker.java new file mode 100644 index 0000000..49c2d2f --- /dev/null +++ b/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPicker.java @@ -0,0 +1,85 @@ +package io.fixd.reactnativenumberpicker; + +import javax.annotation.Nullable; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.AdapterView; +import android.widget.NumberPicker; +import android.widget.EditText; +import android.graphics.Color; + +public class RNNumberPicker extends NumberPicker { + + private @Nullable OnChangeListener mOnChangeListener; + private boolean mSuppressNextEvent; + private @Nullable Integer mStagedSelection; + private @Nullable Integer mTextSize; + private @Nullable Integer mTextColor; + + /** + * Listener interface for events. + */ + public interface OnChangeListener { + void onValueChange(int value); + } + + public RNNumberPicker(Context context) { + super(context); + } + + public RNNumberPicker(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public RNNumberPicker(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } + + public void setOnChangeListener(@Nullable OnChangeListener onValueChangeListener) { + setOnValueChangedListener( + new OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + if (!mSuppressNextEvent && mOnChangeListener != null) { + mOnChangeListener.onValueChange(newVal); + } + mSuppressNextEvent = false; + } + } + ); + mOnChangeListener = onValueChangeListener; + } + + @Nullable public OnChangeListener getOnChangeListener() { + return mOnChangeListener; + } + + /** + * Will cache "selection" value locally and set it only once {@link #updateStagedSelection} is + * called + */ + public void setStagedSelection(int selection) { + mStagedSelection = selection; + } + + public void updateStagedSelection() { + if (mStagedSelection != null) { + setValueWithSuppressEvent(mStagedSelection); + mStagedSelection = null; + } + } + + /** + * Set the selection while suppressing the follow-up event. + * This is used so we don't get an event when changing the selection ourselves. + * + * @param value + */ + private void setValueWithSuppressEvent(int value) { + if (value != getValue()) { + mSuppressNextEvent = true; + setValue(value); + } + } + +} diff --git a/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerManager.java b/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerManager.java new file mode 100644 index 0000000..5d6bd8f --- /dev/null +++ b/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerManager.java @@ -0,0 +1,72 @@ +package io.fixd.reactnativenumberpicker; + +import javax.annotation.Nullable; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.uimanager.annotations.ReactProp; +import com.facebook.react.uimanager.SimpleViewManager; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.common.SystemClock; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.uimanager.UIProp; +import com.facebook.react.uimanager.ViewProps; +import com.facebook.react.uimanager.events.RCTEventEmitter; + +import java.lang.Integer; +import java.lang.String; + +public class RNNumberPickerManager extends SimpleViewManager + implements RNNumberPicker.OnChangeListener { + + public static final String REACT_CLASS = "RNNumberPicker"; + + private RNNumberPicker view; + + @Override + public String getName() { + return REACT_CLASS; + } + + @Override + protected RNNumberPicker createViewInstance(ThemedReactContext reactContext) { + this.view = new RNNumberPicker(reactContext); + return this.view; + } + + @ReactProp(name = "values") + public void setValues(RNNumberPicker view, @Nullable ReadableArray items) { + String[] displayValues = new String[items.size()]; + for (int i = 0; i < items.size(); i++) { + displayValues[i] = (String) items.getString(i); + } + + view.setMinValue(0); + view.setMaxValue(displayValues.length - 1); + view.setDisplayedValues(displayValues); + } + + @ReactProp(name = "selected") + public void setValue(RNNumberPicker view, Integer selected) { + view.setValue(selected); + } + + @Override + protected void addEventEmitters(final ThemedReactContext reactContext, final RNNumberPicker picker) { + picker.setOnChangeListener(this); + } + + @Override + public void onValueChange(int value) { + WritableMap event = Arguments.createMap(); + event.putInt("value", value); + ReactContext reactContext = (ReactContext) view.getContext(); + reactContext.getJSModule(RCTEventEmitter.class) + .receiveEvent(view.getId(), "topChange", event); + } + + +} diff --git a/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerPackage.java b/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerPackage.java new file mode 100644 index 0000000..63f1938 --- /dev/null +++ b/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerPackage.java @@ -0,0 +1,29 @@ +package io.fixd.reactnativenumberpicker; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class RNNumberPickerPackage implements ReactPackage { + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { return Collections.emptyList(); } + + @Override + public List> createJSModules() { + return Collections.emptyList(); + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Arrays.asList( + new RNNumberPickerManager() + ); + } +} From 04ebfa8297fd44c8721b75071d9d5297ccb5812c Mon Sep 17 00:00:00 2001 From: Daniel Maly Date: Sat, 7 Jan 2017 22:48:54 +0100 Subject: [PATCH 2/4] Deleted obsoleted files --- .../io/fixd/numberpicker/RNNumberPicker.java | 85 ------------------- .../RNNumberPickerChangeEvent.java | 33 ------- .../numberpicker/RNNumberPickerManager.java | 77 ----------------- .../numberpicker/RNNumberPickerPackage.java | 29 ------- 4 files changed, 224 deletions(-) delete mode 100644 src/main/java/io/fixd/numberpicker/RNNumberPicker.java delete mode 100644 src/main/java/io/fixd/numberpicker/RNNumberPickerChangeEvent.java delete mode 100644 src/main/java/io/fixd/numberpicker/RNNumberPickerManager.java delete mode 100644 src/main/java/io/fixd/numberpicker/RNNumberPickerPackage.java diff --git a/src/main/java/io/fixd/numberpicker/RNNumberPicker.java b/src/main/java/io/fixd/numberpicker/RNNumberPicker.java deleted file mode 100644 index 49c2d2f..0000000 --- a/src/main/java/io/fixd/numberpicker/RNNumberPicker.java +++ /dev/null @@ -1,85 +0,0 @@ -package io.fixd.reactnativenumberpicker; - -import javax.annotation.Nullable; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; -import android.widget.AdapterView; -import android.widget.NumberPicker; -import android.widget.EditText; -import android.graphics.Color; - -public class RNNumberPicker extends NumberPicker { - - private @Nullable OnChangeListener mOnChangeListener; - private boolean mSuppressNextEvent; - private @Nullable Integer mStagedSelection; - private @Nullable Integer mTextSize; - private @Nullable Integer mTextColor; - - /** - * Listener interface for events. - */ - public interface OnChangeListener { - void onValueChange(int value); - } - - public RNNumberPicker(Context context) { - super(context); - } - - public RNNumberPicker(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public RNNumberPicker(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } - - public void setOnChangeListener(@Nullable OnChangeListener onValueChangeListener) { - setOnValueChangedListener( - new OnValueChangeListener() { - @Override - public void onValueChange(NumberPicker picker, int oldVal, int newVal) { - if (!mSuppressNextEvent && mOnChangeListener != null) { - mOnChangeListener.onValueChange(newVal); - } - mSuppressNextEvent = false; - } - } - ); - mOnChangeListener = onValueChangeListener; - } - - @Nullable public OnChangeListener getOnChangeListener() { - return mOnChangeListener; - } - - /** - * Will cache "selection" value locally and set it only once {@link #updateStagedSelection} is - * called - */ - public void setStagedSelection(int selection) { - mStagedSelection = selection; - } - - public void updateStagedSelection() { - if (mStagedSelection != null) { - setValueWithSuppressEvent(mStagedSelection); - mStagedSelection = null; - } - } - - /** - * Set the selection while suppressing the follow-up event. - * This is used so we don't get an event when changing the selection ourselves. - * - * @param value - */ - private void setValueWithSuppressEvent(int value) { - if (value != getValue()) { - mSuppressNextEvent = true; - setValue(value); - } - } - -} diff --git a/src/main/java/io/fixd/numberpicker/RNNumberPickerChangeEvent.java b/src/main/java/io/fixd/numberpicker/RNNumberPickerChangeEvent.java deleted file mode 100644 index 1ad091f..0000000 --- a/src/main/java/io/fixd/numberpicker/RNNumberPickerChangeEvent.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.fixd.reactnativenumberpicker; - -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.uimanager.events.Event; -import com.facebook.react.uimanager.events.RCTEventEmitter; - -public class RNNumberPickerChangeEvent extends Event { - public static final String EVENT_NAME = "topChange"; - - private final int mValue; - - public RNNumberPickerChangeEvent(int id, long uptimeMillis, int value) { - super(id, uptimeMillis); - mValue = value; - } - - @Override - public String getEventName() { - return EVENT_NAME; - } - - @Override - public void dispatch(RCTEventEmitter rctEventEmitter) { - rctEventEmitter.receiveEvent(getViewTag(), getEventName(), serializeEventData()); - } - - private WritableMap serializeEventData() { - WritableMap eventData = Arguments.createMap(); - eventData.putInt("value", mValue); - return eventData; - } -} \ No newline at end of file diff --git a/src/main/java/io/fixd/numberpicker/RNNumberPickerManager.java b/src/main/java/io/fixd/numberpicker/RNNumberPickerManager.java deleted file mode 100644 index 5cbc007..0000000 --- a/src/main/java/io/fixd/numberpicker/RNNumberPickerManager.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.fixd.reactnativenumberpicker; - -import javax.annotation.Nullable; - -import com.facebook.react.uimanager.annotations.ReactProp; -import com.facebook.react.uimanager.SimpleViewManager; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.events.EventDispatcher; -import com.facebook.react.uimanager.UIManagerModule; -import com.facebook.react.common.SystemClock; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.uimanager.UIProp; -import com.facebook.react.uimanager.ViewProps; - -import java.lang.Integer; -import java.lang.String; - -public class RNNumberPickerManager extends SimpleViewManager { - - public static final String REACT_CLASS = "RNNumberPicker"; - - @Override - public String getName() { - return REACT_CLASS; - } - - @Override - protected RNNumberPicker createViewInstance(ThemedReactContext reactContext) { - return new RNNumberPicker(reactContext); - } - - @ReactProp(name = "values") - public void setValues(RNNumberPicker view, @Nullable ReadableArray items) { - String[] displayValues = new String[items.size()]; - for (int i = 0; i < items.size(); i++) { - displayValues[i] = (String) items.getString(i); - } - - view.setMinValue(0); - view.setMaxValue(displayValues.length - 1); - view.setDisplayedValues(displayValues); - } - - @ReactProp(name = "selected") - public void setValue(RNNumberPicker view, Integer selected) { - view.setValue(selected); - } - - @Override - protected void addEventEmitters(final ThemedReactContext reactContext, final RNNumberPicker picker) { - picker.setOnChangeListener( - new RNNumberPickerEventEmitter( - picker, - reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher() - ) - ); - } - - private static class RNNumberPickerEventEmitter implements RNNumberPicker.OnChangeListener { - - private final RNNumberPicker mRNNumberPicker; - private final EventDispatcher mEventDispatcher; - - public RNNumberPickerEventEmitter(RNNumberPicker reactNumberPicker, EventDispatcher eventDispatcher) { - mRNNumberPicker = reactNumberPicker; - mEventDispatcher = eventDispatcher; - } - - @Override - public void onValueChange(int value) { - mEventDispatcher.dispatchEvent( - new RNNumberPickerChangeEvent(mRNNumberPicker.getId(), SystemClock.nanoTime(), value) - ); - } - } - -} diff --git a/src/main/java/io/fixd/numberpicker/RNNumberPickerPackage.java b/src/main/java/io/fixd/numberpicker/RNNumberPickerPackage.java deleted file mode 100644 index 63f1938..0000000 --- a/src/main/java/io/fixd/numberpicker/RNNumberPickerPackage.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.fixd.reactnativenumberpicker; - -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.JavaScriptModule; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class RNNumberPickerPackage implements ReactPackage { - - @Override - public List createNativeModules(ReactApplicationContext reactContext) { return Collections.emptyList(); } - - @Override - public List> createJSModules() { - return Collections.emptyList(); - } - - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - return Arrays.asList( - new RNNumberPickerManager() - ); - } -} From adaf71eb484f248d09f99c4aa2b852ad65a91f50 Mon Sep 17 00:00:00 2001 From: Daniel Maly Date: Sun, 8 Jan 2017 10:59:57 +0100 Subject: [PATCH 3/4] Reverted package.json changes --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9766437..522fa0b 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "description": "React Native Android NumberPicker", "repository": { "type": "git", - "url": "https://github.com/Symphony9/react-native-numberpicker" + "url": "https://github.com/fixd/react-native-numberpicker.git" }, - "author": "DanielMaly", + "author": "Fixd", "license": "MIT" } \ No newline at end of file From d56df4aee9bd2e7012c7d35c7731573243cbbb08 Mon Sep 17 00:00:00 2001 From: Daniel Maly Date: Sun, 8 Jan 2017 18:29:31 +0100 Subject: [PATCH 4/4] Added the option to disable keyboard input into the picker --- README.md | 1 + index.android.js | 4 +++- .../reactnativenumberpicker/RNNumberPicker.java | 14 +++++++++++++- .../RNNumberPickerManager.java | 5 +++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2c3b852..79cc9c3 100644 --- a/README.md +++ b/README.md @@ -47,5 +47,6 @@ let NumberPicker = require('react-native-numberpicker'); onSelect={(value) => { console.log('onSelect', value); }} + keyboardInputEnabled={true} /> ``` \ No newline at end of file diff --git a/index.android.js b/index.android.js index 281f8f8..10a6877 100644 --- a/index.android.js +++ b/index.android.js @@ -41,7 +41,7 @@ class NumberPicker extends Component { onChange={this._onChange} style={[{height:this.props.height}, style && style]} {...otherProps} - /> + /> ); } } @@ -49,6 +49,7 @@ class NumberPicker extends Component { NumberPicker.defaultProps = { selectedIndex: 0, height: 100, + keyboardInputEnabled: true }; NumberPicker.propTypes = { @@ -57,6 +58,7 @@ NumberPicker.propTypes = { selectedIndex: PropTypes.number, values: PropTypes.arrayOf(PropTypes.string).isRequired, onSelect: PropTypes.func, + keyboardInputEnabled: PropTypes.bool }; var NativeNumberPicker = requireNativeComponent('RNNumberPicker', NumberPicker, { diff --git a/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPicker.java b/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPicker.java index 49c2d2f..5d0b890 100644 --- a/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPicker.java +++ b/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPicker.java @@ -33,7 +33,19 @@ public RNNumberPicker(Context context, AttributeSet attrs) { super(context, attrs); } - public RNNumberPicker(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } + public RNNumberPicker(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public void setKeyboardInputEnabled(boolean enabled) { + if(!enabled) { + this.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); + } + else { + this.setDescendantFocusability(NumberPicker.FOCUS_AFTER_DESCENDANTS); + } + } + public void setOnChangeListener(@Nullable OnChangeListener onValueChangeListener) { setOnValueChangedListener( diff --git a/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerManager.java b/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerManager.java index 5d6bd8f..cc4b70b 100644 --- a/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerManager.java +++ b/src/main/java/io/fixd/reactnativenumberpicker/RNNumberPickerManager.java @@ -54,6 +54,11 @@ public void setValue(RNNumberPicker view, Integer selected) { view.setValue(selected); } + @ReactProp(name = "keyboardInputEnabled") + public void setKeyboardInputEnabled(RNNumberPicker view, Boolean enabled) { + view.setKeyboardInputEnabled(enabled); + } + @Override protected void addEventEmitters(final ThemedReactContext reactContext, final RNNumberPicker picker) { picker.setOnChangeListener(this);