18
18
19
19
import com .google .android .material .R ;
20
20
21
-
22
21
import android .app .Dialog ;
23
22
import android .content .Context ;
23
+ import android .content .DialogInterface ;
24
+ import android .content .DialogInterface .OnCancelListener ;
25
+ import android .content .DialogInterface .OnDismissListener ;
24
26
import android .content .res .ColorStateList ;
25
27
import android .os .Bundle ;
26
28
import androidx .fragment .app .DialogFragment ;
40
42
import com .google .android .material .shape .MaterialShapeDrawable ;
41
43
import java .lang .annotation .Retention ;
42
44
import java .lang .annotation .RetentionPolicy ;
45
+ import java .util .LinkedHashSet ;
46
+ import java .util .Set ;
43
47
44
48
/** A {@link Dialog} with a clock display and a clock face to choose the time. */
45
49
public final class MaterialTimePicker extends DialogFragment {
46
50
47
51
private static final int CLOCK_ICON = R .drawable .ic_clock_black_24dp ;
48
52
private static final int KEYBOARD_ICON = R .drawable .ic_keyboard_black_24dp ;
49
53
54
+ private final Set <OnPositiveButtonClickListener > positiveButtonListeners = new LinkedHashSet <>();
55
+ private final Set <OnClickListener > negativeButtonListeners = new LinkedHashSet <>();
56
+ private final Set <OnCancelListener > cancelListeners = new LinkedHashSet <>();
57
+ private final Set <OnDismissListener > dismissListeners = new LinkedHashSet <>();
58
+
50
59
private TimePickerView timePickerView ;
51
60
private LinearLayout textInputView ;
52
61
@@ -70,26 +79,23 @@ public final class MaterialTimePicker extends DialogFragment {
70
79
@ InputMode private int inputMode = INPUT_MODE_CLOCK ;
71
80
72
81
/**
73
- * The callback interface used to indicate the user is done filling in
74
- * the time (e.g. they clicked on the 'OK' button).
82
+ * The callback interface used to indicate the user is done filling in the time (e.g. they clicked
83
+ * on the 'OK' button).
75
84
*/
76
- public interface OnTimeSetListener {
85
+ public interface OnPositiveButtonClickListener {
77
86
78
- /** **
79
- * Called when the user is done setting a new time and the dialog has
80
- * closed.
87
+ /**
88
+ * Called when the user is done setting a new time and the dialog has closed.
81
89
*
82
- * <p> use {@link #getHour()}, {@link #getMinute()} to get the selection.
90
+ * <p>use {@link #getHour()}, {@link #getMinute()} to get the selection.
83
91
*
84
92
* @param dialog the dialog associated with this listener
85
93
*/
86
- void onTimeSet (MaterialTimePicker dialog );
94
+ void onClick (MaterialTimePicker dialog );
87
95
}
88
96
89
97
private TimeModel time = new TimeModel ();
90
98
91
- private OnTimeSetListener listener ;
92
-
93
99
@ NonNull
94
100
public static MaterialTimePicker newInstance () {
95
101
return new MaterialTimePicker ();
@@ -135,21 +141,15 @@ public final Dialog onCreateDialog(@Nullable Bundle bundle) {
135
141
context , R .attr .colorSurface , MaterialTimePicker .class .getCanonicalName ());
136
142
137
143
MaterialShapeDrawable background =
138
- new MaterialShapeDrawable (
139
- context ,
140
- null ,
141
- 0 ,
142
- R .style .Widget_MaterialComponents_TimePicker );
144
+ new MaterialShapeDrawable (context , null , 0 , R .style .Widget_MaterialComponents_TimePicker );
143
145
144
146
background .initializeElevationOverlay (context );
145
147
background .setFillColor (ColorStateList .valueOf (surfaceColor ));
146
148
Window window = dialog .getWindow ();
147
149
window .setBackgroundDrawable (background );
148
150
window .requestFeature (Window .FEATURE_NO_TITLE );
149
151
// On some Android APIs the dialog won't wrap content by default. Explicitly update here.
150
- window .setLayout (
151
- ViewGroup .LayoutParams .WRAP_CONTENT ,
152
- ViewGroup .LayoutParams .WRAP_CONTENT );
152
+ window .setLayout (ViewGroup .LayoutParams .WRAP_CONTENT , ViewGroup .LayoutParams .WRAP_CONTENT );
153
153
154
154
return dialog ;
155
155
}
@@ -192,23 +192,28 @@ public final View onCreateView(
192
192
modeButton = root .findViewById (R .id .material_timepicker_mode_button );
193
193
updateInputMode (modeButton );
194
194
MaterialButton okButton = root .findViewById (R .id .material_timepicker_ok_button );
195
- okButton .setOnClickListener (new OnClickListener () {
196
- @ Override
197
- public void onClick (View v ) {
198
- if (listener != null ) {
199
- listener .onTimeSet (MaterialTimePicker .this );
200
- }
201
- dismiss ();
202
- }
203
- });
195
+ okButton .setOnClickListener (
196
+ new OnClickListener () {
197
+ @ Override
198
+ public void onClick (View v ) {
199
+ for (OnPositiveButtonClickListener listener : positiveButtonListeners ) {
200
+ listener .onClick (MaterialTimePicker .this );
201
+ }
202
+ dismiss ();
203
+ }
204
+ });
204
205
205
206
MaterialButton cancelButton = root .findViewById (R .id .material_timepicker_cancel_button );
206
- cancelButton .setOnClickListener (new OnClickListener () {
207
- @ Override
208
- public void onClick (View v ) {
209
- dismiss ();
210
- }
211
- });
207
+ cancelButton .setOnClickListener (
208
+ new OnClickListener () {
209
+ @ Override
210
+ public void onClick (View v ) {
211
+ for (OnClickListener listener : negativeButtonListeners ) {
212
+ listener .onClick (v );
213
+ }
214
+ dismiss ();
215
+ }
216
+ });
212
217
213
218
modeButton .setOnClickListener (
214
219
new OnClickListener () {
@@ -222,6 +227,26 @@ public void onClick(View v) {
222
227
return root ;
223
228
}
224
229
230
+ @ Override
231
+ public final void onCancel (@ NonNull DialogInterface dialogInterface ) {
232
+ for (OnCancelListener listener : cancelListeners ) {
233
+ listener .onCancel (dialogInterface );
234
+ }
235
+ super .onCancel (dialogInterface );
236
+ }
237
+
238
+ @ Override
239
+ public final void onDismiss (@ NonNull DialogInterface dialogInterface ) {
240
+ for (OnDismissListener listener : dismissListeners ) {
241
+ listener .onDismiss (dialogInterface );
242
+ }
243
+ ViewGroup viewGroup = ((ViewGroup ) getView ());
244
+ if (viewGroup != null ) {
245
+ viewGroup .removeAllViews ();
246
+ }
247
+ super .onDismiss (dialogInterface );
248
+ }
249
+
225
250
private void updateInputMode (MaterialButton modeButton ) {
226
251
if (activePresenter != null ) {
227
252
activePresenter .hide ();
@@ -262,12 +287,104 @@ private static int iconForMode(@InputMode int mode) {
262
287
}
263
288
}
264
289
265
- public void setListener (@ Nullable OnTimeSetListener listener ) {
266
- this .listener = listener ;
267
- }
268
-
269
290
@ Nullable
270
291
TimePickerClockPresenter getTimePickerClockPresenter () {
271
292
return timePickerClockPresenter ;
272
293
}
294
+
295
+ /** The supplied listener is called when the user confirms a valid selection. */
296
+ public boolean addOnPositiveButtonClickListener (
297
+ OnPositiveButtonClickListener onPositiveButtonClickListener ) {
298
+ return positiveButtonListeners .add (onPositiveButtonClickListener );
299
+ }
300
+
301
+ /**
302
+ * Removes a listener previously added via {@link
303
+ * MaterialTimePicker#addOnPositiveButtonClickListener(OnPositiveButtonClickListener)}.
304
+ */
305
+ public boolean removeOnPositiveButtonClickListener (
306
+ @ NonNull OnPositiveButtonClickListener listener ) {
307
+ return positiveButtonListeners .remove (listener );
308
+ }
309
+
310
+ /**
311
+ * Removes all listeners added via {@link
312
+ * MaterialTimePicker#addOnPositiveButtonClickListener(OnPositiveButtonClickListener)}.
313
+ */
314
+ public void clearOnPositiveButtonClickListeners () {
315
+ positiveButtonListeners .clear ();
316
+ }
317
+
318
+ /** The supplied listener is called when the user clicks the cancel button. */
319
+ public boolean addOnNegativeButtonClickListener (@ NonNull OnClickListener listener ) {
320
+ return negativeButtonListeners .add (listener );
321
+ }
322
+
323
+ /**
324
+ * Removes a listener previously added via {@link
325
+ * MaterialTimePicker#addOnNegativeButtonClickListener(OnClickListener)}.
326
+ */
327
+ public boolean removeOnNegativeButtonClickListener (@ NonNull OnClickListener listener ) {
328
+ return negativeButtonListeners .remove (listener );
329
+ }
330
+
331
+ /**
332
+ * Removes all listeners added via {@link
333
+ * MaterialTimePicker#addOnNegativeButtonClickListener(OnClickListener)}.
334
+ */
335
+ public void clearOnNegativeButtonClickListeners () {
336
+ negativeButtonListeners .clear ();
337
+ }
338
+
339
+ /**
340
+ * The supplied listener is called when the user cancels the picker via back button or a touch
341
+ * outside the view.
342
+ *
343
+ * <p>It is not called when the user clicks the cancel button. To add a listener for use when the
344
+ * user clicks the cancel button, use {@link
345
+ * MaterialTimePicker#addOnNegativeButtonClickListener(OnClickListener)}.
346
+ */
347
+ public boolean addOnCancelListener (@ NonNull OnCancelListener listener ) {
348
+ return cancelListeners .add (listener );
349
+ }
350
+
351
+ /**
352
+ * Removes a listener previously added via {@link
353
+ * MaterialTimePicker#addOnCancelListener(OnCancelListener)}.
354
+ */
355
+ public boolean removeOnCancelListener (@ NonNull OnCancelListener listener ) {
356
+ return cancelListeners .remove (listener );
357
+ }
358
+
359
+ /**
360
+ * Removes all listeners added via {@link
361
+ * MaterialTimePicker#addOnCancelListener(OnCancelListener)}.
362
+ */
363
+ public void clearOnCancelListeners () {
364
+ cancelListeners .clear ();
365
+ }
366
+
367
+ /**
368
+ * The supplied listener is called whenever the DialogFragment is dismissed, no matter how it is
369
+ * dismissed.
370
+ */
371
+ public boolean addOnDismissListener (@ NonNull OnDismissListener listener ) {
372
+ return dismissListeners .add (listener );
373
+ }
374
+
375
+ /**
376
+ * Removes a listener previously added via {@link
377
+ * MaterialTimePicker#addOnDismissListener(OnDismissListener)}.
378
+ */
379
+ public boolean removeOnDismissListener (@ NonNull OnDismissListener listener ) {
380
+ return dismissListeners .remove (listener );
381
+ }
382
+
383
+ /**
384
+ * Removes all listeners added via {@link
385
+ * MaterialTimePicker#addOnDismissListener(OnDismissListener)}.
386
+ */
387
+ public void clearOnDismissListeners () {
388
+ dismissListeners .clear ();
389
+ }
273
390
}
0 commit comments