Skip to content

Conversation

@pandiaraj44
Copy link
Contributor

@pandiaraj44 pandiaraj44 commented Nov 14, 2016

Motivation

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, existing component needs to be changed.

Solution

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.

Test Plan

When opening a date picker on Android, We need to pass the option value(mode: 'calendar/spinner/default').

Example1:

DatePickerAndroid.open({ date: Date.now(), mode: 'calendar'}) // It will open datepicker with calendar mode

Android < 5.0
android_j 5 0 _calendar

Android >= 5.0
android_m 5 0 _calendar

Example2:
DatePickerAndroid.open({ date: Date.now(), mode: 'spinner'}) // It will open datepicker with spinner mode

Android < 5.0
android_j 5 0 _spinner

Android >= 5.0
android_m 5 0 _spinner

Example3:

DatePickerAndroid.open({ date: Date.now()})
(or)
DatePickerAndroid.open({ date: Date.now(), mode: 'default'})
// It will open datepicker with default native mode based on android versions.

Android < 5.0
android_j 5 0 _spinner

Android >= 5.0
android_m 5 0 _calendar

So If the user doesn't give mode option then default mode will be shown.

For real-time testing, you can run UIExplorer android project. I have added example code.
screenshot_20161119-123805

@facebook-github-bot
Copy link
Contributor

By analyzing the blame information on this pull request, we identified @spicyj and @AaaChiuuu to be potential reviewers.

@facebook-github-bot facebook-github-bot added GH Review: review-needed CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. labels Nov 14, 2016
@ericvicenti
Copy link
Contributor

This looks reasonable. Why is it tagged "[URGENT]"? Can you verify that the test failures are unrelated to this change?

@pandiaraj44 pandiaraj44 changed the title Android datepicker mode configurations added [URGENT] Android datepicker mode configurations added Nov 14, 2016
@pandiaraj44
Copy link
Contributor Author

@ericvicenti removed the urgent tag from title. The build issues are related to Xcode8, I have changed only the DatePickerDialogModule for android.

@ericvicenti
Copy link
Contributor

Ok, looks great!

@facebook-github-bot shipit

@facebook-github-bot facebook-github-bot added GH Review: accepted Import Started This pull request has been imported. This does not imply the PR has been approved. and removed GH Review: review-needed labels Nov 14, 2016
@facebook-github-bot
Copy link
Contributor

@ericvicenti has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@ericvicenti
Copy link
Contributor

We had some test failures internally. Do you know why this would happen?

/data/react-native-github/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java:28: error: cannot find symbol
import com.facebook.react.R;
                         ^
/data/react-native-github/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java:63: error: package R does not exist
        dialog = new DismissableDatePickerDialog(activityContext, R.style.CalendarDatePickerDialog, onDateSetListener, year, month, day);
                                                                   ^
/data/react-native-github/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java:65: error: package R does not exist
        dialog = new DismissableDatePickerDialog(activityContext, R.style.SpinnerDatePickerDialog, onDateSetListener, year, month, day);
stderr: /data/react-native-github/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java:28: error: cannot find symbol

@pandiaraj44
Copy link
Contributor Author

pandiaraj44 commented Nov 15, 2016

@ericvicenti I have added custom styles in "react-native/ReactAndroid/src/main/res//shell/values/styles.xml". For reflecting those styles you have to run a clean build on android projects. You need to build the "ReactAndroid" android project.

@ericvicenti
Copy link
Contributor

Hmm. Maybe @mkonicek can help land this, because I have no idea what I'm doing when it comes to best practices around these things.

@facebook-github-bot facebook-github-bot added Import Failed and removed Import Started This pull request has been imported. This does not imply the PR has been approved. labels Nov 15, 2016
@facebook-github-bot
Copy link
Contributor

I tried to merge this pull request into the Facebook internal repo but some checks failed. To unblock yourself please check the following: Does this pull request pass all open source tests on GitHub? If not please fix those. Does the code still apply cleanly on top of GitHub master? If not can please rebase. In all other cases this means some internal test failed, for example a part of a fb app won't work with this pull request. I've added the Import Failed label to this pull request so it is easy for someone at fb to find the pull request and check what failed. If you don't see anyone comment in a few days feel free to comment mentioning one of the core contributors to the project so they get a notification.

@pandiaraj44
Copy link
Contributor Author

@ericvicenti , @mkonicek I have run the "npm test" command inside react-native folder. The test cases are executed successfully.
FYI...
screenshot from 2016-11-15 14 38 20

