Permalink
Browse files

Open source Android date and time pickers

Reviewed By: bestander

Differential Revision: D2856486

fb-gh-sync-id: 0bb81136289e2f121387649765ba682103e4701b
  • Loading branch information...
mkonicek authored and facebook-github-bot-8 committed Jan 26, 2016
1 parent 5f0ef12 commit 9a0539d2c48c528d44ddb53d6ea8343890b0ddaa
Showing with 1,275 additions and 41 deletions.
  1. +117 −0 Examples/UIExplorer/DatePickerAndroidExample.js
  2. +2 −2 Examples/UIExplorer/ListViewExample.js
  3. +8 −10 Examples/UIExplorer/PickerAndroidExample.js
  4. +2 −2 Examples/UIExplorer/RefreshControlExample.js
  5. +112 −0 Examples/UIExplorer/TimePickerAndroidExample.js
  6. +2 −0 Examples/UIExplorer/UIExplorerList.android.js
  7. +5 −5 Libraries/Components/Clipboard/Clipboard.js
  8. +84 −0 Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js
  9. +24 −0 Libraries/Components/DatePickerAndroid/DatePickerAndroid.ios.js
  10. +67 −0 Libraries/Components/TimePickerAndroid/TimePickerAndroid.android.js
  11. +24 −0 Libraries/Components/TimePickerAndroid/TimePickerAndroid.ios.js
  12. +1 −1 Libraries/Components/ToastAndroid/ToastAndroid.ios.js
  13. +2 −0 Libraries/react-native/react-native.js
  14. +2 −0 Libraries/react-native/react-native.js.flow
  15. +32 −6 ReactAndroid/src/main/java/com/facebook/react/bridge/Promise.java
  16. +13 −8 ReactAndroid/src/main/java/com/facebook/react/bridge/PromiseImpl.java
  17. +4 −5 ReactAndroid/src/main/java/com/facebook/react/modules/camera/CameraRollManager.java
  18. +20 −0 ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK
  19. +103 −0 ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java
  20. +176 −0 ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogModule.java
  21. +57 −0 ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DismissableDatePickerDialog.java
  22. +51 −0 ...tAndroid/src/main/java/com/facebook/react/modules/datepicker/SupportDatePickerDialogFragment.java
  23. +20 −0 ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/BUCK
  24. +58 −0 ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/DismissableTimePickerDialog.java
  25. +50 −0 ...tAndroid/src/main/java/com/facebook/react/modules/timepicker/SupportTimePickerDialogFragment.java
  26. +78 −0 ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/TimePickerDialogFragment.java
  27. +153 −0 ReactAndroid/src/main/java/com/facebook/react/modules/timepicker/TimePickerDialogModule.java
  28. +2 −0 ReactAndroid/src/main/java/com/facebook/react/shell/BUCK
  29. +6 −2 ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java
