diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java index a53a4e60..51dde1a7 100644 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java +++ b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java @@ -1,26 +1,58 @@ package com.reactcommunity.rndatetimepicker; import java.util.Calendar; + import android.os.Bundle; public class RNDate { - private Calendar now; + private Calendar now; - public RNDate(Bundle args) { - now = Calendar.getInstance(); + public RNDate(Bundle args) { + now = Calendar.getInstance(); - if (args != null && args.containsKey(RNConstants.ARG_VALUE)) { - set(args.getLong(RNConstants.ARG_VALUE)); + if (args != null && args.containsKey(RNConstants.ARG_VALUE)) { + set(args.getLong(RNConstants.ARG_VALUE)); + } } - } - public void set(long value) { - now.setTimeInMillis(value); - } + public Calendar get() { + return now; + } - public int year() { return now.get(Calendar.YEAR); } - public int month() { return now.get(Calendar.MONTH); } - public int day() { return now.get(Calendar.DAY_OF_MONTH); } - public int hour() { return now.get(Calendar.HOUR_OF_DAY); } - public int minute() { return now.get(Calendar.MINUTE); } + public void set(long value) { + now.setTimeInMillis(value); + } + + public int year() { + return now.get(Calendar.YEAR); + } + + public int month() { + return now.get(Calendar.MONTH); + } + + public int day() { + return now.get(Calendar.DAY_OF_MONTH); + } + + public int hour() { + return now.get(Calendar.HOUR_OF_DAY); + } + + public int minute() { + return now.get(Calendar.MINUTE); + } + + public boolean equals(Object o) { + if (o == this) { + return true; + } + + if (!(o instanceof RNDate)) { + return false; + } + RNDate otherDate = (RNDate) o; + + return now.equals(otherDate.get()); + } } diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java index 3466848f..530a0029 100644 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java +++ b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java @@ -30,6 +30,9 @@ public class RNDatePickerDialogFragment extends DialogFragment { private DatePickerDialog instance; + @Nullable + private RNDate date; + @Nullable private OnDateSetListener mOnDateSetListener; @Nullable @@ -40,12 +43,24 @@ public class RNDatePickerDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { Bundle args = getArguments(); + date = new RNDate(args); instance = createDialog(args, getActivity(), mOnDateSetListener); return instance; } public void update(Bundle args) { - final RNDate date = new RNDate(args); + final RNDate newDate = new RNDate(args); + + // React may rerender components whenever it feels like, even when props haven't changed. + // Calling update on the native android picker will always change its currently selected value. + // This happens even if the user has changed the selection in the picker. + // By only updating the selected value of the picker if it actually differs from last render, + // we avoid the user suddenly having their selection change seemingly randomly. + if (date != null && date.equals(newDate)) { + return; + } + + date = newDate; instance.updateDate(date.year(), date.month(), date.day()); } diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogFragment.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogFragment.java index 0df49a20..f0c64d7a 100644 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogFragment.java +++ b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogFragment.java @@ -28,6 +28,9 @@ public class RNTimePickerDialogFragment extends DialogFragment { private TimePickerDialog instance; + @Nullable + private RNDate date; + @Nullable private OnTimeSetListener mOnTimeSetListener; @Nullable @@ -38,12 +41,24 @@ public class RNTimePickerDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Bundle args = getArguments(); + date = new RNDate(args); instance = createDialog(args, getActivity(), mOnTimeSetListener); return instance; } public void update(Bundle args) { - final RNDate date = new RNDate(args); + final RNDate newDate = new RNDate(args); + + // React may rerender components whenever it feels like, even when props haven't changed. + // Calling update on the native android picker will always change its currently selected value. + // This happens even if the user has changed the selection in the picker. + // By only updating the selected value of the picker if it actually differs from last render, + // we avoid the user suddenly having their selection change seemingly randomly. + if (date != null && date.equals(newDate)) { + return; + } + + date = newDate; instance.updateTime(date.hour(), date.minute()); }