7
7
8
8
package com .facebook .react .modules .datepicker ;
9
9
10
- import android .app .DatePickerDialog ;
11
- import javax .annotation .Nullable ;
12
-
13
10
import android .app .DatePickerDialog ;
14
11
import android .content .Context ;
15
12
import android .os .Build ;
13
+ import android .content .res .TypedArray ;
14
+ import android .util .AttributeSet ;
15
+ import android .widget .DatePicker ;
16
+
17
+ import javax .annotation .Nullable ;
18
+ import java .lang .reflect .Field ;
19
+ import java .lang .reflect .Method ;
16
20
17
21
/**
18
22
* <p>
@@ -33,6 +37,7 @@ public DismissableDatePickerDialog(
33
37
int monthOfYear ,
34
38
int dayOfMonth ) {
35
39
super (context , callback , year , monthOfYear , dayOfMonth );
40
+ fixSpinner (context , year , monthOfYear , dayOfMonth );
36
41
}
37
42
38
43
public DismissableDatePickerDialog (
@@ -43,6 +48,7 @@ public DismissableDatePickerDialog(
43
48
int monthOfYear ,
44
49
int dayOfMonth ) {
45
50
super (context , theme , callback , year , monthOfYear , dayOfMonth );
51
+ fixSpinner (context , year , monthOfYear , dayOfMonth );
46
52
}
47
53
48
54
@ Override
@@ -53,4 +59,65 @@ protected void onStop() {
53
59
super .onStop ();
54
60
}
55
61
}
62
+
63
+ private void fixSpinner (Context context , int year , int month , int dayOfMonth ) {
64
+ if (Build .VERSION .SDK_INT == Build .VERSION_CODES .N ) {
65
+ try {
66
+ // Get the theme's android:datePickerMode
67
+ final int MODE_SPINNER = 2 ;
68
+ Class <?> styleableClass = Class .forName ("com.android.internal.R$styleable" );
69
+ Field datePickerStyleableField = styleableClass .getField ("DatePicker" );
70
+ int [] datePickerStyleable = (int []) datePickerStyleableField .get (null );
71
+
72
+ final TypedArray a = context .obtainStyledAttributes (null , datePickerStyleable , android .R .attr .datePickerStyle , 0 );
73
+ Field datePickerModeStyleableField = styleableClass .getField ("DatePicker_datePickerMode" );
74
+ int datePickerModeStyleable = datePickerModeStyleableField .getInt (null );
75
+ final int mode = a .getInt (datePickerModeStyleable , MODE_SPINNER );
76
+ a .recycle ();
77
+
78
+ if (mode == MODE_SPINNER ) {
79
+ DatePicker datePicker = (DatePicker ) findField (DatePickerDialog .class , DatePicker .class , "mDatePicker" ).get (this );
80
+ Class <?> delegateClass = Class .forName ("android.widget.DatePickerSpinnerDelegate" );
81
+ Field delegateField = findField (DatePicker .class , delegateClass , "mDelegate" );
82
+ Object delegate = delegateField .get (datePicker );
83
+ Class <?> spinnerDelegateClass ;
84
+ spinnerDelegateClass = Class .forName ("android.widget.DatePickerSpinnerDelegate" );
85
+
86
+ // In 7.0 Nougat for some reason the datePickerMode is ignored and the delegate is DatePickerClockDelegate
87
+ if (delegate .getClass () != spinnerDelegateClass ) {
88
+ delegateField .set (datePicker , null ); // throw out the DatePickerClockDelegate!
89
+ datePicker .removeAllViews (); // remove the DatePickerClockDelegate views
90
+ Method createSpinnerUIDelegate = DatePicker .class .getDeclaredMethod ("createSpinnerUIDelegate" , Context .class , AttributeSet .class , int .class , int .class );
91
+ createSpinnerUIDelegate .setAccessible (true );
92
+
93
+ // Instantiate a DatePickerSpinnerDelegate throughout createSpinnerUIDelegate method
94
+ delegate = createSpinnerUIDelegate .invoke (datePicker , context , null , android .R .attr .datePickerStyle , 0 );
95
+ delegateField .set (datePicker , delegate ); // set the DatePicker.mDelegate to the spinner delegate
96
+ datePicker .setCalendarViewShown (false );
97
+ // Initialize the date for the DatePicker delegate again
98
+ datePicker .init (year , month , dayOfMonth , this );
99
+ }
100
+ }
101
+ } catch (Exception e ) {
102
+ throw new RuntimeException (e );
103
+ }
104
+ }
105
+ }
106
+
107
+ private static Field findField (Class objectClass , Class fieldClass , String expectedName ) {
108
+ try {
109
+ Field field = objectClass .getDeclaredField (expectedName );
110
+ field .setAccessible (true );
111
+ return field ;
112
+ } catch (NoSuchFieldException e ) {
113
+ } // ignore
114
+ // search for it if it wasn't found under the expected ivar name
115
+ for (Field searchField : objectClass .getDeclaredFields ()) {
116
+ if (searchField .getType () == fieldClass ) {
117
+ searchField .setAccessible (true );
118
+ return searchField ;
119
+ }
120
+ }
121
+ return null ;
122
+ }
56
123
}
0 commit comments