From 0329ba2fc400fe2f0bd76d4d8e8d8c6d234f7675 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Wed, 27 Jul 2016 23:52:48 -0500 Subject: [PATCH] Use framework date and time pickers on Android 6+ --- .../activities/DateAndTimePickerActivity.java | 56 ++++++++++----- .../tasks/activities/DatePickerActivity.java | 56 ++++++++++----- .../tasks/activities/TimePickerActivity.java | 58 ++++++++++----- .../tasks/dialogs/NativeDatePickerDialog.java | 68 ++++++++++++++++++ .../tasks/dialogs/NativeTimePickerDialog.java | 72 +++++++++++++++++++ .../BaseNativeDialogFragmentComponent.java | 6 ++ 6 files changed, 267 insertions(+), 49 deletions(-) create mode 100644 src/main/java/org/tasks/dialogs/NativeDatePickerDialog.java create mode 100644 src/main/java/org/tasks/dialogs/NativeTimePickerDialog.java diff --git a/src/main/java/org/tasks/activities/DateAndTimePickerActivity.java b/src/main/java/org/tasks/activities/DateAndTimePickerActivity.java index 9671d039e..5bcf60083 100644 --- a/src/main/java/org/tasks/activities/DateAndTimePickerActivity.java +++ b/src/main/java/org/tasks/activities/DateAndTimePickerActivity.java @@ -8,6 +8,7 @@ import android.os.Bundle; import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; import org.tasks.dialogs.MyDatePickerDialog; +import org.tasks.dialogs.NativeDatePickerDialog; import org.tasks.injection.ActivityComponent; import org.tasks.injection.InjectingAppCompatActivity; import org.tasks.themes.ThemeAccent; @@ -16,9 +17,11 @@ import org.tasks.time.DateTime; import javax.inject.Inject; +import static com.todoroo.andlib.utility.AndroidUtilities.atLeastMarshmallow; +import static org.tasks.dialogs.NativeDatePickerDialog.newNativeDatePickerDialog; import static org.tasks.time.DateTimeUtils.currentTimeMillis; -public class DateAndTimePickerActivity extends InjectingAppCompatActivity implements DatePickerDialog.OnDateSetListener, DialogInterface.OnCancelListener { +public class DateAndTimePickerActivity extends InjectingAppCompatActivity implements DatePickerDialog.OnDateSetListener, DialogInterface.OnCancelListener, NativeDatePickerDialog.NativeDatePickerDialogCallback { private static final String FRAG_TAG_DATE_PICKER = "frag_tag_date_picker"; @@ -45,16 +48,23 @@ public class DateAndTimePickerActivity extends InjectingAppCompatActivity implem } FragmentManager fragmentManager = getFragmentManager(); - MyDatePickerDialog datePickerDialog = (MyDatePickerDialog) fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER); - if (datePickerDialog == null) { - datePickerDialog = new MyDatePickerDialog(); - datePickerDialog.initialize(null, initial.getYear(), initial.getMonthOfYear() - 1, initial.getDayOfMonth()); - datePickerDialog.setThemeDark(themeBase.isDarkTheme(this)); - datePickerDialog.setAccentColor(themeAccent.getAccentColor()); - datePickerDialog.show(fragmentManager, FRAG_TAG_DATE_PICKER); + if (atLeastMarshmallow()) { + if (fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER) == null) { + newNativeDatePickerDialog(initial) + .show(fragmentManager, FRAG_TAG_DATE_PICKER); + } + } else { + MyDatePickerDialog datePickerDialog = (MyDatePickerDialog) fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER); + if (datePickerDialog == null) { + datePickerDialog = new MyDatePickerDialog(); + datePickerDialog.initialize(null, initial.getYear(), initial.getMonthOfYear() - 1, initial.getDayOfMonth()); + datePickerDialog.setThemeDark(themeBase.isDarkTheme(this)); + datePickerDialog.setAccentColor(themeAccent.getAccentColor()); + datePickerDialog.show(fragmentManager, FRAG_TAG_DATE_PICKER); + } + datePickerDialog.setOnCancelListener(this); + datePickerDialog.setOnDateSetListener(this); } - datePickerDialog.setOnCancelListener(this); - datePickerDialog.setOnDateSetListener(this); } @Override @@ -70,20 +80,34 @@ public class DateAndTimePickerActivity extends InjectingAppCompatActivity implem @Override public void onDateSet(DatePickerDialog datePickerDialog, int year, int month, int day) { + datePickerDialog.dismiss(); + dateSet(year, month, day); + } + + @Override + public void onCancel(DialogInterface dialog) { + finish(); + } + + @Override + public void cancel() { + finish(); + } + + @Override + public void onDateSet(int year, int month, int day) { + dateSet(year, month, day); + } + + private void dateSet(int year, int month, int day) { dateSelected = true; final long timestamp = new DateTime(year, month + 1, day) .withMillisOfDay(initial.getMillisOfDay()) .getMillis(); - datePickerDialog.dismiss(); startActivity(new Intent(this, TimePickerActivity.class) {{ addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); putExtra(TimePickerActivity.EXTRA_TIMESTAMP, timestamp); }}); finish(); } - - @Override - public void onCancel(DialogInterface dialog) { - finish(); - } } diff --git a/src/main/java/org/tasks/activities/DatePickerActivity.java b/src/main/java/org/tasks/activities/DatePickerActivity.java index 619295142..cd8733419 100644 --- a/src/main/java/org/tasks/activities/DatePickerActivity.java +++ b/src/main/java/org/tasks/activities/DatePickerActivity.java @@ -8,6 +8,7 @@ import android.os.Bundle; import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; import org.tasks.dialogs.MyDatePickerDialog; +import org.tasks.dialogs.NativeDatePickerDialog; import org.tasks.injection.ActivityComponent; import org.tasks.injection.InjectingAppCompatActivity; import org.tasks.themes.ThemeAccent; @@ -16,9 +17,11 @@ import org.tasks.time.DateTime; import javax.inject.Inject; +import static com.todoroo.andlib.utility.AndroidUtilities.atLeastMarshmallow; +import static org.tasks.dialogs.NativeDatePickerDialog.newNativeDatePickerDialog; import static org.tasks.time.DateTimeUtils.currentTimeMillis; -public class DatePickerActivity extends InjectingAppCompatActivity implements DatePickerDialog.OnDateSetListener { +public class DatePickerActivity extends InjectingAppCompatActivity implements DatePickerDialog.OnDateSetListener, NativeDatePickerDialog.NativeDatePickerDialogCallback { private static final String FRAG_TAG_DATE_PICKER = "frag_tag_date_picker"; @@ -35,21 +38,28 @@ public class DatePickerActivity extends InjectingAppCompatActivity implements Da DateTime initial = (timestamp > 0 ? new DateTime(timestamp) : new DateTime()).startOfDay(); FragmentManager fragmentManager = getFragmentManager(); - MyDatePickerDialog dialog = (MyDatePickerDialog) fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER); - if (dialog == null) { - dialog = new MyDatePickerDialog(); - dialog.initialize(null, initial.getYear(), initial.getMonthOfYear() - 1, initial.getDayOfMonth()); - dialog.setThemeDark(themeBase.isDarkTheme(this)); - dialog.setAccentColor(themeAccent.getAccentColor()); - dialog.show(fragmentManager, FRAG_TAG_DATE_PICKER); - } - dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialogInterface) { - finish(); + if (atLeastMarshmallow()) { + if (fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER) == null) { + newNativeDatePickerDialog(initial) + .show(fragmentManager, FRAG_TAG_DATE_PICKER); + } + } else { + MyDatePickerDialog dialog = (MyDatePickerDialog) fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER); + if (dialog == null) { + dialog = new MyDatePickerDialog(); + dialog.initialize(null, initial.getYear(), initial.getMonthOfYear() - 1, initial.getDayOfMonth()); + dialog.setThemeDark(themeBase.isDarkTheme(this)); + dialog.setAccentColor(themeAccent.getAccentColor()); + dialog.show(fragmentManager, FRAG_TAG_DATE_PICKER); } - }); - dialog.setOnDateSetListener(this); + dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialogInterface) { + finish(); + } + }); + dialog.setOnDateSetListener(this); + } } @Override @@ -59,8 +69,22 @@ public class DatePickerActivity extends InjectingAppCompatActivity implements Da @Override public void onDateSet(DatePickerDialog view, final int year, final int monthOfYear, final int dayOfMonth) { + dateSet(year, monthOfYear, dayOfMonth); + } + + @Override + public void cancel() { + finish(); + } + + @Override + public void onDateSet(final int year, final int month, final int day) { + dateSet(year, month, day); + } + + private void dateSet(final int year, final int month, final int day) { setResult(RESULT_OK, new Intent() {{ - putExtra(EXTRA_TIMESTAMP, new DateTime(year, monthOfYear + 1, dayOfMonth).getMillis()); + putExtra(EXTRA_TIMESTAMP, new DateTime(year, month + 1, day).getMillis()); }}); finish(); } diff --git a/src/main/java/org/tasks/activities/TimePickerActivity.java b/src/main/java/org/tasks/activities/TimePickerActivity.java index bc3499dd5..76dd28544 100644 --- a/src/main/java/org/tasks/activities/TimePickerActivity.java +++ b/src/main/java/org/tasks/activities/TimePickerActivity.java @@ -10,6 +10,7 @@ import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout; import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; import org.tasks.dialogs.MyTimePickerDialog; +import org.tasks.dialogs.NativeTimePickerDialog; import org.tasks.injection.ActivityComponent; import org.tasks.injection.InjectingAppCompatActivity; import org.tasks.themes.ThemeAccent; @@ -18,10 +19,12 @@ import org.tasks.time.DateTime; import javax.inject.Inject; +import static com.todoroo.andlib.utility.AndroidUtilities.atLeastMarshmallow; +import static org.tasks.dialogs.NativeTimePickerDialog.newNativeTimePickerDialog; import static org.tasks.time.DateTimeUtils.currentTimeMillis; -public class TimePickerActivity extends InjectingAppCompatActivity implements TimePickerDialog.OnTimeSetListener { +public class TimePickerActivity extends InjectingAppCompatActivity implements TimePickerDialog.OnTimeSetListener, NativeTimePickerDialog.NativeTimePickerDialogCallback { private static final String FRAG_TAG_TIME_PICKER = "frag_tag_time_picker"; @@ -39,21 +42,28 @@ public class TimePickerActivity extends InjectingAppCompatActivity implements Ti initial = new DateTime(getIntent().getLongExtra(EXTRA_TIMESTAMP, currentTimeMillis())); FragmentManager fragmentManager = getFragmentManager(); - MyTimePickerDialog dialog = (MyTimePickerDialog) fragmentManager.findFragmentByTag(FRAG_TAG_TIME_PICKER); - if (dialog == null) { - dialog = new MyTimePickerDialog(); - dialog.initialize(null, initial.getHourOfDay(), initial.getMinuteOfHour(), 0, DateFormat.is24HourFormat(this)); - dialog.setThemeDark(themeBase.isDarkTheme(this)); - dialog.setAccentColor(themeAccent.getAccentColor()); - dialog.show(fragmentManager, FRAG_TAG_TIME_PICKER); - } - dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialogInterface) { - finish(); + if (atLeastMarshmallow()) { + if (fragmentManager.findFragmentByTag(FRAG_TAG_TIME_PICKER) == null) { + newNativeTimePickerDialog(initial) + .show(fragmentManager, FRAG_TAG_TIME_PICKER); + } + } else { + MyTimePickerDialog dialog = (MyTimePickerDialog) fragmentManager.findFragmentByTag(FRAG_TAG_TIME_PICKER); + if (dialog == null) { + dialog = new MyTimePickerDialog(); + dialog.initialize(null, initial.getHourOfDay(), initial.getMinuteOfHour(), 0, DateFormat.is24HourFormat(this)); + dialog.setThemeDark(themeBase.isDarkTheme(this)); + dialog.setAccentColor(themeAccent.getAccentColor()); + dialog.show(fragmentManager, FRAG_TAG_TIME_PICKER); } - }); - dialog.setOnTimeSetListener(this); + dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialogInterface) { + finish(); + } + }); + dialog.setOnTimeSetListener(this); + } } @Override @@ -63,11 +73,25 @@ public class TimePickerActivity extends InjectingAppCompatActivity implements Ti @Override public void onTimeSet(RadialPickerLayout radialPickerLayout, final int hours, final int minutes, int seconds) { + timeSet(hours, minutes); + } + + @Override + public void cancel() { + finish(); + } + + @Override + public void onTimeSet(final int hour, final int minute) { + timeSet(hour, minute); + } + + private void timeSet(final int hour, final int minute) { setResult(RESULT_OK, new Intent() {{ putExtra(EXTRA_TIMESTAMP, initial .startOfDay() - .withHourOfDay(hours) - .withMinuteOfHour(minutes) + .withHourOfDay(hour) + .withMinuteOfHour(minute) .getMillis()); }}); finish(); diff --git a/src/main/java/org/tasks/dialogs/NativeDatePickerDialog.java b/src/main/java/org/tasks/dialogs/NativeDatePickerDialog.java new file mode 100644 index 000000000..08d25c959 --- /dev/null +++ b/src/main/java/org/tasks/dialogs/NativeDatePickerDialog.java @@ -0,0 +1,68 @@ +package org.tasks.dialogs; + +import android.app.Activity; +import android.app.DatePickerDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.widget.DatePicker; + +import org.tasks.injection.InjectingNativeDialogFragment; +import org.tasks.injection.NativeDialogFragmentComponent; +import org.tasks.themes.Theme; +import org.tasks.time.DateTime; + +import javax.inject.Inject; + +public class NativeDatePickerDialog extends InjectingNativeDialogFragment implements DatePickerDialog.OnDateSetListener { + + public static NativeDatePickerDialog newNativeDatePickerDialog(DateTime initial) { + NativeDatePickerDialog dialog = new NativeDatePickerDialog(); + dialog.initial = initial; + return dialog; + } + + public interface NativeDatePickerDialogCallback { + void cancel(); + + void onDateSet(int year, int month, int day); + } + + @Inject Theme theme; + + private NativeDatePickerDialogCallback callback; + private DateTime initial; + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + DatePickerDialog datePickerDialog = new DatePickerDialog(theme.wrap(getActivity()), this, 0, 0, 0); + if (initial != null) { + datePickerDialog.updateDate(initial.getYear(), initial.getMonthOfYear() - 1, initial.getDayOfMonth()); + } + return datePickerDialog; + } + + @Override + public void onDateSet(DatePicker datePicker, int year, int month, int day) { + callback.onDateSet(year, month, day); + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + + callback.cancel(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + callback = (NativeDatePickerDialogCallback) activity; + } + + @Override + protected void inject(NativeDialogFragmentComponent component) { + component.inject(this); + } +} diff --git a/src/main/java/org/tasks/dialogs/NativeTimePickerDialog.java b/src/main/java/org/tasks/dialogs/NativeTimePickerDialog.java new file mode 100644 index 000000000..0658194ef --- /dev/null +++ b/src/main/java/org/tasks/dialogs/NativeTimePickerDialog.java @@ -0,0 +1,72 @@ +package org.tasks.dialogs; + +import android.app.Activity; +import android.app.Dialog; +import android.app.TimePickerDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.widget.TimePicker; + +import com.todoroo.andlib.utility.DateUtilities; + +import org.tasks.injection.InjectingNativeDialogFragment; +import org.tasks.injection.NativeDialogFragmentComponent; +import org.tasks.themes.Theme; +import org.tasks.time.DateTime; + +import javax.inject.Inject; + +public class NativeTimePickerDialog extends InjectingNativeDialogFragment implements TimePickerDialog.OnTimeSetListener { + + public static NativeTimePickerDialog newNativeTimePickerDialog(DateTime initial) { + NativeTimePickerDialog dialog = new NativeTimePickerDialog(); + dialog.initial = initial; + return dialog; + } + + public interface NativeTimePickerDialogCallback { + void cancel(); + + void onTimeSet(int hour, int minute); + } + + @Inject Theme theme; + + private NativeTimePickerDialogCallback callback; + private DateTime initial; + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + Context context = theme.wrap(getActivity()); + TimePickerDialog timePickerDialog = new TimePickerDialog(context, this, 0, 0, DateUtilities.is24HourFormat(context)); + if (initial != null) { + timePickerDialog.updateTime(initial.getHourOfDay(), initial.getMinuteOfHour()); + } + return timePickerDialog; + } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + + callback.cancel(); + } + + @Override + public void onTimeSet(TimePicker timePicker, int hour, int minute) { + callback.onTimeSet(hour, minute); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + callback = (NativeTimePickerDialogCallback) activity; + } + + @Override + protected void inject(NativeDialogFragmentComponent component) { + component.inject(this); + } +} diff --git a/src/main/java/org/tasks/injection/BaseNativeDialogFragmentComponent.java b/src/main/java/org/tasks/injection/BaseNativeDialogFragmentComponent.java index 2c942d932..ce811c26b 100644 --- a/src/main/java/org/tasks/injection/BaseNativeDialogFragmentComponent.java +++ b/src/main/java/org/tasks/injection/BaseNativeDialogFragmentComponent.java @@ -1,7 +1,13 @@ package org.tasks.injection; +import org.tasks.dialogs.NativeDatePickerDialog; +import org.tasks.dialogs.NativeTimePickerDialog; import org.tasks.locale.LocalePickerDialog; public interface BaseNativeDialogFragmentComponent { void inject(LocalePickerDialog localePickerDialog); + + void inject(NativeDatePickerDialog nativeDatePickerDialog); + + void inject(NativeTimePickerDialog nativeTimePickerDialog); }