質問

The CrimeFragment Fragment has a button that stores the date and time of a crime. It is changeable when the user clicks the button and fires the ClickListener. I have been instructed to have the ClickListener create an AlertDialog that asks the user whether he would like to change the date or the time. This choice calls the correct Fragment (DatePickerFragment/TimePickerFragment) which then returns the chosen data to mDate.

When creating a new AlertDialog using Builder, the constructor asks for context. I have tried getActivity(), getContext(), and getApplicationContext() to no avail. I believe that is all that I need to keep writing but do not want to go any further until I get this figured out so I can start testing. I can post up more code if needed but I figured that posting up a wall of code would be a little offsetting.

This first block is the CrimeFragment class

public class CrimeFragment extends Fragment {

public static final String EXTRA_CRIME_ID = "criminalReport.CRIME_ID";
public static final String DIALOG_DATE = "date";
public static final int REQUEST_DATE = 0;
public Crime mCrime;
private EditText mTitleField;
private Button mDateButton;
private CheckBox mSolvedCheckBox;
final Context context = this.getActivity();

@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    //mCrime = new Crime();
    //UUID crimeID = (UUID) getActivity().getIntent().getSerializableExtra(EXTRA_CRIME_ID);
    UUID crimeID = (UUID) getArguments().getSerializable(EXTRA_CRIME_ID);
    mCrime = CrimeLab.get(getActivity()).getCrime(crimeID);
}

@Override
//You explicitly inflate the fragment's view 
//by calling layoutInflater's inflate()
public View onCreateView(LayoutInflater inflator, ViewGroup parent, final Bundle savedInstanceState){
    //first parameter : layout resource ID
    //second parameter : view's parent
    //third parameter : tells the layout inflater whether to add the inflated view to the view's parent
    View v = inflator.inflate(R.layout.fragment_crime, parent, false);
    mTitleField=(EditText)v.findViewById(R.id.crime_title);
    mTitleField.setText(mCrime.getTitle());
    mTitleField.addTextChangedListener(new TextWatcher(){
        public void onTextChanged(CharSequence c, int start, int before, int count){
            mCrime.setTitle(c.toString());
        }
        public void beforeTextChanged(CharSequence c, int start, int count, int after){
            //this space intentionally left blank
        }
        public void afterTextChanged(Editable c){
            //this one too
        }
    });
    mDateButton = (Button)v.findViewById(R.id.crime_date);
    mDateButton.setText(mCrime.getDate().toString());
    //mDateButton.setEnabled(false);
    mDateButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            TimeDateDialogFragment tddf = TimeDateDialogFragment.newInstance(context, CrimeFragment.this, REQUEST_DATE, DIALOG_DATE, mCrime);
            tddf.show(getFragmentManager(), "dialog");

            //FragmentManager fm = getActivity().getSupportFragmentManager();
            //DatePickerFragment dialog = DatePickerFragment.newInstance(mCrime.getDate());
            //dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE);
            //dialog.show(fm, DIALOG_DATE);
        }
    });
    mSolvedCheckBox = (CheckBox) v.findViewById(R.id.crime_solved);
    mSolvedCheckBox.setChecked(mCrime.isSolved());
    mSolvedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
            //set the crime's solved property
            mCrime.setSolved(isChecked);
        }
        });
    return v;
}

//attaching argument to a fragment must be done after the fragment is creater
//but before it is added to an activity.  this method create the fragment 
//instance and bundle up and set its agrument
public static CrimeFragment newInstance(UUID crimeID){
    Bundle args = new Bundle();
    args.putSerializable(EXTRA_CRIME_ID, crimeID);

    CrimeFragment fragment = new CrimeFragment();
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
    if (resultCode != Activity.RESULT_OK){
        return;
    }
    if (requestCode == REQUEST_DATE){
        Date date = (Date) data.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
        mCrime.setDate(date);
        mDateButton.setText(mCrime.getDate().toString());
    }
}
}

This second block is the TimeDateDialogFragment class that I created.

