开发环境:win7,Android Studio 1.2,

1、Model

Crime,数据模型,每个Crime有一个UUID作为唯一标识。

  1. package tina.criminalintent;
  2.  
  3. import java.util.Date;
  4. import java.util.UUID;
  5.  
  6. /**
  7. * Created by CW3479 on 2015/7/13.
  8. */
  9. public class Crime {
  10. private UUID mId;
  11. private String mTitle;
  12. private Date mDate;
  13. private boolean mSolved;
  14.  
  15. public Crime(){
  16. //Genetate unique identifier
  17. mId=UUID.randomUUID();
  18.  
  19. }
  20.  
  21. public UUID getId() {
  22. return mId;
  23. }
  24.  
  25. public String getTitle() {
  26. return mTitle;
  27. }
  28.  
  29. public void setTitle(String title) {
  30. mTitle = title;
  31. }
  32.  
  33. public Date getDate() {
  34. if(mDate==null)
  35. mDate=new Date();
  36. return mDate;
  37. }
  38.  
  39. public void setDate(Date date) {
  40. mDate = date;
  41. }
  42.  
  43. public boolean isSolved() {
  44. return mSolved;
  45. }
  46.  
  47. public void setSolved(boolean solved) {
  48. mSolved = solved;
  49. }
  50.  
  51. @Override
  52. public String toString() {
  53. return mTitle;
  54. }
  55. }

CrimeLab,数据库,用了单例模式,保证了应用运行过程中使用同一个数据库。目前还是简单应用,CrimeLab里面的数据(Crime)是初始化时设定的,只能查询和更改,以后会进行改造,对CrimeLab进行增删操作。

  1. package tina.criminalintent;
  2.  
  3. import android.content.Context;
  4.  
  5. import java.util.ArrayList;
  6. import java.util.UUID;
  7.  
  8. /**
  9. * Created by CW3479 on 2015/7/13.
  10. */
  11. public class CrimeLab {
  12. private ArrayList<Crime> mCrimes;
  13.  
  14. private static CrimeLab sCrimeLab;
  15. private Context mAppContext;
  16.  
  17. public static CrimeLab getInstance(Context context) {
  18. if(sCrimeLab==null) {
  19. sCrimeLab = new CrimeLab(context.getApplicationContext());
  20. }
  21. return sCrimeLab;
  22. }
  23.  
  24. private CrimeLab(Context appContext) {
  25. mAppContext=appContext;
  26. mCrimes=new ArrayList<Crime>();
  27.  
  28. for(int i=0;i<10;i++){
  29. Crime crime=new Crime();
  30. crime.setTitle("Crime #"+i);
  31. crime.setSolved(i%2==0);
  32. mCrimes.add(crime);
  33. }
  34. }
  35.  
  36. public ArrayList<Crime> getCrimes() {
  37. return mCrimes;
  38. }
  39.  
  40. public Crime getCrime(UUID id){
  41. for(Crime crime:mCrimes){
  42. if(crime.getId().equals(id)){
  43. return crime;
  44. }
  45. }
  46. return null;
  47. }
  48. }

2、Controller & View

以往都是直接用Activity进行应用的设计,从这个demo开始,使用Fragment来完成应用的设计,增加应用程序的灵活性。关于Fragment,可以参考这篇文章Android Fragment 真正的完全解析(上)。需要注意的是,有关Fragment的类,有静态支持库版本和标准包版本(不知道这么说合不合适),前者是为了兼容Android3.0以下版本,需要导入Android Support库(android.support.v4.*),后者就在android.app.*包里,两者的使用方法大致相同,写程序的时候考虑是否向下兼容来做选择即可。

这个Demo按照书上,使用静态支持库。

