8

Following the official doc http://developer.android.com/guide/topics/ui/controls/pickers.html#DatePicker.

I have used just the same code, and added only the result formatting in the onDateSet method:

public class DatePickerFragment extends DialogFragment
                            implements DatePickerDialog.OnDateSetListener {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the current date as the default date in the picker
        final Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);

        // Create a new instance of DatePickerDialog and return it
        return new DatePickerDialog(getActivity(), this, year, month, day);
    }

    @Override
    public void onDateSet(DatePicker view, int year, int month, int day) {
        Calendar c = Calendar.getInstance();
        c.set(year, month, day);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String formattedDate = sdf.format(c.getTime());

        // How to get the string from here to the caller?

    }
}

For testing, the caller activity just displays the TextView and calls the picker when the user touches the widget:

public class OrderHeadEditActivity extends Activity {

    private TextView mDTDelivery;
    ...

    @Override
    protected void onCreate(Bundle bundle) {
        ...
        mDTDelivery = (TextView) findViewById(R.id.order_head_view_dt_delivery);
        ...
        mDTDelivery.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DialogFragment picker = new DatePickerFragment();
                picker.show(getFragmentManager(), "datePicker");
            }
        });
    }
...
}

The date picker is displayed, and after setting the breakpoint at the place where the result is formatted to a string, I can see it works.

However, I do not know how to pass the string value back to the mtDTDelivery widget?

Raghunandan
  • 132,755
  • 26
  • 225
  • 256
pepr
  • 20,112
  • 15
  • 76
  • 139

2 Answers2

15

As tyczj pointed out you can use the interface method or you could make datapicker class an inner class of your activity class in which case it should be static and you need a weakreference of the outerclass

Using interface.

Define a interface in DatePickerFragment. Implement the interface in your activity class and set the date to textview.

public class DatePickerFragment extends DialogFragment
implements DatePickerDialog.OnDateSetListener {

    TheListener listener;

public interface TheListener{
    public void returnDate(String date);
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the current date as the default date in the picker
final Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
listener = (TheListener) getActivity(); 

// Create a new instance of DatePickerDialog and return it
return new DatePickerDialog(getActivity(), this, year, month, day);
}

@Override
public void onDateSet(DatePicker view, int year, int month, int day) {
Calendar c = Calendar.getInstance();
c.set(year, month, day);

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String formattedDate = sdf.format(c.getTime());
if (listener != null) 
{
  listener.returnDate(formattedDate); 

}

}
}

MainActivity

public class MainActivity extends Activity implements DatePickerFragment.TheListener{

    Button b;
    TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        b= (Button) findViewById(R.id.button1);
        tv= (TextView) findViewById(R.id.textView1);
        b.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                DialogFragment picker = new DatePickerFragment();
                picker.show(getFragmentManager(), "datePicker");
            }

        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void returnDate(String date) {
        // TODO Auto-generated method stub
        tv.setText(date);
    }

}

Second way not sure if this is the best way. I would recommend the above interface method.

public class MainActivity extends Activity {//implements DatePickerFragment.TheListener{

    Button b;
    TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        b= (Button) findViewById(R.id.button1);
        tv= (TextView) findViewById(R.id.textView1);
        b.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                DialogFragment picker = new DatePickerFragment();
                picker.show(getFragmentManager(), "datePicker");
            }

        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }


    public static class DatePickerFragment extends DialogFragment
    implements DatePickerDialog.OnDateSetListener {

        private WeakReference<MainActivity> mActivity;

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
    // Use the current date as the default date in the picker
    final Calendar c = Calendar.getInstance();
    int year = c.get(Calendar.YEAR);
    int month = c.get(Calendar.MONTH);
    int day = c.get(Calendar.DAY_OF_MONTH);
    mActivity = new WeakReference<MainActivity>((MainActivity) getActivity());

    // Create a new instance of DatePickerDialog and return it
    return new DatePickerDialog(getActivity(), this, year, month, day);
    }

    @Override
    public void onDateSet(DatePicker view, int year, int month, int day) {
    Calendar c = Calendar.getInstance();
    c.set(year, month, day);

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    String formattedDate = sdf.format(c.getTime());
      MainActivity target = mActivity.get(); 
      if (target != null) target.tv.setText(formattedDate);

    }
    }
}
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • 1
    I have to study it a bit more. Anyway, how it happens the `listener` in the `DatePickerFragment` gets its non-null value? – pepr Aug 14 '13 at 11:09
  • you define a interface in `DatePickerFragment`. Then implement the interface in your activity class. You set the value to the interface method. Since your activity class implements the interface you get the value there. Check the topic **Creating event callbacks to the activity** http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity – Raghunandan Aug 14 '13 at 11:11
  • @pepr to know about interface. http://docs.oracle.com/javase/tutorial/java/concepts/interface.html – Raghunandan Aug 14 '13 at 11:13
  • Thanks, it works. I did not noticed earlier the line `listener = (TheListener) getActivity();` :) Thanks also for the links. – pepr Aug 14 '13 at 13:25
  • @pepr glad i could help. `getActivity()` will get you the activity context of the hosting activity. remember fragment is hosted by a activity. – Raghunandan Aug 14 '13 at 13:27
  • It's clear now. The overlooked line was the answer to my first comment here ;) – pepr Aug 14 '13 at 13:44
  • How to use for multiple buttons in one Fragment @Raghunandan – Pratik Butani Apr 21 '14 at 10:55
  • 1
    @Raghunandan When I add this line `listener = (TheListener) getActivity();` and I click on the EditTextBox the App stop Working and get closed automaticly – Chlebta Nov 03 '14 at 17:13
  • @pepr can you help me in my post over here : http://stackoverflow.com/questions/26718067/get-selected-date-from-datepickerfragment/26718287 – Chlebta Nov 03 '14 at 21:39
  • In Oncick write this DialogFragment picker = new DatePickerFragment (new SelectDateFragment.TheListener() { @Override public void returnDate(String date) { dateOfBirth.setText(date); dobValue = date; } }); picker.show(getFragmentManager(), "datePicker"); And in Date DatePickerFragment add a constructor : public DatePickerFragment (TheListener listener){ this.listener = listener; } – Sagar Devanga Jul 22 '15 at 10:54
  • @Chlebta check my above answer – Sagar Devanga Jul 22 '15 at 10:54
  • @SagarDevanga no need for that. You just need the activity to implement the interface. – Raghunandan Jul 22 '15 at 11:13
  • mine crashed too when i wrote this listener = (TheListener) getActivity(); So i figured out a work around.Anyways thanx – Sagar Devanga Jul 22 '15 at 12:15
  • You need to check why it crashed. But if ur activity implements the interface it will work fine. You can check the same in the docs fragment to fragment communication – Raghunandan Jul 22 '15 at 14:45
  • @Raghunandan: Could you elaborate on the "static nested class + weak reference" approach you mention at the beginning of your post? More specifically, what exactly do you mean by "weak reference"? The only option I see would consist in using `getActivity()` to get a reference to the original activity and notify it of any changes. – balu Aug 19 '16 at 18:32
  • Look at the second answer posted in the post. Also read about static and weak reference along with memory leaks due to context – Raghunandan Aug 19 '16 at 21:13
4

The proper way is to create a callback to the activity passing the string.

take a look at Communicating with an Activity

tyczj
  • 71,600
  • 54
  • 194
  • 296