public class TimeDateDialogFragment extends DialogFragment {

static Context context;
static String DIALOG_DATE;
static int REQUEST_DATE;
static CrimeFragment crimeFragment;
static Crime mCrime;

public static TimeDateDialogFragment newInstance(final Context con, final CrimeFragment crimeFrag, final int rd, 
        final String dd, final Crime mc) {
    TimeDateDialogFragment frag = new TimeDateDialogFragment();
    Bundle args = new Bundle();
    args.putInt("title", 1);
    frag.setArguments(args);

    context = con;
    DIALOG_DATE = dd;
    REQUEST_DATE = rd;
    crimeFragment = crimeFrag;
    mCrime = mc;
    return frag;
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    int title = getArguments().getInt("title");

    return new AlertDialog.Builder(getActivity())
            //.setIcon(R.drawable.alert_dialog_icon)
            .setTitle("Make a selection: ")
            .setPositiveButton("Change date",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        //change the date
                        FragmentManager fm = getActivity().getSupportFragmentManager();
                        DatePickerFragment dpf = DatePickerFragment.newInstance(mCrime.getDate());
                        dpf.setTargetFragment(crimeFragment, REQUEST_DATE);
                        dpf.show(fm, DIALOG_DATE);
                    }
                }
            )
            .setNegativeButton("Change time",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        //change the time
                        FragmentManager fm = getActivity().getSupportFragmentManager();
                        TimePickerFragment tpf = TimePickerFragment.newInstance(savedInstanceState, );
                    }
                }
            )
            .create();
}
}

If you see any other glaring errors, I would love to hear about them.

edit - I created a Context object inside the CrimeFragment class and tried passing that through to the AlertDialog class that I created.

edit2- MASSIVE UPDATE. Got the DatePicker working, now for the TimePicker. the newInstance(... TimePickerDialog.OnTimeSetListener callBack...) method calls for that TPD.OnTimeSetListener. I cannot find much information on that and have no idea what it is looking for. Any ideas? I have fully updated the code with the working stuff.

TimePickerFragment class from the documentation:

public class TimePickerFragment extends DialogFragment
implements TimePickerDialog.OnTimeSetListener {

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // Use the current time as the default values for the picker
    final Calendar c = Calendar.getInstance();
    int hour = c.get(Calendar.HOUR_OF_DAY);
    int minute = c.get(Calendar.MINUTE);

    // Create a new instance of TimePickerDialog and return it
    return new TimePickerDialog(getActivity(), this, hour, minute,
    DateFormat.is24HourFormat(getActivity()));
}

public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
    // Do something with the time chosen by the user
}
}
役に立ちましたか?

解決

The problem is caused by

AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());

Replace getApplicationContext() with getActivity()


You changed your code, anyway DialogFragment.onCreateDialog is different from original override and it's the wrong way to do what you want.

TimeDateDialogFragment tddf = new TimeDateDialogFragment();
tddf.onCreateDialog(context, CrimeFragment.this, REQUEST_DATE, DIALOG_DATE, mCrime);

use normal .show() method as you did in the onClick method and use setArguments/getArguments to pass datas to it.

And change onCreateDialog method too.

Documentation.


  1. You should show your fragment using his .show() method.
  2. Override onCreateDialog here and create and return the dialog to show

    • If you need to pass any data to the fragment you can use setArguments and getArguments.
    • Use bundle and then .setArguments before show it.

      TimeDateDialogFragment tddf = new TimeDateDialogFragment();
      
      Bundle bundle = new Bundle();
      
      bundle.put/*something*/(/* something else */);
      bundle.putInt("hello", 5);
      
      tddf.setArguments(bundle);
      
      tddf.show(getFragmentManager(), "A");
      
    • bundle.putX(X, Y) will be used to put something in the map bundle, in your case will put

      CrimeFragment.this, REQUEST_DATE, DIALOG_DATE, mCrime

    • To read the bundle use getArguments() then getArguments().getX, example: getArguments().getInt("NAME"); Example:

      Bundle bundle = getArguments();
      
    • then int x = bundle.getInt("hello"); and you will get 5 in x.

  3. Inside your onCreateDialog, you should use getActivity() it will return the context of the activity which asked to show the fragment.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top