Add TimePicker modes

Summary:
In the spirit of #10932, I added the `mode` option to the `TimePicker` Android API.
There is only one mode available for **Android < 5**, the `spinner` one.
If we are on **Android >= 5** we can choose between `spinner` or `clock`. If we specify `default` it will use the default of the current Android version.

On **Android < 5**, whatever we choose it will be this:
![screen shot 2017-02-14 at 17 05 44](https://cloud.githubusercontent.com/assets/5436545/22937805/024ec67e-f2da-11e6-8b32-a680d9bc2247.png)

On **Android >= 5**, with the `spinner` mode:
![screen shot 2017-02-14 at 16 51 17](https://cloud.githubusercontent.com/assets/5436545/22937803/024e0bbc-f2da-11e6-9f4b-26102ff2eeac.png)

And with the `clock` mode, the default:
![screen shot 2017-02-14 at 16 51 02](https://cloud.githubusercontent.com/assets/5436545/22937804/024e64e0-f2da-11e6-9911-4135049f4726.png)
Closes https://github.com/facebook/react-native/pull/12384

Differential Revision: D6006689

Pulled By: hramos

fbshipit-source-id: fcd37c867c4061b9982b1687f2c10211e54df7cf
This commit is contained in:
Yann Pringault 2017-10-08 12:28:10 -07:00 committed by Facebook Github Bot
parent f9be64aea0
commit 1c24440644
6 changed files with 112 additions and 13 deletions

View File

@ -44,6 +44,10 @@ class TimePickerAndroid {
* * `is24Hour` (boolean) - If `true`, the picker uses the 24-hour format. If `false`,
* the picker shows an AM/PM chooser. If undefined, the default for the current locale
* is used.
* * `mode` (`enum('clock', 'spinner', 'default')`) - set the time picker mode
* - 'clock': Show a time picker in clock mode.
* - 'spinner': Show a time picker in spinner mode.
* - 'default': Show a default time picker based on Android versions.
*
* Returns a Promise which will be invoked an object containing `action`, `hour` (0-23),
* `minute` (0-59) if the user picked a time. If the user dismissed the dialog, the Promise will

View File

@ -32,6 +32,9 @@ class TimePickerAndroidExample extends React.Component {
presetMinute: 4,
presetText: 'pick a time, default: 4:04AM',
simpleText: 'pick a time',
clockText: 'pick a time',
spinnerText: 'pick a time',
defaultText: 'pick a time',
};
showPicker = async (stateKey, options) => {
@ -60,6 +63,24 @@ class TimePickerAndroidExample extends React.Component {
<Text style={styles.text}>{this.state.simpleText}</Text>
</TouchableWithoutFeedback>
</RNTesterBlock>
<RNTesterBlock title="Simple clock time picker">
<TouchableWithoutFeedback
onPress={this.showPicker.bind(this, 'clock', {mode: 'clock'})}>
<Text style={styles.text}>{this.state.clockText}</Text>
</TouchableWithoutFeedback>
</RNTesterBlock>
<RNTesterBlock title="Simple spinner time picker">
<TouchableWithoutFeedback
onPress={this.showPicker.bind(this, 'spinner', {mode: 'spinner'})}>
<Text style={styles.text}>{this.state.spinnerText}</Text>
</TouchableWithoutFeedback>
</RNTesterBlock>
<RNTesterBlock title="Simple default time picker">
<TouchableWithoutFeedback
onPress={this.showPicker.bind(this, 'default', {mode: 'default'})}>
<Text style={styles.text}>{this.state.defaultText}</Text>
</TouchableWithoutFeedback>
</RNTesterBlock>
<RNTesterBlock title="Time picker with pre-set time">
<TouchableWithoutFeedback
onPress={this.showPicker.bind(this, 'preset', {
@ -69,7 +90,6 @@ class TimePickerAndroidExample extends React.Component {
<Text style={styles.text}>{this.state.presetText}</Text>
</TouchableWithoutFeedback>
</RNTesterBlock>
<RNTesterBlock title="Time picker with 24-hour time format">
<TouchableWithoutFeedback
onPress={this.showPicker.bind(this, 'isoFormat', {

View File

@ -9,19 +9,22 @@
package com.facebook.react.modules.timepicker;
import javax.annotation.Nullable;
import java.util.Calendar;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.TimePickerDialog;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.os.Build;
import android.os.Bundle;
import android.text.format.DateFormat;
import java.util.Calendar;
import java.util.Locale;
import javax.annotation.Nullable;
@SuppressWarnings("ValidFragment")
public class TimePickerDialogFragment extends DialogFragment {
@ -44,6 +47,11 @@ public class TimePickerDialogFragment extends DialogFragment {
int minute = now.get(Calendar.MINUTE);
boolean is24hour = DateFormat.is24HourFormat(activityContext);
TimePickerMode mode = TimePickerMode.DEFAULT;
if (args != null && args.getString(TimePickerDialogModule.ARG_MODE, null) != null) {
mode = TimePickerMode.valueOf(args.getString(TimePickerDialogModule.ARG_MODE).toUpperCase(Locale.US));
}
if (args != null) {
hour = args.getInt(TimePickerDialogModule.ARG_HOUR, now.get(Calendar.HOUR_OF_DAY));
minute = args.getInt(TimePickerDialogModule.ARG_MINUTE, now.get(Calendar.MINUTE));
@ -52,12 +60,42 @@ public class TimePickerDialogFragment extends DialogFragment {
DateFormat.is24HourFormat(activityContext));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mode == TimePickerMode.CLOCK) {
return new DismissableTimePickerDialog(
activityContext,
activityContext.getResources().getIdentifier(
"ClockTimePickerDialog",
"style",
activityContext.getPackageName()
),
onTimeSetListener,
hour,
minute,
is24hour
);
} else if (mode == TimePickerMode.SPINNER) {
return new DismissableTimePickerDialog(
activityContext,
activityContext.getResources().getIdentifier(
"SpinnerTimePickerDialog",
"style",
activityContext.getPackageName()
),
onTimeSetListener,
hour,
minute,
is24hour
);
}
}
return new DismissableTimePickerDialog(
activityContext,
onTimeSetListener,
hour,
minute,
is24hour);
activityContext,
onTimeSetListener,
hour,
minute,
is24hour
);
}
@Override

View File

@ -9,8 +9,6 @@
package com.facebook.react.modules.timepicker;
import javax.annotation.Nullable;
import android.app.Activity;
import android.app.DialogFragment;
import android.app.FragmentManager;
@ -31,6 +29,8 @@ import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.module.annotations.ReactModule;
import javax.annotation.Nullable;
/**
* {@link NativeModule} that allows JS to show a native time picker dialog and get called back when
* the user selects a time.
@ -46,6 +46,7 @@ public class TimePickerDialogModule extends ReactContextBaseJavaModule {
/* package */ static final String ARG_HOUR = "hour";
/* package */ static final String ARG_MINUTE = "minute";
/* package */ static final String ARG_IS24HOUR = "is24Hour";
/* package */ static final String ARG_MODE = "mode";
/* package */ static final String ACTION_TIME_SET = "timeSetAction";
/* package */ static final String ACTION_DISMISSED = "dismissedAction";
@ -148,6 +149,9 @@ public class TimePickerDialogModule extends ReactContextBaseJavaModule {
if (options.hasKey(ARG_IS24HOUR) && !options.isNull(ARG_IS24HOUR)) {
args.putBoolean(ARG_IS24HOUR, options.getBoolean(ARG_IS24HOUR));
}
if (options.hasKey(ARG_MODE) && !options.isNull(ARG_MODE)) {
args.putString(ARG_MODE, options.getString(ARG_MODE));
}
return args;
}
}

View File

@ -0,0 +1,17 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.modules.timepicker;
public enum TimePickerMode {
CLOCK,
SPINNER,
DEFAULT
}

View File

@ -19,7 +19,6 @@
<item name="android:datePickerMode">spinner</item>
</style>
<style name="CalendarDatePickerDialog" parent="Theme.AppCompat.Light.Dialog" tools:targetApi="lollipop">
<item name="android:datePickerStyle">@style/CalendarDatePickerStyle</item>
</style>
@ -28,4 +27,21 @@
<item name="android:datePickerMode">calendar</item>
</style>
<style name="ClockTimePickerDialog" parent="Theme.AppCompat.Light.Dialog" tools:targetApi="lollipop">
<item name="android:timePickerStyle">@style/ClockTimePickerStyle</item>
</style>
<style name="ClockTimePickerStyle" parent="android:Widget.Material.Light.TimePicker" tools:targetApi="lollipop">
<item name="android:timePickerMode">clock</item>
</style>
<style name="SpinnerTimePickerDialog" parent="Theme.AppCompat.Light.Dialog" tools:targetApi="lollipop">
<item name="android:timePickerStyle">@style/SpinnerTimePickerStyle</item>
</style>
<style name="SpinnerTimePickerStyle" parent="android:Widget.Material.Light.TimePicker" tools:targetApi="lollipop">
<item name="android:timePickerMode">spinner</item>
</style>
</resources>