Как поместить ранее выбранную дату в Android DatePickerDialog?

У меня есть простой DatePickerFragment, который загружает сегодняшнюю дату в качестве даты по умолчанию в DatePickerDialog, который отображается пользователю. Затем пользователь выбирает дату из DatePicker, а затем код устанавливает эту дату в строке EditText. Если позже пользователь снова щелкнет строку EditText, чтобы изменить выбранную дату, я хочу, чтобы в диалоговом окне отображалась выбранная дата, а не сегодняшняя дата.

Я использую тест на пустоту в строке EditText. Если пусто, установите сегодняшнюю дату в Диалоге. Если не пусто, установите существующую дату в диалоговом окне из строки EditText, которую ранее выбрал пользователь. До сих пор я пытался передать ранее выбранную дату в Bundle из onDateSet обратно в onCreateDialog. Я получаю фатальное исключение: «Фрагмент уже активен», поэтому моя логика должна быть настроена в неправильном цикле с фрагментом. Что мне здесь не хватает?

partial Fragment file:

import android.content.DialogInterface;
import android.support.v4.app.DialogFragment;
import android.app.Dialog;
import android.app.DatePickerDialog;
import android.view.inputmethod.InputMethodManager;
import android.os.Bundle;
import android.widget.DatePicker;
import android.widget.EditText;
import java.util.Calendar;

public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

private EditText txtDate;
private int currentyear;
private int currentmonth;
private int currentday;
private int prvselectedyear;
private int prvselectedmonth;
private int prvselectedday;

private String stringDueDateFrag;

public DatePickerFragment() {
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {

    txtDate = (EditText) getActivity().getWindow().getDecorView().getRootView().findViewById(R.id.FEditText);

    // If the FEditText line is empty (no "Due Date") entered then add current date to a new DatePickerDialog.
    if (txtDate.getText().length() == 0) {
    // DatePickerDialog is a simple dialog containing a DatePicker.
    // Set up a Calendar object that will capture the current date for the DatePickerDialog to use.
    // Use the current date as the default date in the DatePicker.
    final Calendar cal = Calendar.getInstance();
    currentyear = cal.get(Calendar.YEAR);
    currentmonth = cal.get(Calendar.MONTH);
    currentday = cal.get(Calendar.DAY_OF_MONTH);

    // Create a new instance of DatePickerDialog by passing 5 parameters/arguments to the constructor and return it.
    DatePickerDialog dialog = new DatePickerDialog(getActivity(), this, currentyear, currentmonth, currentday);
    dialog.getDatePicker().setCalendarViewShown(true);
    dialog.getDatePicker().setSpinnersShown(false);
    dialog.setTitle("Select a Due Date");

    return dialog;
    }

    // If the FEditText line already has a due date then put the user's previously selected date in
    // the DatePickerDialog to edit.
    else {
       final Calendar prvcalendar = Calendar.getInstance();
       prvselectedyear = prvcalendar.get(Calendar.YEAR);
       prvselectedmonth = prvcalendar.get(Calendar.MONTH);
       prvselectedday = prvcalendar.get(Calendar.DAY_OF_MONTH);

       // Create a new instance of DatePickerDialog by passing 5 parameters/arguments to the constructor and return it.
       DatePickerDialog dialog = new DatePickerDialog(getActivity(), this, prvselectedyear, prvselectedmonth, prvselectedday);
       dialog.getDatePicker().setCalendarViewShown(true);
       dialog.getDatePicker().setSpinnersShown(false);
       dialog.setTitle("Select a Due Date");

       return dialog;
    }
}

public void onDateSet (DatePicker view,int year, int month, int day) {
    txtDate = (EditText) getActivity().getWindow().getDecorView().getRootView().findViewById(R.id.FEditText);
    stringDueDateFrag = (month + 1) + "/" + day + "/" + year + " ";
    txtDate.setText(stringDueDateFrag);
    txtDate.setSelection(txtDate.getText().length());

    // Set up a Calendar object to capture the user selected date in case the user wants
    // edit the date later.  Put the user selected date in a Bundle for onCreateDialog function to use.
    Calendar prvcalendar = Calendar.getInstance();
    Bundle argsbundle = new Bundle();
    argsbundle.putInt("year", prvcalendar.get(Calendar.YEAR));
    argsbundle.putInt("month", prvcalendar.get(Calendar.MONTH));
    argsbundle.putInt("day", prvcalendar.get(Calendar.DAY_OF_MONTH));
    setArguments(argsbundle);
}

частичный файл активности:

public class Activity extends AppCompatActivity {

private ListenerEditText fListenerEditText;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.cardviewinput);

    fListenerEditText = (ListenerEditText) findViewById(R.id.FEditText);

    fListenerEditText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            DialogFragment newFragment = new DatePickerFragment();
            newFragment.show(getSupportFragmentManager(), "datePicker");
        }
    });

    fListenerEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus && (fListenerEditText.getText().length() == 0)) {
                DialogFragment newFragment = new DatePickerFragment();
                newFragment.show(getSupportFragmentManager(), "datePicker");
            }
        }
    });

