作为Big的Android指南示例“犯罪意图”的一部分,我正在更新一个在Date/TimePicker中输入日期/时间的按钮。按钮和日期/时间选择器驻留在不同的片段中。我是在他们之间传输数据的意图。它在前Lollipop设备上运行良好,但似乎不更新Android5.0或Lollipop设备上的按钮文本。我遗漏了什么?
完整的代码可以在Github上看到。
CrimeFragment.java
package com.sudhirkhanger.android.criminalintent;
import java.util.Date;
import java.util.UUID;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
public class CrimeFragment extends Fragment {
private Crime mCrime;
private EditText mTitleField;
private Button mDateButton;
private Button mTimeButton;
private CheckBox mSolvedCheckBox;
private static final String TAG = "CriminalFragment";
public static final String EXTRA_CRIME_ID = "com.sudhirkhanger.android.criminalintent.crime_id";
private static final String DIALOG_DATE = "date";
private static final String DIALOG_TIME = "time";
private static final int REQUEST_DATE = 0;
private static final int REQUEST_TIME = 1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID crimeId = (UUID) getArguments().getSerializable(EXTRA_CRIME_ID);
mCrime = CrimeLab.get(getActivity()).getCrime(crimeId);
}
private void updateDateAndTime() {
Date d = mCrime.getDate();
CharSequence c = DateFormat.format("EEEE, MMM dd, yyyy", d);
CharSequence t = DateFormat.format("h:mm a", d);
mDateButton.setText(c);
mTimeButton.setText(t);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
View v = inflater.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.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FragmentManager fm = getActivity().getSupportFragmentManager();
DatePickerFragment dialog = DatePickerFragment
.newInstance(mCrime.getDate());
dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE);
dialog.show(fm, DIALOG_DATE);
}
});
mTimeButton = (Button) v.findViewById(R.id.crime_time);
mTimeButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FragmentManager fm = getActivity().getSupportFragmentManager();
TimePickerFragment dialog = TimePickerFragment
.newInstance(mCrime.getDate());
dialog.setTargetFragment(CrimeFragment.this, REQUEST_TIME);
dialog.show(fm, DIALOG_TIME);
}
});
updateDateAndTime();
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;
}
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);
updateDateAndTime();
} else if (requestCode == REQUEST_TIME) {
Date date = (Date) data
.getSerializableExtra(TimePickerFragment.EXTRA_TIME);
mCrime.setDate(date);
updateDateAndTime();
}
}
}DatePickerFragment.java
package com.sudhirkhanger.android.criminalintent;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.View;
import android.widget.DatePicker;
import android.widget.DatePicker.OnDateChangedListener;
public class DatePickerFragment extends DialogFragment {
public static final String EXTRA_DATE = "com.sudhirkhanger.android.criminalintent.date";
private Date mDate;
public static DatePickerFragment newInstance(Date date) {
Bundle args = new Bundle();
args.putSerializable(EXTRA_DATE, date);
DatePickerFragment fragment = new DatePickerFragment();
fragment.setArguments(args);
return fragment;
}
private void sendResult(int resultCode) {
if (getTargetFragment() == null)
return;
Intent i = new Intent();
i.putExtra(EXTRA_DATE, mDate);
getTargetFragment().onActivityResult(getTargetRequestCode(),
resultCode, i);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mDate = (Date) getArguments().getSerializable(EXTRA_DATE);
// Create a Calendar to get the year, month, and day
final 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 OnDateChangedListener() {
public void onDateChanged(DatePicker view, int year, int month,
int day) {
// Translate year, month, day into a Date object using a
// calendar
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
mDate = new GregorianCalendar(year, month, day, hour, minute)
.getTime();
// Update argument to preserve selected value on rotation
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() {
public void onClick(DialogInterface dialog,
int which) {
sendResult(Activity.RESULT_OK);
}
}).create();
}
}发布于 2014-12-10 07:26:05
问题不在于片段之间的通信,而是由于某种原因,Lollipop中的默认CalendarView DatePicker从不调用OnDateChanged()方法,因此DatePickerFragment.java中的mDate不会被更改;DatePickerFragment将从CrimeFragment收到的相同值发送给CrimeFragment,因此看起来这两个片段之间的通信不起作用。
棒棒糖DatePicker在OnDateChanged()处于SpinnerView模式时确实调用了SpinnerView(),因此CrimeFragment的日期将得到正确更新。不幸的是,Lollipop忽略了android:calendarViewShown=文件中DatePicker标记中的“false”指令。强制DatePicker显示为派生器的唯一方法是在DatePicker的xml标记中包含一个android:datePickerMode="spinner“指令。您将得到一个警告,这个指令仅在API 21中被支持,但是运行pre-5.0 Android.You的设备必须保留calendarViewShown=对pre-5.0设备的“false”指令,这将被忽略。
DatePickerDialog似乎已经在Android5.0中得到了修复,所以您也可以使用DatePickerFragment中的该资源来使其正常工作。
https://stackoverflow.com/questions/27214832
复制相似问题