Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TimePicker display="spinner" no longer working in RN 64 (Android) #411

Closed
klandell opened this issue Mar 16, 2021 · 15 comments · Fixed by #418 or #424
Closed

TimePicker display="spinner" no longer working in RN 64 (Android) #411

klandell opened this issue Mar 16, 2021 · 15 comments · Fixed by #418 or #424
Labels
help wanted Extra attention is needed released

Comments

@klandell
Copy link
Contributor

Bug report

Hello!

Summary

Setting display to spinner on the time picker in Android renders a clock in React Native 64. It works as expected in React Native 63. I have only tested on Android.

Reproducible sample code

See this repo for a sample. Branch main uses RN 63 and works as expected. Branch rn-64 is exactly the same code, simply upgraded by running npx react-native upgrade

https://github.com/klandell/time-spinner-bug

Steps to reproduce

Open the app on an Android device. Click show time spinner. On react native 63, it shows as a spinner. On react native 64 it shows as a clock.

Environment info

Vanilla react native app, not Expo.

System:
    OS: macOS 11.1
    CPU: (8) x64 Intel(R) Core(TM) i5-8257U CPU @ 1.40GHz
    Memory: 564.87 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 15.0.1 - /var/folders/bq/rv3dbnrd4gnfymg9n66rgdc80000gn/T/yarn--1615903404422-0.9955909284122346/node
    Yarn: 1.22.10 - /var/folders/bq/rv3dbnrd4gnfymg9n66rgdc80000gn/T/yarn--1615903404422-0.9955909284122346/yarn
    npm: 7.0.3 - /usr/local/bin/npm
    Watchman: Not Found
  Managers:
    CocoaPods: 1.10.1 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 14.4, DriverKit 20.2, macOS 11.1, tvOS 14.3, watchOS 7.2
    Android SDK:
      Android NDK: 21.0.6113669
  IDEs:
    Android Studio: 4.1 AI-201.8743.12.41.6953283
    Xcode: 12.4/12D4e - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.9 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 17.0.1 => 17.0.1 
    react-native: 0.64.0 => 0.64.0 
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

datetimepicker version: 3.2
iOS / Android version: Samsung Galaxy S20e, Android 10.

@vonovak vonovak added the help wanted Extra attention is needed label Mar 16, 2021
@billnbell
Copy link
Collaborator

yeah this is happening in react native 64 only on Android

@billnbell
Copy link
Collaborator

I am getting SpinnerTimePickerDialog in static TimePickerDialog getDialog()... and display = SPINNER.
image

@billnbell
Copy link
Collaborator