首先,SingleFragmentActivity,可看做一个放置有FragmentContainer的Activity抽象类。其中的抽象方法createFragment可以用来实现不同的Fragment。书上的例程继承的是FragmentActivity类,但是我在用模拟器运行的时候发现没有像书中一样出现ActionBar。查了一番,原来ActionBarActivity是FragmentActivity的子类,所以我直接就继承了ActionBarActivity,这个也是Android Studio的Blank Activity模板中默认使用的Activity类。

  1. package tina.criminalintent;
  2.  
  3. import android.os.Bundle;
  4. import android.support.v4.app.Fragment;
  5. import android.support.v4.app.FragmentManager;
  6. import android.support.v7.app.ActionBarActivity;
  7.  
  8. /**
  9. * Created by CW3479 on 2015/7/13.
  10. */
  11. public abstract class SingleFragmentActivity extends ActionBarActivity {
  12. protected abstract Fragment createFragment();
  13.  
  14. @Override
  15. public void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.activity_fragment);
  18.  
  19. FragmentManager fm=getSupportFragmentManager();
  20. Fragment fragment=fm.findFragmentById(R.id.fragmentContainer);
  21. if(fragment==null){
  22. fragment=createFragment();
  23. fm.beginTransaction()
  24. .add(R.id.fragmentContainer,fragment)
  25. .commit();
  26. }
  27. }
  28. }

其对应的布局文件activity_fragment.xml如下,只有一个id为fragmentContainer的FrameLayout,FrameLayout里面不放置任何子控件。

  1. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:paddingLeft="@dimen/activity_horizontal_margin"
  6. android:paddingRight="@dimen/activity_horizontal_margin"
  7. android:paddingTop="@dimen/activity_vertical_margin"
  8. android:paddingBottom="@dimen/activity_vertical_margin"
  9. tools:context="tina.criminalintent.CrimeActivity"
  10. android:id="@+id/fragmentContainer">
  11.  
  12. </FrameLayout>

上面有了基本的模板了,接下来就是第一个页面啦。应用一打开,就是一个列表页面,显示CrimeLab中的Crime。

CrimeListActivity继承上面的SingleFragmentActivity,创建一个CrimeListFragment,放置到fragmentContainer中。

  1. package tina.criminalintent;
  2.  
  3. import android.support.v4.app.Fragment;
  4.  
  5. /**
  6. * Created by CW3479 on 2015/7/13.
  7. */
  8. public class CrimeListActivity extends SingleFragmentActivity {
  9.  
  10. @Override
  11. protected Fragment createFragment() {
  12. return new CrimeListFragment();
  13. }
  14. }

要显示列表,CrimeListFragment继承了ListFragment,从CrimeLab单例中获取Crime数据,再根据mCrimes构建ArrayAdapter,给列表中的每一行赋予数据,然后对item点击事件做响应,跳转到相应的Detail页面。

  1. package tina.criminalintent;
  2.  
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.support.v4.app.ListFragment;
  6. import android.view.LayoutInflater;
  7. import android.view.View;
  8. import android.view.ViewGroup;
  9. import android.widget.ArrayAdapter;
  10. import android.widget.CheckBox;
  11. import android.widget.ListView;
  12. import android.widget.TextView;
  13.  
  14. import java.util.ArrayList;
  15.  
  16. public class CrimeListFragment extends ListFragment {
  17.  
  18. private ArrayList<Crime> mCrimes;
  19.  
  20. private CrimeAdapter mAdapter;
  21.  
  22. @Override
  23. public void onCreate(Bundle savedInstanceState) {
  24. super.onCreate(savedInstanceState);
  25. getActivity().setTitle(R.string.crimes_title);
  26.  
  27. mCrimes=CrimeLab.getInstance(getActivity()).getCrimes();
  28. mAdapter=new CrimeAdapter(mCrimes);
  29. setListAdapter(mAdapter);
  30. }
  31.  
  32. @Override
  33. public void onListItemClick(ListView l, View v, int position, long id) {
  34. super.onListItemClick(l, v, position, id);
  35. Crime crime=((CrimeAdapter)getListAdapter()).getItem(position);
  36.  
  37. // Intent intent=new Intent(getActivity(),CrimeActivity.class);
  38. Intent intent=new Intent(getActivity(),CrimePagerActivity.class);
  39. intent.putExtra(CrimeFragment.EXTRA_CRIME_ID, crime.getId());
  40. startActivity(intent);
  41. }
  42.  
  43. private class CrimeAdapter extends ArrayAdapter<Crime>{
  44. public CrimeAdapter(ArrayList<Crime> crimes) {
  45. super(getActivity(), 0, crimes);
  46. }
  47.  
  48. @Override
  49. public View getView(int position, View convertView, ViewGroup parent) {
  50.  
  51. if(convertView==null){
  52. convertView=getActivity().getLayoutInflater()
  53. .inflate(R.layout.list_item_crime,null);
  54. }
  55.  
  56. Crime c=getItem(position);
  57. TextView titleTextView=(TextView)convertView.findViewById(R.id.crime_list_item_title);
  58. titleTextView.setText(c.getTitle());
  59.  
  60. TextView dateTextView=(TextView)convertView.findViewById(R.id.crime_list_item_date);
  61. dateTextView.setText(c.getDate().toString());
  62.  
  63. CheckBox solvedCheckBox=(CheckBox)convertView.findViewById(R.id.crime_list_item_solvedCheckBox);
  64. solvedCheckBox.setChecked(c.isSolved());
  65.  
  66. return convertView;
  67. }
  68. }
  69.  
  70. @Override
  71. public void onResume() {
  72. super.onResume();
  73. ((CrimeAdapter)getListAdapter()).notifyDataSetChanged();
  74. }
  75. }

