Skip to content

Commit eaccd7e

Browse files
pandiaraj44Facebook Github Bot
authored and
Facebook Github Bot
committed
Android datepicker mode configurations added
Summary: Currently, The **DatePickerAndroid** component opens the native date picker with default mode. We can't able to change the mode via configurations. To support android **[date-picker mode](https://developer.android.com/reference/android/widget/DatePicker.html)**, existing component needs to be changed. **For Android >= 5.0**, The DatePickerDialog doesn't provide the default method to change the mode of a date picker. So I have added custom theme which will support two kinds of **mode('spinner','calendar')** ref:https://developer.android.com/reference/android/R.attr.html#datePickerStyle. **For Android < 5.0,** The DatePickerDialog provides the default method to change the mode of a date picker. ref:https://developer.android.com/reference/android/widget/DatePicker.html#setCalendarViewShown(boolean). With the help of **Build.VERSION.SDK_INT** I have done the above functionality with limited lines of code changes and also I have added the example to UIExplorer. Closes #10932 Differential Revision: D4176089 Pulled By: ericvicenti fbshipit-source-id: 7dfa9101214501ac2124bda7ee273a538f04e7cf
1 parent d196ca7 commit eaccd7e

File tree

6 files changed

+109
-3
lines changed

6 files changed

+109
-3
lines changed

Examples/UIExplorer/js/DatePickerAndroidExample.js

+21
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class DatePickerAndroidExample extends React.Component {
4040
presetDate: new Date(2020, 4, 5),
4141
allDate: new Date(2020, 4, 5),
4242
simpleText: 'pick a date',
43+
spinnerText: 'pick a date',
44+
calendarText: 'pick a date',
45+
defaultText: 'pick a date',
4346
minText: 'pick a date, no earlier than today',
4447
maxText: 'pick a date, no later than today',
4548
presetText: 'pick a date, preset to 2020/5/5',
@@ -72,6 +75,24 @@ class DatePickerAndroidExample extends React.Component {
7275
<Text style={styles.text}>{this.state.simpleText}</Text>
7376
</TouchableWithoutFeedback>
7477
</UIExplorerBlock>
78+
<UIExplorerBlock title="Simple spinner date picker">
79+
<TouchableWithoutFeedback
80+
onPress={this.showPicker.bind(this, 'spinner', {date: this.state.spinnerDate, mode: 'spinner'})}>
81+
<Text style={styles.text}>{this.state.spinnerText}</Text>
82+
</TouchableWithoutFeedback>
83+
</UIExplorerBlock>
84+
<UIExplorerBlock title="Simple calendar date picker">
85+
<TouchableWithoutFeedback
86+
onPress={this.showPicker.bind(this, 'calendar', {date: this.state.calendarDate, mode: 'calendar'})}>
87+
<Text style={styles.text}>{this.state.calendarText}</Text>
88+
</TouchableWithoutFeedback>
89+
</UIExplorerBlock>
90+
<UIExplorerBlock title="Simple default date picker">
91+
<TouchableWithoutFeedback
92+
onPress={this.showPicker.bind(this, 'default', {date: this.state.defaultDate, mode: 'default'})}>
93+
<Text style={styles.text}>{this.state.defaultText}</Text>
94+
</TouchableWithoutFeedback>
95+
</UIExplorerBlock>
7596
<UIExplorerBlock title="Date picker with pre-set date">
7697
<TouchableWithoutFeedback
7798
onPress={this.showPicker.bind(this, 'preset', {date: this.state.presetDate})}>

Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js

+4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class DatePickerAndroid {
5252
* * `date` (`Date` object or timestamp in milliseconds) - date to show by default
5353
* * `minDate` (`Date` or timestamp in milliseconds) - minimum date that can be selected
5454
* * `maxDate` (`Date` object or timestamp in milliseconds) - minimum date that can be selected
55+
* * `mode` (`enum('calendar', 'spinner', 'default')`) - To set the date-picker mode to calendar/spinner/default
56+
* - 'calendar': Show a date picker in calendar mode.
57+
* - 'spinner': Show a date picker in spinner mode.
58+
* - 'default': Show a default native date picker(spinner/calendar) based on android versions.
5559
*
5660
* Returns a Promise which will be invoked an object containing `action`, `year`, `month` (0-11),
5761
* `day` if the user picked a date. If the user dismissed the dialog, the Promise will

ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java

+39-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import javax.annotation.Nullable;
1313

1414
import java.util.Calendar;
15+
import java.util.Locale;
1516

1617
import android.annotation.SuppressLint;
1718
import android.app.DatePickerDialog;
@@ -21,6 +22,7 @@
2122
import android.content.Context;
2223
import android.content.DialogInterface;
2324
import android.content.DialogInterface.OnDismissListener;
25+
import android.os.Build;
2426
import android.os.Bundle;
2527
import android.widget.DatePicker;
2628

@@ -53,8 +55,43 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {
5355
final int month = c.get(Calendar.MONTH);
5456
final int day = c.get(Calendar.DAY_OF_MONTH);
5557

56-
final DatePickerDialog dialog =
57-
new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day);
58+
DatePickerMode mode = DatePickerMode.DEFAULT;
59+
if (args != null && args.getString(DatePickerDialogModule.ARG_MODE, null) != null) {
60+
mode = DatePickerMode.valueOf(args.getString(DatePickerDialogModule.ARG_MODE).toUpperCase(Locale.US));
61+
}
62+
63+
DatePickerDialog dialog = null;
64+
65+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
66+
switch (mode) {
67+
case CALENDAR:
68+
dialog = new DismissableDatePickerDialog(activityContext,
69+
activityContext.getResources().getIdentifier("CalendarDatePickerDialog", "style", activityContext.getPackageName()),
70+
onDateSetListener, year, month, day);
71+
break;
72+
case SPINNER:
73+
dialog = new DismissableDatePickerDialog(activityContext,
74+
activityContext.getResources().getIdentifier("SpinnerDatePickerDialog", "style", activityContext.getPackageName()),
75+
onDateSetListener, year, month, day);
76+
break;
77+
case DEFAULT:
78+
dialog = new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day);
79+
break;
80+
}
81+
} else {
82+
dialog = new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day);
83+
84+
switch (mode) {
85+
case CALENDAR:
86+
dialog.getDatePicker().setCalendarViewShown(true);
87+
dialog.getDatePicker().setSpinnersShown(false);
88+
break;
89+
case SPINNER:
90+
dialog.getDatePicker().setCalendarViewShown(false);
91+
break;
92+
}
93+
}
94+
5895
final DatePicker datePicker = dialog.getDatePicker();
5996