Вот вывод исключения из Android Studio:

09-19 03:18:43.052  17379-17379/com.example.jdw.fourthscreen W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xa6310288)
09-19 03:18:43.052  17379-17379/com.example.jdw.fourthscreen E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.IllegalStateException: Fragment already active
            at android.support.v4.app.Fragment.setArguments(Fragment.java:551)
            at com.example.jdw.fourthscreen.DatePickerFragment.onDateSet(DatePickerFragment.java:100)
            at android.app.DatePickerDialog.tryNotifyDateSet(DatePickerDialog.java:148)
            at android.app.DatePickerDialog.onClick(DatePickerDialog.java:116)
            at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:166)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4745)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)

person AJW    schedule 19.09.2015    source источник
comment
Всякий раз, когда вы публикуете проблему, с которой вы столкнулись, не забудьте добавить трассировку стека в свой пост.   -  person Derek Fung    schedule 19.09.2015
comment
Опубликуйте код, в котором вы вызываете этот диалог. Потому что из вашего исключения ( IllegalStateException: Fragment already active ) вы пытаетесь снова показать диалоговое окно, прежде чем закрыть его.   -  person Rami    schedule 19.09.2015
comment
Привет, Код активности добавлен к исходному вопросу выше.   -  person AJW    schedule 19.09.2015


Ответы (1)


Когда ваш EditText пуст, и вы нажимаете на него, вы дважды показываете диалоговое окно. Первый в методе onClick() и второй в onFocusChange().

Я предлагаю вам добавить переменную boolean в ваш класс Dialog, чтобы указать, отображается ли уже диалоговое окно.

Вы можете переопределить методы show() и onDismiss():

private boolean mIsShown = false;

@Override
public void show(FragmentManager manager, String tag) {    
    super.show(manager, tag);
    mIsShown = true;
}

@Override
public void onDismiss(DialogInterface dialog) {
    mIsShown = false;
    super.onDismiss(dialog);
}

public boolean isDialogShown(){
    return mIsShown;
}

Затем, прежде чем вызывать диалоговое окно, вам нужно проверить, не показано ли оно уже.

DatePickerFragment mPickerFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.cardviewinput);

    fListenerEditText = (ListenerEditText) findViewById(R.id.FEditText);

    fListenerEditText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(mPickerFragment == null || !mPickerFragment.isDialogShown()){
               mPickerFragment = new DatePickerFragment();
               mPickerFragment.show(getSupportFragmentManager(), "datePicker");
            }
        }
    });

    fListenerEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus && (fListenerEditText.getText().length() == 0) && ((mPickerFragment == null || !mPickerFragment.isDialogShown()))) {
                mPickerFragment = new DatePickerFragment();
                mPickerFragment.show(getSupportFragmentManager(), "datePicker");
            }
        }
    });
}
person Rami    schedule 19.09.2015