上面的列表对应的item布局文件list_item_crime.xml如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5.  
  6. <TextView
  7. android:layout_width="wrap_content"
  8. android:layout_height="wrap_content"
  9. android:id="@+id/crime_list_item_title"
  10. android:layout_alignParentTop="true"
  11. android:layout_alignParentStart="true"/>
  12.  
  13. <TextView
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. android:text="New Text"
  17. android:id="@+id/crime_list_item_date"
  18. android:layout_below="@+id/crime_list_item_title"
  19. android:layout_alignParentStart="true"/>
  20.  
  21. <CheckBox
  22. android:layout_width="wrap_content"
  23. android:layout_height="wrap_content"
  24. android:text="@string/crime_solved_label"
  25. android:id="@+id/crime_list_item_solvedCheckBox"
  26. android:layout_alignParentTop="true"
  27. android:layout_alignParentEnd="true"
  28. android:focusable="false"
  29. />
  30. </RelativeLayout>

Detail页面CrimePagerActivity,用ViewPager来实现。点击列表项进入相应的Detail页面,页面标题对应相应的Crime Title,向左(向右)进入前一项(后一项)的Detail页面,也就是通过FragmentManager加载相应的CrimeFragment到ViewPager中。

  1. import android.os.Bundle;
  2. import android.support.v4.app.Fragment;
  3. import android.support.v4.app.FragmentManager;
  4. import android.support.v4.app.FragmentStatePagerAdapter;
  5. import android.support.v4.view.ViewPager;
  6. import android.support.v7.app.ActionBarActivity;
  7.  
  8. import java.util.ArrayList;
  9. import java.util.UUID;
  10.  
  11. public class CrimePagerActivity extends ActionBarActivity {
  12.  
  13. private ViewPager mViewPager;
  14. private ArrayList<Crime> mCrimes;
  15.  
  16. @Override
  17. protected void onCreate(Bundle savedInstanceState) {
  18. super.onCreate(savedInstanceState);
  19.  
  20. mViewPager=new ViewPager(this);
  21. mViewPager.setId(R.id.viewPager);
  22. setContentView(mViewPager);
  23.  
  24. mCrimes=CrimeLab.getInstance(this).getCrimes();
  25.  
  26. FragmentManager fm=getSupportFragmentManager();
  27. mViewPager.setAdapter(new FragmentStatePagerAdapter(fm) {
  28. @Override
  29. public Fragment getItem(int position) {
  30. Crime crime=mCrimes.get(position);
  31. return CrimeFragment.newInstance(crime.getId());
  32. }
  33.  
  34. @Override
  35. public int getCount() {
  36. return mCrimes.size();
  37. }
  38. });
  39.  
  40. // 匹配UUID,跳转到当前选中的crime项对应的ViewPager Item
  41. final UUID crimeId=(UUID)getIntent().getSerializableExtra(CrimeFragment.EXTRA_CRIME_ID);
  42. for(int i=0;i<mCrimes.size();i++){
  43. if(mCrimes.get(i).getId().equals(crimeId)){
  44. mViewPager.setCurrentItem(i);
  45. setTitle(mCrimes.get(i).getTitle());
  46. break;
  47. }
  48. }
  49.  
  50. // 将当前的ViewPage的Title改为对应的Crime Title
  51. mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
  52. @Override
  53. public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
  54.  
  55. }
  56.  
  57. @Override
  58. public void onPageSelected(int position) {
  59. Crime crime=mCrimes.get(position);
  60. if(crime.getTitle()!=null){
  61. setTitle(crime.getTitle());
  62. }
  63. }
  64.  
  65. @Override
  66. public void onPageScrollStateChanged(int state) {
  67.  
  68. }
  69. });
  70. }
  71. }