Can someone from android core team have a look at on this.

@leeight
Copy link
Contributor

leeight commented Nov 16, 2016

Try to run scripts/run-android-local-unit-tests.sh

@pandiaraj44 pandiaraj44 force-pushed the master branch 2 times, most recently from a3cc751 to 7bcf865 Compare November 16, 2016 06:57
@pandiaraj44
Copy link
Contributor Author

pandiaraj44 commented Nov 16, 2016

Hi @ericvicenti , @mkonicek , @facebook-github-bot , @leeight Finally, I have found the root cause of the issue("error: cannot find symbol import com.facebook.react.R;"). I have missed the resource dependency in date picker buck file. Now I have added the dependencies to "ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK" file. I run the android unit test cases and it was passed and In an android integration test, date picker modal test cases were passed.

FYI..
sh scripts/run-android-local-unit-tests.sh- Result
screenshot from 2016-11-16 12 12 40

sh scripts/run-android-local-integration-tests.sh - Result
screenshot from 2016-11-16 12 12 53

I have re-base the code from master and updated the pull request.

@sophiebits
Copy link
Contributor

@pandiaraj44 Please stop tagging everyone. It sounds like @mkonicek will look into why the import failed and tell you if anything needs to be changed.

@ericvicenti
Copy link
Contributor

I am re-running internal tests and will land this afternoon if everything passes.

* * `date` (`Date` object or timestamp in milliseconds) - date to show by default
* * `minDate` (`Date` or timestamp in milliseconds) - minimum date that can be selected
* * `maxDate` (`Date` object or timestamp in milliseconds) - minimum date that can be selected
* * `calendarMode` (`Boolean` true or false) - To set the date-picker mode to spinner/calendar.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use enum type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per the android API documentation, Android date-picker supports only two modes. https://developer.android.com/reference/android/R.styleable.html#DatePicker_datePickerMode

react_native_target('java/com/facebook/react/bridge:bridge'),
react_native_target('java/com/facebook/react/common:common'),
react_native_target('java/com/facebook/react/module/annotations:annotations'),
react_native_target('res:shell'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually i'm not sure it's right or not add res:shell dependency here, but i guess it's a bad smell...

Copy link
Contributor Author

@pandiaraj44 pandiaraj44 Nov 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside ReactAndroid project, The shell resource visibility is in PUBLIC mode. So I have reused that one and added some list of styles to shell resource folder.

I don't think it is necessary to create a resource folder for each of the package in ReactAndroid project.

Maybe if the visibility of the shell is in private mode then I would create separate resource folder.

Ref: https://developer.android.com/guide/topics/ui/themes.html

Copy link
Contributor

@leeight leeight Nov 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about remove react_native_target('res:shell'), dependency and use context.getResources().getIdentifier instead of R...., for example:

cc @satya164

ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/I18nManagerModule.java
44:    final Locale locale = context.getResources().getConfiguration().locale;

ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java
58:    final int heightResId = context.getResources()
61:      PixelUtil.toDIPFromPixel(context.getResources().getDimensionPixelSize(heightResId)) :

ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java
55:    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();

ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java
601:    Resources resources = v.getContext().getResources();

ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ResourceDrawableIdHelper.java
54:    int id = context.getResources().getIdentifier(
64:    return resId > 0 ? context.getResources().getDrawable(resId) : null;

ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java
167:    return new GenericDraweeHierarchyBuilder(context.getResources())

ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/FrescoBasedReactTextInlineImageShadowNode.java
80:    int resId = context.getResources().getIdentifier(
97:    Resources resources = getThemedContext().getResources();

ReactAndroid/src/main/java/com/facebook/react/views/toolbar/ReactToolbar.java
301:    return new GenericDraweeHierarchyBuilder(getResources())
308:    return getResources().getIdentifier(
317:      return getResources().getDrawable(getDrawableResourceByName(name));

ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.java
41:      int attrID = context.getResources().getIdentifier(attr, "attr", "android");
49:          return context.getResources()
52:          return context.getResources().getDrawable(sResolveOutValue.resourceId);
72:          color = context.getResources().getColor(sResolveOutValue.resourceId);

@pandiaraj44
Copy link
Contributor Author

Hi @ericvicenti , FYI... All git hub checks have passed.

@pandiaraj44 pandiaraj44 force-pushed the master branch 2 times, most recently from c3e250d to aa514dc Compare November 18, 2016 08:53
@pandiaraj44
Copy link
Contributor Author

Hi @ericvicenti , Again I have re-base my code from upstream and tests have passed.

@pandiaraj44
Copy link
Contributor Author

cc @leeight

@pandiaraj44
Copy link
Contributor Author

@satya164
Copy link
Contributor

@pandiaraj44 Can you address @leeight 's nits regarding whitespace please?

@pandiaraj44
Copy link
Contributor Author

@satya164 Updated the pull request.
Can you please let me know who is the potential reviewer for this pull request and when they will accept/reject this pull request?

cc @leeight

@@ -0,0 +1 @@
5  4f:}&� dl�8mH No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this file used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@satya164 While running test cases that file get created. I removed that file and updated the pull request.

@satya164
Copy link
Contributor

Can you please let me know who is the potential reviewer

Me, @leeight and @mkonicek are reviewing your PR, so I guess we're the reviewers

when they will accept/reject this pull request?

We'll merge when all review comments have been addressed

@pandiaraj44
Copy link
Contributor Author

@satya164 Thank you very much for your information.


final DatePickerDialog dialog =
new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day);
DatePickerMode mode = DatePickerMode.DEFAULT; //To set mode to default
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Please remove comment that repeats what the code does without adding information.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment has been removed.

onDateSetListener, year, month, day);
break;
case DEFAULT:
//To Show a default native date picker
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove redundant comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment has been removed.

break;
case SPINNER:
dialog.getDatePicker().setCalendarViewShown(false);
break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code in this switch statement should be moved up to the branches where the dialogs are created.

break;
}
} else {
dialog = new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible to write the code above without repeating this line twice:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  if (mode ==  DatePickerMode.CALENDAR) {
    // Create picker with calendar
  } else (if mode == DatePickerMode.SPINNER) {
    // Create picker with spinner
  }
}
// Default case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setCalendarViewShown has been deprecated in latest android API version. So build version "if condition" is mandatory.

