第22章 Master-Detail 用户界面
22.1.1 修改SingleFragmentActivity
protected int getLayoutResId() {
return R.layout.activity_fragment;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResId());
...
22.1.3 使用别名资源
创建默认的别名资源值(res/values/refs.xml)
<resources>
<item name="activity_masterdetail" type="layout">@layout/activity_fragment</item>
</resources>
用于大屏幕设备的可选资源(res/values-sw600dp/refs.xml)
<resources>
<item name="activity_masterdetail" type="layout">@layout/activity_twopane</item>
</resources>
再次切换布局(CrimeListActivity.java)
@Override
protected int getLayoutResId() {
return R.layout.activity_masterdetail;
}
fragment回调接口
添加回调接口(CrimeListFragment.java)
public class CrimeListFragment extends ListFragment {
private MyCallBacks mCallBacks;
...
public interface MyCallBacks {
void onCrimeSelected(Crime crime);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallBacks = (MyCallBacks) activity;
}
@Override
public void onDetach() {
super.onDetach();
mCallBacks = null;
}
实现回调接口(CrimeListActivity.java)
public class CrimeListActivity extends SingleFragmentActivity implements CrimeListFragment.MyCallBacks{
@Override
public void onCrimeSelected(Crime crime) {
if (findViewById(R.id.detailFragmentContainer) == null) {
Intent intent = new Intent(this, CrimePagerActivity.class);
intent.putExtra(CrimeFragment.EXTRA_CRIME_ID, crime.getId());
startActivity(intent);
} else {
getSupportFragmentManager().
beginTransaction().
replace(R.id.detailFragmentContainer, CrimeFragment.newInstance(crime.getId())).
commit();
}
}
}
调用全部回调方法(CrimeListFragment.java)
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Crime crime = (Crime) getListAdapter().getItem(position);
mCallBacks.onCrimeSelected(crime);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_new_crime:
addNewCrime();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void addNewCrime() {
Crime crime = new Crime();
CrimeLab.getInstance(getActivity()).addCrime(crime);
((CrimeAdapter) getListAdapter()).notifyDataSetChanged();
mCallBacks.onCrimeSelected(crime);
}
CrimeFragment.Callbacks回调接口的实现
CrimeFragment类中定义的接口如下:
public class CrimeFragment extends Fragment {
private MyCallBacks mCallBacks;
...
public interface MyCallBacks {
void onCrimeUpdate();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallBacks = (MyCallBacks) activity;
}
@Override
public void onDetach() {
super.onDetach();
mCallBacks = null;
}
新增updateUI()方法 (CrimeListFragment.java)
public void onUpdateUI() {
((CrimeAdapter) getListAdapter()).notifyDataSetChanged();
}
刷新显示crime列表(CrimeListActivity.java)
@Override
public void onCrimeUpdate() {
((CrimeListFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainer)).onUpdateUI();
}
调用onCrimeUpdated(Crime)方法(CrimeFragment.java)
mTitleField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
mCrime.setTitle(charSequence.toString());
mCallBacks.onCrimeUpdate();
getActivity().setTitle(mCrime.getTitle());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
mSolvedCheckBox = (CheckBox) view.findViewById(R.id.crime_solved);
mSolvedCheckBox.setChecked(mCrime.isSolved());
mSolvedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
mCrime.setSolved(b);
mCallBacks.onCrimeUpdate();
}
});
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK)
return;
if (requestCode == REQUEST_DATE) {
mCrime.setDate((Date) data.getSerializableExtra(DatePickerFragment.EXTRA_DATE));
Log.d(TAG, mCrime.getDate().toString());
mDateButton.setText(mCrime.getDate().toString());
mCallBacks.onCrimeUpdate();
}
if (requestCode == REQUEST_PHOTO) {
String filename = data.getStringExtra(CrimeCameraFragment.EXTRA_PHOTO_FILENAME);
if (filename != null) {
Photo photo = new Photo(filename);
mCrime.setPhoto(photo);
mCallBacks.onCrimeUpdate();
showPhoto();
}
}
if (requestCode == REQUEST_CONTACT) {
Uri contactUri = data.getData();
String[] queryFields = new String[]{ContactsContract.Contacts.DISPLAY_NAME};
Cursor cursor = getActivity().getContentResolver().query(contactUri, queryFields, null, null, null);
if (cursor.getCount() == 0) {
cursor.close();
return;
}
cursor.moveToFirst();
String suspect = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
mCrime.setSuspect(suspect);
mCallBacks.onCrimeUpdate();
mSuspectButton.setText(suspect);
cursor.close();
}
}
CrimeListActivity现在有了CrimeFragment.Callbacks接口的一个良好实现。然而,如 果在手机设备上运行CriminalIntent应用,它将会崩溃。记住,任何托管CrimeFragment的activity 都必须实现CrimeFragment.Callbacks接口。因此,我们还需要在CrimePagerActivity类中 实现CrimeFragment.Callbacks接口。
对于CrimePagerActivity类,onCrimeUpdated(Crime)方法什么都不用做,因此直接实现 一个空方法即可
CrimeFragment.Callbacks接口的空实现(CrimePagerActivity.java)
public class CrimePagerActivity extends AppCompatActivity implements CrimeFragment.MyCallBacks{
@Override
public void onCrimeUpdate() {
}
...
}