CrimeFragment继承Fragment,点击显示时间的DateButton,弹出DatePickerFragment对话框,用于选择时间,在onActivityResult方法中接收选中的事件信息,并作出响应。此外,为了得到对应的Crime数据,CrimeFragment的类方法newInstance(UUID crimeId)中,在fragment中设置Crime Id作为arguments。以便使用newInstance产生实例,能在onCreate中取回数据,对frament做初始化。

  1. package tina.criminalintent;
  2.  
  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.os.Bundle;
  6. import android.support.v4.app.Fragment;
  7. import android.support.v4.app.FragmentManager;
  8. import android.text.Editable;
  9. import android.text.TextWatcher;
  10. import android.view.LayoutInflater;
  11. import android.view.View;
  12. import android.view.ViewGroup;
  13. import android.widget.Button;
  14. import android.widget.CheckBox;
  15. import android.widget.CompoundButton;
  16. import android.widget.EditText;
  17.  
  18. import java.util.Date;
  19. import java.util.UUID;
  20.  
  21. public class CrimeFragment extends Fragment {
  22.  
  23. public static final String EXTRA_CRIME_ID="tina.criminalintent.crime_id";
  24. private static final String DIALOG_DATE="date";
  25. private static final int REQUEST_DATE=0;
  26.  
  27. private Crime mCrime;
  28. private EditText mTitleField;
  29. private Button mDateButton;
  30. private CheckBox mSolvedCheckBox;
  31.  
  32. public CrimeFragment() {
  33. // Required empty public constructor
  34. }
  35.  
  36. public static CrimeFragment newInstance(UUID crimeId){
  37. Bundle args=new Bundle();
  38. args.putSerializable(EXTRA_CRIME_ID,crimeId);
  39.  
  40. CrimeFragment fragment=new CrimeFragment();
  41. fragment.setArguments(args);
  42. return fragment;
  43. }
  44. @Override
  45. public void onCreate(Bundle savedInstanceState) {
  46. super.onCreate(savedInstanceState);
  47.  
  48. UUID id=(UUID) getArguments().getSerializable(EXTRA_CRIME_ID);
  49. mCrime=CrimeLab.getInstance(getActivity()).getCrime(id);
  50.  
  51. }
  52.  
  53. public void updateDate(){
  54. mDateButton.setText(mCrime.getDate().toString());
  55. }
  56.  
  57. @Override
  58. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  59. Bundle savedInstanceState) {
  60. // Inflate the layout for this fragment
  61. View v=inflater.inflate(R.layout.fragment_crime, container, false);
  62.  
  63. mTitleField=(EditText)v.findViewById(R.id.crime_title);
  64. mTitleField.setText(mCrime.getTitle());
  65. mTitleField.addTextChangedListener(new TextWatcher() {
  66. @Override
  67. public void beforeTextChanged(CharSequence s, int start, int count, int after) {
  68. mCrime.setTitle(s.toString());
  69. }
  70.  
  71. @Override
  72. public void onTextChanged(CharSequence s, int start, int before, int count) {
  73.  
  74. }
  75.  
  76. @Override
  77. public void afterTextChanged(Editable s) {
  78.  
  79. }
  80. });
  81.  
  82. mDateButton=(Button)v.findViewById(R.id.crime_date);
  83. updateDate();
  84. mDateButton.setOnClickListener(new View.OnClickListener() {
  85. @Override
  86. public void onClick(View v) {
  87. FragmentManager fm=getActivity().getSupportFragmentManager();
  88. DatePickerFragment dialog=DatePickerFragment.newInstance(mCrime.getDate());
  89. dialog.setTargetFragment(CrimeFragment.this,REQUEST_DATE);
  90. dialog.show(fm,DIALOG_DATE);
  91. }
  92. });
  93.  
  94. mSolvedCheckBox=(CheckBox)v.findViewById(R.id.crime_solved);
  95. mSolvedCheckBox.setChecked(mCrime.isSolved());
  96. mSolvedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
  97. @Override
  98. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  99. mCrime.setSolved(isChecked);
  100. }
  101. });
  102. return v;
  103. }
  104.  
  105. @Override
  106. public void onActivityResult(int requestCode, int resultCode, Intent data) {
  107. if(resultCode!= Activity.RESULT_OK)
  108. return;
  109.  
  110. if(requestCode==REQUEST_DATE){
  111. Date date=(Date)data.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
  112. mCrime.setDate(date);
  113. updateDate();
  114. }
  115. }
  116.  
  117. }