@@ -0,0 +1,117 @@
+/**
+ * The examples provided by Facebook are for non-commercial testing and
+ * evaluation purposes only.
+ *
+ * Facebook reserves all rights not expressly granted.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
+ * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+'use strict';
+
+var React = require('react-native');
+var {
+ DatePickerAndroid,
+ StyleSheet,
+ Text,
+ TouchableWithoutFeedback,
+} = React;
+
+var UIExplorerBlock = require('./UIExplorerBlock');
+var UIExplorerPage = require('./UIExplorerPage');
+
+var DatePickerAndroidExample = React.createClass({
+
+ statics: {
+ title: 'DatePickerAndroid',
+ description: 'Standard Android date picker dialog',
+ },
+
+ getInitialState() {
+ return {
+ presetDate: new Date(2020, 4, 5),
+ allDate: new Date(2020, 4, 5),
+ simpleText: 'pick a date',
+ minText: 'pick a date, no earlier than today',
+ maxText: 'pick a date, no later than today',
+ presetText: 'pick a date, preset to 2020/5/5',
+ allText: 'pick a date between 2020/5/1 and 2020/5/10',
+ };
+ },
+
+ async showPicker(stateKey, options) {
+ try {
+ var newState = {};
+ const {action, year, month, day} = await DatePickerAndroid.open(options);
+ if (action === DatePickerAndroid.dismissedAction) {
+ newState[stateKey + 'Text'] = 'dismissed';
+ } else {
+ var date = new Date(year, month, day);
+ newState[stateKey + 'Text'] = date.toLocaleDateString();
+ newState[stateKey + 'Date'] = date;
+ }
+ this.setState(newState);
+ } catch ({code, message}) {
+ console.warn(`Error in example '${stateKey}': `, message);
+ }
+ },
+
+ render() {
+ return (
+ <UIExplorerPage title="DatePickerAndroid">
+ <UIExplorerBlock title="Simple date picker">
+ <TouchableWithoutFeedback
+ onPress={this.showPicker.bind(this, 'simple', {date: this.state.simpleDate})}>
+ <Text style={styles.text}>{this.state.simpleText}</Text>
+ </TouchableWithoutFeedback>
+ </UIExplorerBlock>
+ <UIExplorerBlock title="Date picker with pre-set date">
+ <TouchableWithoutFeedback
+ onPress={this.showPicker.bind(this, 'preset', {date: this.state.presetDate})}>
+ <Text style={styles.text}>{this.state.presetText}</Text>
+ </TouchableWithoutFeedback>
+ </UIExplorerBlock>
+ <UIExplorerBlock title="Date picker with minDate">
+ <TouchableWithoutFeedback
+ onPress={this.showPicker.bind(this, 'min', {
+ date: this.state.minDate,
+ minDate: new Date(),
+ })}>
+ <Text style={styles.text}>{this.state.minText}</Text>
+ </TouchableWithoutFeedback>
+ </UIExplorerBlock>
+ <UIExplorerBlock title="Date picker with maxDate">
+ <TouchableWithoutFeedback
+ onPress={this.showPicker.bind(this, 'max', {
+ date: this.state.maxDate,
+ maxDate: new Date(),
+ })}>
+ <Text style={styles.text}>{this.state.maxText}</Text>
+ </TouchableWithoutFeedback>
+ </UIExplorerBlock>
+ <UIExplorerBlock title="Date picker with all options">
+ <TouchableWithoutFeedback
+ onPress={this.showPicker.bind(this, 'all', {
+ date: this.state.allDate,
+ minDate: new Date(2020, 4, 1),
+ maxDate: new Date(2020, 4, 10),
+ })}>
+ <Text style={styles.text}>{this.state.allText}</Text>
+ </TouchableWithoutFeedback>
+ </UIExplorerBlock>
+ </UIExplorerPage>
+ );
+ },
+});
+
+var styles = StyleSheet.create({
+ text: {
+ color: 'black',
+ },
+});
+
+module.exports = DatePickerAndroidExample;
@@ -30,7 +30,7 @@ var UIExplorerPage = require('./UIExplorerPage');
var ListViewSimpleExample = React.createClass({
statics: {
- title: '<ListView> - Simple',
+ title: '<ListView>',
description: 'Performant, scrollable list of data.'
},
@@ -50,7 +50,7 @@ var ListViewSimpleExample = React.createClass({
render: function() {
return (
<UIExplorerPage
- title={this.props.navigator ? null : '<ListView> - Simple'}
+ title={this.props.navigator ? null : '<ListView>'}
noSpacer={true}
noScroll={true}>
<ListView
@@ -27,6 +27,12 @@ const {
const Item = PickerAndroid.Item;
const PickerAndroidExample = React.createClass({
+
+ statics: {
+ title: '<PickerAndroid>',
+ description: 'Provides multiple options to choose from, using either a dropdown menu or a dialog.',
+ },
+
getInitialState: function() {
return {
selected1: 'key1',
@@ -124,19 +130,11 @@ const PickerAndroidExample = React.createClass({
this.setState({mode: newMode});
},
- onSelect: function(key, value) {
+ onSelect: function(key: string, value: string) {
const newState = {};
newState[key] = value;
this.setState(newState);
},
});
-exports.title = '<PickerAndroid>';
-exports.displayName = 'PickerAndroidExample';
-exports.description = 'The Android Picker component provides multiple options to choose from';
-exports.examples = [
- {
- title: 'PickerAndroidExample',
- render(): ReactElement { return <PickerAndroidExample />; }
- },
-];
+module.exports = PickerAndroidExample;
@@ -69,7 +69,7 @@ const RefreshControlExample = React.createClass({
isRefreshing: false,
loaded: 0,
rowData: Array.from(new Array(20)).map(
- (val, i) => ({text: 'Initial row' + i, clicks: 0})),
+ (val, i) => ({text: 'Initial row ' + i, clicks: 0})),
};
},
@@ -108,7 +108,7 @@ const RefreshControlExample = React.createClass({
// prepend 10 items
const rowData = Array.from(new Array(10))
.map((val, i) => ({
- text: 'Loaded row' + (+this.state.loaded + i),
+ text: 'Loaded row ' + (+this.state.loaded + i),
clicks: 0,
}))
.concat(this.state.rowData);
@@ -0,0 +1,112 @@
+/**
+ * The examples provided by Facebook are for non-commercial testing and
+ * evaluation purposes only.
+ *
+ * Facebook reserves all rights not expressly granted.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
+ * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+'use strict';
+
+var React = require('react-native');
+var {
+ TimePickerAndroid,
+ StyleSheet,
+ Text,
+ TouchableWithoutFeedback,
+} = React;
+
+var UIExplorerBlock = require('./UIExplorerBlock');
+var UIExplorerPage = require('./UIExplorerPage');
+
+var TimePickerAndroidExample = React.createClass({
+
+ statics: {
+ title: 'TimePickerAndroid',
+ description: 'Standard Android time picker dialog',
+ },
+
+ getInitialState() {
+ // *Text, *Hour and *Minute are set by successCallback -- this updates the text with the time
+ // picked by the user and makes it so the next time they open it the hour and minute they picked
+ // before is displayed.
+ return {
+ isoFormatText: 'pick a time (24-hour format)',
+ presetHour: 4,
+ presetMinute: 4,
+ presetText: 'pick a time, default: 4:04AM',
+ simpleText: 'pick a time',
+ };
+ },
+
+ async showPicker(stateKey, options) {
+ try {
+ const {action, minute, hour} = await TimePickerAndroid.open(options);
+ var newState = {};
+ if (action === TimePickerAndroid.timeSetAction) {
+ newState[stateKey + 'Text'] = _formatTime(hour, minute);
+ newState[stateKey + 'Hour'] = hour;
+ newState[stateKey + 'Minute'] = minute;
+ } else if (action === TimePickerAndroid.dismissedAction) {
+ newState[stateKey + 'Text'] = 'dismissed';
+ }
+ this.setState(newState);
+ } catch ({code, message}) {
+ console.warn(`Error in example '${stateKey}': `, message);
+ }
+ },
+
+ render() {
+ return (
+ <UIExplorerPage title="TimePickerAndroid">
+ <UIExplorerBlock title="Simple time picker">
+ <TouchableWithoutFeedback
+ onPress={this.showPicker.bind(this, 'simple')}>
+ <Text style={styles.text}>{this.state.simpleText}</Text>
+ </TouchableWithoutFeedback>
+ </UIExplorerBlock>
+ <UIExplorerBlock title="Time picker with pre-set time">
+ <TouchableWithoutFeedback
+ onPress={this.showPicker.bind(this, 'preset', {
+ hour: this.state.presetHour,
+ minute: this.state.presetMinute,
+ })}>
+ <Text style={styles.text}>{this.state.presetText}</Text>
+ </TouchableWithoutFeedback>
+ </UIExplorerBlock>
+
+ <UIExplorerBlock title="Time picker with 24-hour time format">
+ <TouchableWithoutFeedback
+ onPress={this.showPicker.bind(this, 'isoFormat', {
+ hour: this.state.isoFormatHour,
+ minute: this.state.isoFormatMinute,
+ is24Hour: true,
+ })}>
+ <Text style={styles.text}>{this.state.isoFormatText}</Text>
+ </TouchableWithoutFeedback>
+ </UIExplorerBlock>
+ </UIExplorerPage>
+ );
+ },
+});
+
+/**
+ * Returns e.g. '3:05'.
+ */
+function _formatTime(hour, minute) {
+ return hour + ':' + (minute < 10 ? '0' + minute : minute);
+}
+
+var styles = StyleSheet.create({
+ text: {
+ color: 'black',
+ },
+});
+
+module.exports = TimePickerAndroidExample;
+
@@ -47,13 +47,15 @@ var APIS = [
require('./BorderExample'),
require('./CameraRollExample'),
require('./ClipboardExample'),
+ require('./DatePickerAndroidExample'),
require('./GeolocationExample'),
require('./IntentAndroidExample.android'),
require('./LayoutEventsExample'),
require('./LayoutExample'),
require('./NetInfoExample'),
require('./PanResponderExample'),
require('./PointerEventsExample'),
+ require('./TimePickerAndroidExample'),
require('./TimerExample'),
require('./ToastAndroidExample.android'),
require('./XHRExample'),
@@ -26,10 +26,10 @@ module.exports = {
*/
getString() {
if (arguments.length > 0) {
- let callback = arguments[0];
- console.warn('Clipboard.getString(callback) is deprecated. Use the returned Promise instead');
- Clipboard.getString().then(callback);
- return;
+ let callback = arguments[0];
+ console.warn('Clipboard.getString(callback) is deprecated. Use the returned Promise instead');
+ Clipboard.getString().then(callback);
+ return;
}
return Clipboard.getString();
},
@@ -40,7 +40,7 @@ module.exports = {
* Clipboard.setString('hello world');
* }
* ```
- * @param this parameter is content that will be set into clipboard.
+ * @param the content to be stored in the clipboard.
*/
setString(content) {
Clipboard.setString(content);
Oops, something went wrong.

5 comments on commit 9a0539d

@satya164

This comment has been minimized.

Show comment
Hide comment
@satya164

satya164 Jan 26, 2016

Collaborator

🎉

Collaborator

satya164 replied Jan 26, 2016

🎉

@chandu0101

This comment has been minimized.

Show comment
Hide comment
@chandu0101

chandu0101 Jan 27, 2016

Contributor

👍

Contributor

chandu0101 replied Jan 27, 2016

👍

@xitaoque

This comment has been minimized.

Show comment
Hide comment
@xitaoque

xitaoque Feb 15, 2016

I compile the example in UIExplorer and the DatePickerAndroid and TimePickerAndroid do work.
But when I write it in my code, it doesn't work. DatePickerAndroid and TimePickerAndroid is undefined.
I noticed that under "myProject"/node_modules/react-native/Libraries/Components there are no DatePickerAndroid and TimePickerAndroid folders, so I copy them form RN source and put them there.
But still, It do not work.
What should I add to my project in order to make DatePickerAndroid and TimePickerAndroid to work?

I compile the example in UIExplorer and the DatePickerAndroid and TimePickerAndroid do work.
But when I write it in my code, it doesn't work. DatePickerAndroid and TimePickerAndroid is undefined.
I noticed that under "myProject"/node_modules/react-native/Libraries/Components there are no DatePickerAndroid and TimePickerAndroid folders, so I copy them form RN source and put them there.
But still, It do not work.
What should I add to my project in order to make DatePickerAndroid and TimePickerAndroid to work?

@xu6148152

This comment has been minimized.

Show comment
Hide comment
@xu6148152

xu6148152 Feb 17, 2016

@xitaoque
Update your RN to 0.20

@xitaoque
Update your RN to 0.20

@pickhardt

This comment has been minimized.

Show comment
Hide comment
@pickhardt

pickhardt Feb 25, 2016

Hey @mkonicek quick question - DatePickerAndroid isn't in the docs, but it looks like it's been available here for about a month. Is this something we can rely on using?

Hey @mkonicek quick question - DatePickerAndroid isn't in the docs, but it looks like it's been available here for about a month. Is this something we can rely on using?

Please sign in to comment.