If I change:

  private void fixSpinner(Context context, int hourOfDay, int minute, boolean is24HourView, RNTimePickerDisplay display) {
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N && display == RNTimePickerDisplay.SPINNER) {

to

  private void fixSpinner(Context context, int hourOfDay, int minute, boolean is24HourView, RNTimePickerDisplay display) {
    if (display == RNTimePickerDisplay.SPINNER) {

It works.

@billnbell
Copy link
Collaborator

My recommendation is to do:

  private void fixSpinner(Context context, int hourOfDay, int minute, boolean is24HourView, RNTimePickerDisplay display) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && display == RNTimePickerDisplay.SPINNER) {

I'll set up a PR

@vonovak
Copy link
Member

vonovak commented Mar 22, 2021

🎉 This issue has been resolved in version 3.4.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@vonovak
Copy link
Member

vonovak commented Mar 22, 2021

@klandell please let us know if the issue is resolved in latest release and please test it on different android versions (not just the appearance but the actual function), thank you!

@klandell
Copy link
Contributor Author

@vonovak @billnbell Thank you both for looking into this. I updated to the latest package in the rn-64 branch of the demo repo above to 3.4.1. Unfortunately, the app is now crashing with the following exception:

--------- beginning of crash
03-23 09:13:21.320 19282 19282 E AndroidRuntime: FATAL EXCEPTION: main
03-23 09:13:21.320 19282 19282 E AndroidRuntime: Process: com.awesomeproject, PID: 19282
03-23 09:13:21.320 19282 19282 E AndroidRuntime: java.lang.RuntimeException: java.lang.NoSuchFieldException: TimePicker
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at com.reactcommunity.rndatetimepicker.RNDismissableTimePickerDialog.fixSpinner(RNDismissableTimePickerDialog.java:104)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at com.reactcommunity.rndatetimepicker.RNDismissableTimePickerDialog.<init>(RNDismissableTimePickerDialog.java:63)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at com.reactcommunity.rndatetimepicker.RNTimePickerDialogFragment.getDialog(RNTimePickerDialogFragment.java:83)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at com.reactcommunity.rndatetimepicker.RNTimePickerDialogFragment.createDialog(RNTimePickerDialogFragment.java:112)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at com.reactcommunity.rndatetimepicker.RNTimePickerDialogFragment.onCreateDialog(RNTimePickerDialogFragment.java:41)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at androidx.fragment.app.DialogFragment.onGetLayoutInflater(DialogFragment.java:380)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at androidx.fragment.app.Fragment.performGetLayoutInflater(Fragment.java:1412)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:881)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at android.os.Handler.handleCallback(Handler.java:883)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at android.os.Handler.dispatchMessage(Handler.java:100)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at android.os.Looper.loop(Looper.java:237)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at android.app.ActivityThread.main(ActivityThread.java:8167)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
03-23 09:13:21.320 19282 19282 E AndroidRuntime: Caused by: java.lang.NoSuchFieldException: TimePicker
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at java.lang.Class.getField(Class.java:1604)
03-23 09:13:21.320 19282 19282 E AndroidRuntime:        at com.reactcommunity.rndatetimepicker.RNDismissableTimePickerDialog.fixSpinner(RNDismissableTimePickerDialog.java:77)

@vonovak
Copy link
Member

vonovak commented Mar 23, 2021

Hmm, sorry about that. If you or someone else could look into this, that would be great, my time is limited now. In the mean time, im going to revert the fix because it was probably better before. Thanks.

@klandell
Copy link
Contributor Author

Thanks. I'll try to take a look at this next week as my time is limited right now as well. Unless someone else gets to it first!

@klandell
Copy link
Contributor Author

klandell commented Mar 24, 2021

I was able to do a little bit of digging into this. From what I can tell so far the issue seems to be stemming from this code

activityContext.getResources().getIdentifier(
        resourceName,
        "style",
        activityContext.getPackageName()
),

in the getDialog method of RNTimePickerDialogFragment which creates the RNDismissableTimePickerDialog.

This value is passed as the theme variable to the RNDismissableTimePickerDialog constructor here:

  public RNDismissableTimePickerDialog(
    Context context,
    int theme,
    @Nullable TimePickerDialog.OnTimeSetListener callback,
    int hourOfDay,
    int minute,
    int minuteInterval,
    boolean is24HourView,
    RNTimePickerDisplay display
  ) {
    super(context, theme, callback, hourOfDay, minute, minuteInterval, is24HourView, display);
    fixSpinner(context, hourOfDay, minute, is24HourView, display);
  }

In React native 63, int theme = 2131558599 during debugging. In React Native 64 int theme = 0.

I'm not sure of the reason yet.

@klandell
Copy link
Contributor Author

klandell commented Mar 24, 2021

I just inspected the react-native-0.63.4.aar file packaged with react native.

In react-native-0.63.4.aar -> res -> values -> values.xml I see the following.

<style name="SpinnerTimePickerDialog" parent="Theme.AppCompat.Light.Dialog" ns1:targetApi="lollipop">
  <item name="android:timePickerStyle">@style/SpinnerTimePickerStyle</item>
</style>
<style name="SpinnerTimePickerStyle" parent="android:Widget.Material.Light.TimePicker" ns1:targetApi="lollipop">
  <item name="android:timePickerMode">spinner</item>
</style>

These values do not exist in react-native-0.64.0.aar -> res -> values -> values.xml

This is the commit that removed the styles this library relied on:
facebook/react-native@c8fed9e

@klandell
Copy link
Contributor Author

Simply adding

<style name="SpinnerTimePickerDialog" parent="Theme.AppCompat.Light.Dialog">
    <item name="android:timePickerStyle">@style/SpinnerTimePickerStyle</item>
</style>
<style name="SpinnerTimePickerStyle" parent="android:Widget.Material.Light.TimePicker">
    <item name="android:timePickerMode">spinner</item>
</style>

to my styles.xml file fixed the issue.

Is there a recommended way of integrating this change into the this library? I removed ns1:targetApi="lollipop" from my styles.xml file because the parser was complaining about it. I assume that field is needed in the library though?

If someone with more familiarity with Android could weigh in it would be hugely helpful.

@vonovak
Copy link
Member

vonovak commented Mar 24, 2021

ah, so it's this: #258 becoming a real issue 6 months later 😆

Nice, thanks a lot for the investigation!

I removed ns1:targetApi="lollipop" from my styles.xml file because the parser was complaining about it

I'm assuming we should keep it. There probably is a commit in RN's history that explains what those things do and why they are there.

So if you add those things to the styles.xml file in this package that should probably fix it. The file does not exists but I'm guessing that android studio will have a way to create it or you can do it manually. Unfortunately, I'm not an android guru either but I think this should work.

Thanks again! 👍

@billnbell
Copy link
Collaborator

@vonovak
Copy link
Member

vonovak commented Mar 25, 2021

🎉 This issue has been resolved in version 3.4.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed released
Projects
None yet
3 participants