对应的布局文件fragment_crime.xml如下:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. tools:context="tina.criminalintent.CrimeFragment">
  6.  
  7. <EditText
  8. android:layout_width="match_parent"
  9. android:layout_height="wrap_content"
  10. android:id="@+id/crime_title"
  11. android:hint="@string/crime_title_hint"
  12. android:layout_below="@+id/textView"
  13. android:layout_alignParentStart="true"/>
  14.  
  15. <TextView
  16. android:layout_width="match_parent"
  17. android:layout_height="wrap_content"
  18. android:textAppearance="?android:attr/textAppearanceLarge"
  19. android:text="@string/crime_title_label"
  20. android:id="@+id/textView"
  21. android:layout_alignParentTop="true"
  22. android:layout_alignParentStart="true"
  23. style="?android:listSeparatorTextViewStyle"/>
  24.  
  25. <TextView
  26. android:layout_width="match_parent"
  27. android:layout_height="wrap_content"
  28. android:textAppearance="?android:attr/textAppearanceLarge"
  29. android:text="@string/crime_details_label"
  30. android:id="@+id/textView2"
  31. android:layout_below="@+id/crime_title"
  32. android:layout_alignParentStart="true"
  33. style="?android:listSeparatorTextViewStyle"/>
  34.  
  35. <Button
  36. android:layout_width="match_parent"
  37. android:layout_height="wrap_content"
  38. android:id="@+id/crime_date"
  39. android:layout_below="@+id/textView2"
  40. android:layout_centerHorizontal="true"/>
  41.  
  42. <CheckBox
  43. android:layout_width="wrap_content"
  44. android:layout_height="wrap_content"
  45. android:text="@string/crime_solved_label"
  46. android:id="@+id/crime_solved"
  47. android:layout_below="@+id/crime_date"
  48. android:layout_alignParentStart="true"/>
  49. </RelativeLayout>

在手机横着的时候,需要对布局进行调整。在res文件夹中新建一个Android Resource Directory,name设置为layout-land,resource type选择layout,source set默认为main。注意,项目显示结构选择Project来能看到layout-land文件夹,选择Android的话,会把所有的layout文件都整合显示在layout目录下面。把fragment_crime.xml复制到layout-land文件夹中,对布局进行调整,调整后的布局内容如下:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. tools:context="tina.criminalintent.CrimeFragment">
  6.  
  7. <EditText
  8. android:layout_width="match_parent"
  9. android:layout_height="wrap_content"
  10. android:id="@+id/crime_title"
  11. android:hint="@string/crime_title_hint"
  12. android:layout_below="@+id/textView"
  13. android:layout_alignParentStart="true"/>
  14.  
  15. <TextView
  16. android:layout_width="match_parent"
  17. android:layout_height="wrap_content"
  18. android:textAppearance="?android:attr/textAppearanceLarge"
  19. android:text="@string/crime_title_label"
  20. android:id="@+id/textView"
  21. android:layout_alignParentTop="true"
  22. android:layout_alignParentStart="true"
  23. style="?android:listSeparatorTextViewStyle"/>
  24.  
  25. <TextView
  26. android:layout_width="match_parent"
  27. android:layout_height="wrap_content"
  28. android:textAppearance="?android:attr/textAppearanceLarge"
  29. android:text="@string/crime_details_label"
  30. android:id="@+id/textView2"
  31. android:layout_below="@+id/crime_title"
  32. android:layout_alignParentStart="true"
  33. style="?android:listSeparatorTextViewStyle"/>
  34.  
  35. <LinearLayout
  36. android:orientation="horizontal"
  37. android:layout_width="match_parent"
  38. android:layout_height="match_parent"
  39. android:layout_below="@+id/textView2"
  40. android:layout_alignParentStart="true"
  41. android:layout_marginLeft="16dp"
  42. android:layout_marginRight="16dp">
  43.  
  44. <Button
  45. android:layout_width="0dp"
  46. android:layout_height="wrap_content"
  47. android:id="@+id/crime_date"
  48. android:layout_weight="1"/>
  49.  
  50. <CheckBox
  51. android:layout_width="0dp"
  52. android:layout_height="wrap_content"
  53. android:text="@string/crime_solved_label"
  54. android:id="@+id/crime_solved"
  55. android:layout_weight="1"
  56. android:layout_marginBottom="78dp"/>
  57. </LinearLayout>
  58. </RelativeLayout>

再回到页面实现,上面提到显示DatePickerFragment对话框,这个对话框继承的是DialogFragment类,使用date数据作为arguments,用一个DatePicker控件来选择日期。

在上面,CrimeFragment用DatePickerFragment的setTargetFragment()方法,指定了DatePickerFragment返回时传递数据给自己。

DatePickerFragment实现了DatePickerDialog.OnDateSetListener这个接口,使得类可以在onDateSet()方法中监听日期的选择,并将用getTargetFragment().onActivityResult(),把时间数据传递给CrimeFragment实例。

  1. import android.app.Activity;
  2. import android.app.AlertDialog;
  3. import android.app.DatePickerDialog;
  4. import android.app.Dialog;
  5. import android.content.DialogInterface;
  6. import android.content.Intent;
  7. import android.os.Bundle;
  8. import android.support.v4.app.DialogFragment;
  9. import android.util.Log;
  10. import android.view.View;
  11. import android.widget.DatePicker;
  12.  
  13. import java.util.Calendar;
  14. import java.util.Date;
  15. import java.util.GregorianCalendar;
  16.  
  17. public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener{
  18. public static final String EXTRA_DATE="tina.criminalintent.date";
  19.  
  20. private Date mDate;
  21.  
  22. public static DatePickerFragment newInstance(Date date){
  23. Bundle args=new Bundle();
  24. args.putSerializable(EXTRA_DATE, date);
  25.  
  26. DatePickerFragment fragment=new DatePickerFragment();
  27. fragment.setArguments(args);
  28. return fragment;
  29. }
  30.  
  31. @Override
  32. public Dialog onCreateDialog(Bundle savedInstanceState) {
  33. mDate=(Date)getArguments().getSerializable(EXTRA_DATE);
  34. Calendar calendar=Calendar.getInstance();
  35. calendar.setTime(mDate);
  36. int year=calendar.get(Calendar.YEAR);
  37. final int month=calendar.get(Calendar.MONTH);
  38. final int day=calendar.get(Calendar.DAY_OF_MONTH);
  39.  
  40. return new DatePickerDialog(getActivity(),this,year,month,day);
  41. }
  42.  
  43. @Override
  44. public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
  45. mDate = new GregorianCalendar(year, monthOfYear, dayOfMonth).getTime();
  46. if(getTargetFragment()==null)
  47. return;
  48.  
  49. Intent intent=new Intent();
  50. intent.putExtra(EXTRA_DATE,mDate);
  51. getTargetFragment().onActivityResult(getTargetRequestCode(),Activity.RESULT_OK,intent);
  52. }
  53.  
  54. }

至此,Demo的布局文件和Activity设计完毕。

下面是上面的文件中用到的Value文件:

strings.xml

  1. <resources>
  2. <string name="app_name">CriminalIntent</string>
  3.  
  4. <!-- TODO: Remove or change this placeholder text -->
  5. <string name="hello_blank_fragment">Hello blank fragment</string>
  6. <string name="title_activity_crime">CrimeActivity</string>
  7.  
  8. <string name="crime_title_hint">Enter a title for the crime.</string>
  9. <string name="crime_title_label">title</string>
  10. <string name="crime_details_label">details</string>
  11. <string name="crime_solved_label">Solved?</string>
  12. <string name="crimes_title">Crimes</string>
  13. <string name="date_picker_title">Date of crime:</string>
  14. </resources>

还有,为ViewPager创建的ids.xml。由于这里的ViewPager是用代码产生的(mViewPager = new ViewPager(this)),而ViewPager是一个Fragment的Container,必须提供一个resource id才能被FragmentManager使用。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <item name="viewPager" type="id"/>
  4. </resources>

至此,Demo结束。

3、Android Studio中的Fragment模板

AndroidStudio中的Fragment(Blank)模板使用的是android.app.Fragment。

Fragment(List)模板是用Frament和布局文件中的ListView相结合,没有直接使用ListFragment,模板里面有很多东西,初看有点复杂,有两个布局文件,分别用于大小屏幕(也就是手机和平板吧),大屏的那个布局文件可以放GridView。

