问题
this is my first post and I am trying to create a very simple tasker app, however I am having issues with (what seems to be) the onDateChanged method. It seems that it does not implement the changes even though the dialog pops up normally. There are no errors in the log and i double checked various solutions with similar functionalities, but i could not find something relevant. (minSDK 16, Target 21)
Thanks a lot in advance and I am sorry if it is something obvious.
public class DatePickerFragment extends DialogFragment {
public static final String EXTRA_DATE = "thanoschatz.com.annastodolist.date";
private Date mDate;
public static DatePickerFragment newInstance(Date mDate) {
Bundle args = new Bundle();
args.putSerializable(EXTRA_DATE, mDate);
DatePickerFragment fragment = new DatePickerFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mDate = (Date) getArguments().getSerializable(EXTRA_DATE);
Calendar calendar = Calendar.getInstance();
calendar.setTime(mDate);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
View v = getActivity().getLayoutInflater().inflate(R.layout.dialog_date, null);
DatePicker datePicker = (DatePicker) v.findViewById(R.id.dialog_date_datepicker);
datePicker.init(year, month, day, new DatePicker.OnDateChangedListener() {
@Override
public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
mDate = new GregorianCalendar(year, monthOfYear, dayOfMonth).getTime();
getArguments().putSerializable(EXTRA_DATE, mDate);
}
});
return new AlertDialog.Builder(getActivity())
.setView(v) //
.setTitle(R.string.date_picker_title) //
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
sendResult(Activity.RESULT_OK);
}
})
.create();
}
private void sendResult(int resultCode) {
if (getTargetFragment() == null) return;
Intent intent = new Intent();
intent.putExtra(EXTRA_DATE, mDate);
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
}
}
public class ToDoFragment extends Fragment {
public static final String EXTRA_TODO_ID = "thanoschatz.com.annastodolist.todo_id";
private static final String DIALOG_DATE = "date";
private static final int REQUEST_DATE = 0;
private ToDo mToDo;
private EditText mTitleField;
private Button mDateButton;
private CheckBox mDoneCheckBox;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
UUID toDoId = (UUID)getArguments().getSerializable(EXTRA_TODO_ID);
mToDo= ToDoLab.get(getActivity()).getToDo(toDoId);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_todo, container, false);
wireTitleField(view);
wireDateButton(view);
wireSolvedCheckBox(view);
return view;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode != Activity.RESULT_OK) {
return;
}
if (requestCode == REQUEST_DATE) {
Date mDate = (Date)intent.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
mToDo.setDate(mDate);
}
}
public ToDoFragment(){
}
public static ToDoFragment newInstance(UUID mId) {
Bundle args = new Bundle();
args.putSerializable(EXTRA_TODO_ID, mId);
ToDoFragment fragment = new ToDoFragment();
fragment.setArguments(args);
return fragment;
}
private void wireDateButton(View view) {
SimpleDateFormat dateFormatter = getSimpleDateFormat();
mDateButton = (Button)view.findViewById(R.id.toDo_date);
updateDate(dateFormatter);
mDateButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
FragmentManager fragmentManager = getFragmentManager();
DatePickerFragment datePicker = DatePickerFragment.newInstance(mToDo.getDate());
datePicker.setTargetFragment(ToDoFragment.this, REQUEST_DATE);
datePicker.show(fragmentManager, DIALOG_DATE);
}
});
}
}
回答1:
There is also another way to get it to work under 5.0 and keeping your DatePicker in Calendar mode. What you can do is set to listen to the click changes on the dialog, and update your date reference. If by any chance your closing dialog handler notices that the last button clicked was "cancel" then simply ignore the change...
private String dateString; //last date saved.
private String clickedDate; //last date clicked on DatePicker
private DatePicker datePicker;
@Override
protected void onDialogClosed(boolean shouldSave) {
if (shouldSave && this.clickedDate != null) {
updateDate(this.clickedDate);
this.clickedDate = null;
}
}
@Override
public void onDateChanged(DatePicker view, int year, int month, int day) {
Calendar selected = new GregorianCalendar(year, month, day);
this.clickedDate = formatter().format(selected.getTime());
}
@Override
public void onClick(DialogInterface dialog, int which) {
super.onClick(dialog, which);
datePicker.clearFocus();
onDateChanged(datePicker, datePicker.getYear(), datePicker.getMonth(),
datePicker.getDayOfMonth());
onDialogClosed(which == DialogInterface.BUTTON_NEGATIVE);
}
private void updateDate(String s) {
dateString = s;
}
This is where the idea came from https://github.com/bostonandroid/DatePreference/blob/master/DatePreference/src/org/bostonandroid/datepreference/DatePreference.java
回答2:
You're running your app under Android 5.0, right? I've found that under 5.0 a DatePicker will not call the OnDateChanged() method when it's in its default CalendarView mode, but it will do so if it's Spinners mode. Your code should work if the DatePicker is shown as spinners.
The only way I've found to force a 5.0 DatePicker into Spinners mode is to include the following in the xml code defining the DatePicker:
android:datePickerMode="spinner"
Lollipop seems to ignore any android:CalendarViewShown="false" directives as well as all DatePicker.setCalendarViewShown(false) calls in Java code. The datePickerMode xml directive is supported only in API 21, but any device running at a lower API level will just ignore it, so your code will still run on older versions of Android. Keep the CalendarViewShown="false" directive in your xml code, however, if you want the DatePicker to be spinners on a pre-5.0 device.
回答3:
Use DatePickerDialog
instead:
return new DatePickerDialog(getActivity(), this, year, month, day);
Your class declaration should look like this:
public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
You will need to implement OnDateSet
method:
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
mDate = new GregorianCalendar(year, monthOfYear, dayOfMonth).getTime();
getArguments().putSerializable(EXTRA_DATE, mDate);
sendResult(Activity.RESULT_OK);
}
Or you can set your theme to Holo.Light which seems to support DatePicker OnDateChanged events. In your manifest file:
<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:theme="@android:style/Theme.Holo.Light">
Or you can lower your minimum API level, this will set Holo theme by default:
<uses-sdk android:minSdkVersion="15" />
回答4:
This is my answer that can simply solve this question:
public class MyDatePickerDialog extends DatePickerDialog
{
public MyDatePickerDialog(Context context, OnDateSetListener callBack, int year,
int monthOfYear, int dayOfMonth)
{
super(context, callBack, year, monthOfYear, dayOfMonth);
}
@TargetApi(11)
@Override
public void onClick(DialogInterface dialog, int which)
{
getDatePicker().clearFocus();
super.onClick(dialog, which);
}
}
来源:https://stackoverflow.com/questions/26589338/ondatechanged-method-does-not-seem-to-work