6097
if (args != null && args.containsKey(DatePickerDialogModule.ARG_MINDATE)) {

ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogModule.java

+7
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public class DatePickerDialogModule extends ReactContextBaseJavaModule {
4848
/* package */ static final String ARG_DATE = "date";
4949
/* package */ static final String ARG_MINDATE = "minDate";
5050
/* package */ static final String ARG_MAXDATE = "maxDate";
51+
/* package */ static final String ARG_MODE = "mode";
5152

5253
/* package */ static final String ACTION_DATE_SET = "dateSetAction";
5354
/* package */ static final String ACTION_DISMISSED = "dismissedAction";
@@ -109,6 +110,9 @@ public void onDismiss(DialogInterface dialog) {
109110
* {@code maxDate} (timestamp in milliseconds) the maximum date the user should be allowed
110111
* to select
111112
* </li>
113+
* <li>
114+
* {@code mode} To set the date picker mode to 'calendar/spinner/default'
115+
* </li>
112116
* </ul>
113117
*
114118
* @param promise This will be invoked with parameters action, year,
@@ -173,6 +177,9 @@ private Bundle createFragmentArguments(ReadableMap options) {
173177
if (options.hasKey(ARG_MAXDATE) && !options.isNull(ARG_MAXDATE)) {
174178
args.putLong(ARG_MAXDATE, (long) options.getDouble(ARG_MAXDATE));
175179
}
180+
if (options.hasKey(ARG_MODE) && !options.isNull(ARG_MODE)) {
181+
args.putString(ARG_MODE, options.getString(ARG_MODE));
182+
}
176183
return args;
177184
}
178185
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
package com.facebook.react.modules.datepicker;
11+
12+
/**
13+
* Date picker modes
14+
*/
15+
public enum DatePickerMode {
16+
CALENDAR,
17+
SPINNER,
18+
DEFAULT
19+
}

ReactAndroid/src/main/res/shell/values/styles.xml

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<resources>
2+
<resources xmlns:tools="http://schemas.android.com/tools">
33
<style name="Theme.ReactNative.AppCompat.Light" parent="@style/Theme.AppCompat.Light.NoActionBar">
44
<item name="android:textColor">@android:color/black</item>
55
</style>
@@ -10,4 +10,22 @@
1010
<item name="android:windowFullscreen">true</item>
1111
<item name="android:windowContentOverlay">@null</item>
1212
</style>
13+
14+
<style name="SpinnerDatePickerDialog" parent="Theme.AppCompat.Light.Dialog" tools:targetApi="lollipop">
15+
<item name="android:datePickerStyle">@style/SpinnerDatePickerStyle</item>
16+
</style>
17+
18+
<style name="SpinnerDatePickerStyle" parent="android:Widget.Material.Light.DatePicker" tools:targetApi="lollipop">
19+
<item name="android:datePickerMode">spinner</item>
20+
</style>
21+
22+
23+
<style name="CalendarDatePickerDialog" parent="Theme.AppCompat.Light.Dialog" tools:targetApi="lollipop">
24+
<item name="android:datePickerStyle">@style/CalendarDatePickerStyle</item>
25+
</style>
26+
27+
<style name="CalendarDatePickerStyle" parent="android:Widget.Material.Light.DatePicker" tools:targetApi="lollipop">
28+
<item name="android:datePickerMode">calendar</item>
29+
</style>
30+
1331
</resources>

0 commit comments

Comments
 (0)