对于上面的Demo,用模板写的CrimeListFragment大致如下:

  1. package tina.criminalintent;
  2.  
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.app.Fragment;
  6. import android.view.LayoutInflater;
  7. import android.view.View;
  8. import android.view.ViewGroup;
  9. import android.widget.AbsListView;
  10. import android.widget.AdapterView;
  11. import android.widget.ArrayAdapter;
  12. import android.widget.CheckBox;
  13. import android.widget.TextView;
  14.  
  15. import java.util.ArrayList;
  16.  
  17. //
  18. ///**
  19. // * A fragment representing a list of Items.
  20. // * <p/>
  21. // * Large screen devices (such as tablets) are supported by replacing the ListView
  22. // * with a GridView.
  23. // * <p/>
  24. // * Activities containing this fragment MUST implement the {@link OnFragmentInteractionListener}
  25. // * interface.
  26. // */
  27. public class CrimeListFragment2 extends Fragment implements AbsListView.OnItemClickListener {
  28.  
  29. private ArrayList<Crime> mCrimes;
  30.  
  31. // private OnFragmentInteractionListener mListener;
  32.  
  33. /**
  34. * The fragment's ListView/GridView.
  35. */
  36. private AbsListView mListView;
  37.  
  38. /**
  39. * The Adapter which will be used to populate the ListView/GridView with
  40. * Views.
  41. */
  42. private CrimeAdapter mAdapter;
  43.  
  44. /**
  45. * Mandatory empty constructor for the fragment manager to instantiate the
  46. * fragment (e.g. upon screen orientation changes).
  47. */
  48. public CrimeListFragment2() {
  49. }
  50.  
  51. @Override
  52. public void onCreate(Bundle savedInstanceState) {
  53. super.onCreate(savedInstanceState);
  54. getActivity().setTitle(R.string.crimes_title);
  55.  
  56. mCrimes=CrimeLab.getInstance(getActivity()).getCrimes();
  57. mAdapter=new CrimeAdapter(mCrimes);
  58. }
  59.  
  60. @Override
  61. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  62. Bundle savedInstanceState) {
  63. View view = inflater.inflate(R.layout.fragment_crimelist, container, false);
  64.  
  65. // Set the adapter
  66. mListView = (AbsListView) view.findViewById(android.R.id.list);
  67. ((AdapterView) mListView).setAdapter(mAdapter);
  68.  
  69. // Set OnItemClickListener so we can be notified on item clicks
  70. mListView.setOnItemClickListener(this);
  71.  
  72. return view;
  73. }
  74.  
  75. @Override
  76. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  77. Crime crime=((CrimeAdapter)(parent.getAdapter())).getItem(position);
  78.  
  79. // Intent intent=new Intent(getActivity(),CrimeActivity.class);
  80. Intent intent=new Intent(getActivity(),CrimePagerActivity.class);
  81. intent.putExtra(CrimeFragment.EXTRA_CRIME_ID, crime.getId());
  82. startActivity(intent);
  83. }
  84.  
  85. private class CrimeAdapter extends ArrayAdapter<Crime>{
  86. public CrimeAdapter(ArrayList<Crime> crimes) {
  87. super(getActivity(), 0, crimes);
  88. }
  89.  
  90. @Override
  91. public View getView(int position, View convertView, ViewGroup parent) {
  92.  
  93. if(convertView==null){
  94. convertView=getActivity().getLayoutInflater()
  95. .inflate(R.layout.list_item_crime,null);
  96. }
  97.  
  98. Crime c=getItem(position);
  99. TextView titleTextView=(TextView)convertView.findViewById(R.id.crime_list_item_title);
  100. titleTextView.setText(c.getTitle());
  101.  
  102. TextView dateTextView=(TextView)convertView.findViewById(R.id.crime_list_item_date);
  103. dateTextView.setText(c.getDate().toString());
  104.  
  105. CheckBox solvedCheckBox=(CheckBox)convertView.findViewById(R.id.crime_list_item_solvedCheckBox);
  106. solvedCheckBox.setChecked(c.isSolved());
  107.  
  108. return convertView;
  109. }
  110. }
  111.  
  112. @Override
  113. public void onResume() {
  114. super.onResume();
  115. ((CrimeAdapter)mListView.getAdapter()).notifyDataSetChanged();
  116. }
  117. }

刚刚接触Fragment,除了模板不兼容Android3.0以下版本以外,我觉得里面的结构也有点复杂,不过Fragment的使用方法很多,具体不知道这种模板是不是用得比较普遍。以后再看吧。

4、运行效果

BNR Android Demo学习笔记(一)——CrimeIntent的更多相关文章

  1. Android动画学习笔记-Android Animation

    Android动画学习笔记-Android Animation   3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中 ...

  2. Android自动化学习笔记:编写MonkeyRunner脚本的几种方式

    ---------------------------------------------------------------------------------------------------- ...

  3. Android自动化学习笔记之MonkeyRunner:官方介绍和简单实例

    ---------------------------------------------------------------------------------------------------- ...

  4. android开发学习笔记000

    使用书籍:<疯狂android讲义>——李刚著,2011年7月出版 虽然现在已2014,可我挑来跳去,还是以这本书开始我的android之旅吧. “疯狂源自梦想,技术成就辉煌.” 让我这个 ...

  5. Android 数字签名学习笔记

    Android 数字签名学习笔记 在Android系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系,如果一个permission的pro ...

  6. Android:日常学习笔记(9)———探究持久化技术

    Android:日常学习笔记(9)———探究持久化技术 引入持久化技术 什么是持久化技术 持久化技术就是指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失 ...

  7. Android:日常学习笔记(9)———探究广播机制

    Android:日常学习笔记(9)———探究广播机制 引入广播机制 Andorid广播机制 广播是任何应用均可接收的消息.系统将针对系统事件(例如:系统启动或设备开始充电时)传递各种广播.通过将 In ...

  8. Android:日常学习笔记(8)———开发微信聊天界面

    Android:日常学习笔记(8)———开发微信聊天界面 只做Nine-Patch图片 Nine-Patch是一种被特殊处理过的PNG图片,能够指定哪些区域可以被拉升,哪些区域不可以.

  9. Android:日常学习笔记(8)———探究UI开发(5)

    Android:日常学习笔记(8)———探究UI开发(5) ListView控件的使用 ListView概述 A view that shows items in a vertically scrol ...

随机推荐

  1. Beta版本——第六次冲刺博客

    我说的都队 031402304 陈燊 031402342 许玲玲 031402337 胡心颖 03140241 王婷婷 031402203 陈齐民 031402209 黄伟炜 031402233 郑扬 ...

  2. infobright 导入 导出

    SET SQL_LOG_BIN = 0;select * into outfile 'mydata.cvs' fields terminated by ',' from table1;load dat ...

  3. java编程思想-java中的并发(二)

    二.共享受限资源 有了并发就可以同时做多件事情了.但是,两个或多个线程彼此互相干涉的问题也就出现了.如果不防范这种冲突,就可能发生两个线程同时试图访问同一个银行账户,或向同一个打印机打印,改变同一个值 ...

  4. 嵌入式Linux系统开发环境搭建

    Linux kernel Complier: http://supportopensource.iteye.com/blog/680483 sudo make mrproper         净化解 ...

  5. 【转】CSS3的REM设置字体大小

    rem 长度单位   在Web中使用什么单位来定义页面的字体大小,至今天为止都还在激烈的争论着,有人说PX做为单位好,有人说EM优点多,还有人在说百分比方便,以至于出现了CSS Font-Size: ...

  6. magelinux notes

    [root@centos01 01]# cd ~jack #进入指定用户的家目录[root@centos01 jack]# cd - #切回上一次目录[root@centos01 home]# cd ...

  7. Flask-WTF form doesn't have attribute 'validate_on_submit'问题

    今天在学习WTF表单的时候遇到了这个问题,在stackoverflow上搜索查到了解决方案 from flask.ext.wtf import Form from wtforms import Tex ...

  8. Java 命令行运行参数大全

    Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOME"bin"java –option 来启动,-option为虚拟 ...

  9. Ubuntu 设置程序开机启动(以指定用户身份)

    一.方法 在/etc/rc.local写程序的启动命令(系统执行内核过程中会启动init进程,该进程把当前runlevel所对应的的所有service 都启动后,才会执行rc.local里的命令),程 ...

  10. 解惑好文:移动端H5页面高清多屏适配方案 (转)

    转自:http://mobile.51cto.com/web-484304.htm https://github.com/amfe/lib-flexible/blob/master/src/makeg ...