8

I am using a DialogFragment to return a DatePickerDialog in onCreateDialog(). I have set the dateSetListener to be the DialogFragment ("this" in example below) and everything works except that onDateSet() is called when a screen rotation occurs, which is undesirable. How can I get onDateSet to not be called when the screen is rotated?

My DialogFragment

public static class DateDialogFragment extends DialogFragment implements
DatePickerDialog.OnDateSetListener{

    public static DateDialogFragment newInstance() {
        return new DateDialogFragment();
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new DatePickerDialog(getActivity(), this, 2012, 11, 19);
    }

    @Override
    public void onDateSet(DatePicker view, int year, int monthOfYear,
        int dayOfMonth) {
        //This is called when screen rotated, which I dont want
        Toast.makeText(getActivity(), "Year: "+year+" Month: "+monthOfYear+" Day: "+dayOfMonth, Toast.LENGTH_SHORT).show();
    }

}

And this is how I call it

if(getActivity()!=null){
    FragmentManager fm = getActivity().getSupportFragmentManager();
    DialogFragment newFragment = DateDialogFragment.newInstance();
    newFragment.show(fm, "dialog");
}
jfortunato
  • 11,607
  • 3
  • 19
  • 14
  • Have a look at [setRetainInstance()](http://stackoverflow.com/questions/11182180/understanding-fragments-setretaininstanceboolean) – Dmide Apr 24 '14 at 10:02
  • am I correct ? you do not want to recall on **dateset** method when screen rotated – CompEng Apr 24 '14 at 10:21
  • Since posting a bounty on this question, I've discovered that it's a duplicate of http://stackoverflow.com/questions/11444238/jelly-bean-datepickerdialog-is-there-a-way-to-cancel but I can't vote to close it because of my bounty. – Graham Borland Apr 30 '14 at 10:08

6 Answers6

9

In onDateSet method, check whether Activity is being restarted due to the configuration change by using Activity::isChangingConfigurations. If yes, then don't display the Toast.

@Override
public void onDateSet(android.widget.DatePicker view, int year, int monthOfYear, int dayOfMonth) {
    if( ! this.getActivity().isChangingConfigurations() ) {
        // Dialog is dismissed by user explicitly, hence show the Toast message.       
        Toast.makeText(getActivity(), "Year: "+year+" Month: "+monthOfYear+" Day: "+dayOfMonth, Toast.LENGTH_SHORT).show();
    }
}

I've tested it and works perfectly. Let me know if any further help is required.

Manish Mulimani
  • 17,535
  • 2
  • 41
  • 60
  • 1
    This will work only in configuration change , but `onDateSet` will also get called when user dismiss `DatePickerDialog` by back key. – Libin May 02 '14 at 02:01
3

You could try using a flag in the attached/detached callbacks of the dialog. The idea is to cancel any triggering of the listener while the dialog isn't yet attached to the window(so the change can't possible come from the user) like a restore(which I think is the reason for the listener being called again):

// a field in the DateDialogFragment
private boolean mShouldBeCanceled = true; // cancel the listener when this is true(the default)

//...
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
     return new DatePickerDialog(getActivity(), this, 2012, 11, 19) {

                @Override
                public void onAttachedToWindow() {
                    mShouldBeCanceled = false;
                }

                @Override
                public void onDetachedFromWindow() {
                    mShouldBeCanceled = true;
                }
     };
}

and use the flag in the listener(due to the listener being initialized only in the constructor):

@Override
public void onDateSet(DatePicker view, int year, int monthOfYear,
    int dayOfMonth) {
    if (mShouldBeCanceled) {
            return; // not a valid listener triggering
    }
    //This is called when screen rotated, which I dont want
    Toast.makeText(getActivity(), "Year: "+year+" Month: "+monthOfYear+" Day: "+dayOfMonth, Toast.LENGTH_SHORT).show();
}
user
  • 86,916
  • 18
  • 197
  • 190
2

The way DatePickerDialog is implemented that it will notify the DataSet Change in onStop if OnDateSetListener is registered.

You could also see onDateSet called when Back key is pressed when DatePickerDialog is Shown(not only orientation)

Reason, when you created the DatePickerDialog instance , you have registered the callback listener.

So the best way is to create a custom Dialog which extends DatePickerDialog and override the onStop

Custom DatePickerDialog

  private static class CustomDatePickerDialog extends DatePickerDialog{

    public CustomDatePickerDialog(Context context, OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth) {
        super(context, callBack, year, monthOfYear, dayOfMonth);
    }

    @Override
    protected void onStop() {
        return;
    }
}

Finally , change the CreateDialog to

@Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new CustomDatePickerDialog(getActivity(), this, 2012, 11, 19);
    }

This should work perfectly. Let me know if you see any issue.

Libin
  • 16,967
  • 7
  • 61
  • 83
1

Try to replace the line

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
         return new DatePickerDialog(getActivity(), this, 2012, 11, 19);
    }

by

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
     super.onCreateDialog(savedInstanceState);
 }
Inther
  • 161
  • 4
0

add this property to your activity in manifest

android:configChanges="keyboardHidden|orientation"
Sishin
  • 2,001
  • 1
  • 17
  • 22
-1

When the screen is rotated the activity is destroyed and recreated, this creates a new fragment each time. One way to avoid this problem would be to change the placement of your if(getActivity()!=null) statement in your code. Place it somewhere that is not affected by the activity recreation (not in the OnCreate method).

Rilcon42
  • 9,584
  • 18
  • 83
  • 167