We can remove the dialog creation line but it requires extra two if condition

    DatePickerDialog dialog = null;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      switch (mode) {
        case CALENDAR:
          dialog = new DismissableDatePickerDialog(activityContext,
            activityContext.getResources().getIdentifier("CalendarDatePickerDialog", "style", activityContext.getPackageName()),
            onDateSetListener, year, month, day);
          break;
        case SPINNER:
          dialog = new DismissableDatePickerDialog(activityContext,
            activityContext.getResources().getIdentifier("SpinnerDatePickerDialog", "style", activityContext.getPackageName()),
            onDateSetListener, year, month, day);
          break;
      }
    }

    if (dialog == null) {
      dialog = new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day);
    }

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
      switch (mode) {
        case CALENDAR:
          dialog.getDatePicker().setCalendarViewShown(true);
          dialog.getDatePicker().setSpinnersShown(false);
          break;
        case SPINNER:
          dialog.getDatePicker().setCalendarViewShown(false);
          break;
      }
    }


For supporting future cases, I have used a switch statement.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thanks!

mValue = value;
}

public static DatePickerMode fromString(String value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ValueOf has been implemented. For that, we need to match the user values with enum constants.


<style name="CalendarDatePickerStyle" parent="android:Widget.Material.Light.DatePicker" tools:targetApi="lollipop">
<item name="android:datePickerMode">calendar</item>
</style>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it needed for these styles to be defined in resources? Is it possible to set the android:datePickerMode programmatically instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkonicek
Copy link
Contributor

Thanks!

@facebook-github-bot shipit

break;
}
} else {
dialog = new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thanks!

@facebook-github-bot facebook-github-bot added GH Review: accepted Import Started This pull request has been imported. This does not imply the PR has been approved. and removed GH Review: review-needed labels Nov 23, 2016
rozele pushed a commit to microsoft/react-native-windows that referenced this pull request Nov 23, 2016
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 facebook/react-native#10932

Differential Revision: D4176089

Pulled By: ericvicenti

fbshipit-source-id: 7dfa9101214501ac2124bda7ee273a538f04e7cf
DanielMSchmidt pushed a commit to DanielMSchmidt/react-native that referenced this pull request Jan 4, 2017
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 facebook#10932

Differential Revision: D4176089

Pulled By: ericvicenti

fbshipit-source-id: 7dfa9101214501ac2124bda7ee273a538f04e7cf
facebook-github-bot pushed a commit that referenced this pull request Oct 8, 2017
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 #12384

Differential Revision: D6006689

Pulled By: hramos

fbshipit-source-id: fcd37c867c4061b9982b1687f2c10211e54df7cf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Import Started This pull request has been imported. This does not imply the PR has been approved.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants