开发环境:win7,Android Studio 1.2,
1、Model
Crime,数据模型,每个Crime有一个UUID作为唯一标识。
package tina.criminalintent; import java.util.Date; import java.util.UUID; /** * Created by CW3479 on 2015/7/13. */ public class Crime { private UUID mId; private String mTitle; private Date mDate; private boolean mSolved; public Crime(){ //Genetate unique identifier mId=UUID.randomUUID(); } public UUID getId() { return mId; } public String getTitle() { return mTitle; } public void setTitle(String title) { mTitle = title; } public Date getDate() { if(mDate==null) mDate=new Date(); return mDate; } public void setDate(Date date) { mDate = date; } public boolean isSolved() { return mSolved; } public void setSolved(boolean solved) { mSolved = solved; } @Override public String toString() { return mTitle; } }
CrimeLab,数据库,用了单例模式,保证了应用运行过程中使用同一个数据库。目前还是简单应用,CrimeLab里面的数据(Crime)是初始化时设定的,只能查询和更改,以后会进行改造,对CrimeLab进行增删操作。
package tina.criminalintent; import android.content.Context; import java.util.ArrayList; import java.util.UUID; /** * Created by CW3479 on 2015/7/13. */ public class CrimeLab { private ArrayList<Crime> mCrimes; private static CrimeLab sCrimeLab; private Context mAppContext; public static CrimeLab getInstance(Context context) { if(sCrimeLab==null) { sCrimeLab = new CrimeLab(context.getApplicationContext()); } return sCrimeLab; } private CrimeLab(Context appContext) { mAppContext=appContext; mCrimes=new ArrayList<Crime>(); for(int i=0;i<10;i++){ Crime crime=new Crime(); crime.setTitle("Crime #"+i); crime.setSolved(i%2==0); mCrimes.add(crime); } } public ArrayList<Crime> getCrimes() { return mCrimes; } public Crime getCrime(UUID id){ for(Crime crime:mCrimes){ if(crime.getId().equals(id)){ return crime; } } return null; } }
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类。
package tina.criminalintent; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v7.app.ActionBarActivity; /** * Created by CW3479 on 2015/7/13. */ public abstract class SingleFragmentActivity extends ActionBarActivity { protected abstract Fragment createFragment(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fragment); FragmentManager fm=getSupportFragmentManager(); Fragment fragment=fm.findFragmentById(R.id.fragmentContainer); if(fragment==null){ fragment=createFragment(); fm.beginTransaction() .add(R.id.fragmentContainer,fragment) .commit(); } } }
其对应的布局文件activity_fragment.xml如下,只有一个id为fragmentContainer的FrameLayout,FrameLayout里面不放置任何子控件。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context="tina.criminalintent.CrimeActivity" android:id="@+id/fragmentContainer"> </FrameLayout>
上面有了基本的模板了,接下来就是第一个页面啦。应用一打开,就是一个列表页面,显示CrimeLab中的Crime。
CrimeListActivity继承上面的SingleFragmentActivity,创建一个CrimeListFragment,放置到fragmentContainer中。
package tina.criminalintent; import android.support.v4.app.Fragment; /** * Created by CW3479 on 2015/7/13. */ public class CrimeListActivity extends SingleFragmentActivity { @Override protected Fragment createFragment() { return new CrimeListFragment(); } }
要显示列表,CrimeListFragment继承了ListFragment,从CrimeLab单例中获取Crime数据,再根据mCrimes构建ArrayAdapter,给列表中的每一行赋予数据,然后对item点击事件做响应,跳转到相应的Detail页面。
package tina.criminalintent; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.ListView; import android.widget.TextView; import java.util.ArrayList; public class CrimeListFragment extends ListFragment { private ArrayList<Crime> mCrimes; private CrimeAdapter mAdapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getActivity().setTitle(R.string.crimes_title); mCrimes=CrimeLab.getInstance(getActivity()).getCrimes(); mAdapter=new CrimeAdapter(mCrimes); setListAdapter(mAdapter); } @Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Crime crime=((CrimeAdapter)getListAdapter()).getItem(position); // Intent intent=new Intent(getActivity(),CrimeActivity.class); Intent intent=new Intent(getActivity(),CrimePagerActivity.class); intent.putExtra(CrimeFragment.EXTRA_CRIME_ID, crime.getId()); startActivity(intent); } private class CrimeAdapter extends ArrayAdapter<Crime>{ public CrimeAdapter(ArrayList<Crime> crimes) { super(getActivity(), 0, crimes); } @Override public View getView(int position, View convertView, ViewGroup parent) { if(convertView==null){ convertView=getActivity().getLayoutInflater() .inflate(R.layout.list_item_crime,null); } Crime c=getItem(position); TextView titleTextView=(TextView)convertView.findViewById(R.id.crime_list_item_title); titleTextView.setText(c.getTitle()); TextView dateTextView=(TextView)convertView.findViewById(R.id.crime_list_item_date); dateTextView.setText(c.getDate().toString()); CheckBox solvedCheckBox=(CheckBox)convertView.findViewById(R.id.crime_list_item_solvedCheckBox); solvedCheckBox.setChecked(c.isSolved()); return convertView; } } @Override public void onResume() { super.onResume(); ((CrimeAdapter)getListAdapter()).notifyDataSetChanged(); } }
上面的列表对应的item布局文件list_item_crime.xml如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/crime_list_item_title" android:layout_alignParentTop="true" android:layout_alignParentStart="true"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Text" android:id="@+id/crime_list_item_date" android:layout_below="@+id/crime_list_item_title" android:layout_alignParentStart="true"/> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/crime_solved_label" android:id="@+id/crime_list_item_solvedCheckBox" android:layout_alignParentTop="true" android:layout_alignParentEnd="true" android:focusable="false" /> </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 9 import java.util.ArrayList; 10 import java.util.UUID; 11 12 public class CrimePagerActivity extends ActionBarActivity { 13 14 private ViewPager mViewPager; 15 private ArrayList<Crime> mCrimes; 16 17 @Override 18 protected void onCreate(Bundle savedInstanceState) { 19 super.onCreate(savedInstanceState); 20 21 mViewPager=new ViewPager(this); 22 mViewPager.setId(R.id.viewPager); 23 setContentView(mViewPager); 24 25 mCrimes=CrimeLab.getInstance(this).getCrimes(); 26 27 FragmentManager fm=getSupportFragmentManager(); 28 mViewPager.setAdapter(new FragmentStatePagerAdapter(fm) { 29 @Override 30 public Fragment getItem(int position) { 31 Crime crime=mCrimes.get(position); 32 return CrimeFragment.newInstance(crime.getId()); 33 } 34 35 @Override 36 public int getCount() { 37 return mCrimes.size(); 38 } 39 }); 40 41 // 匹配UUID,跳转到当前选中的crime项对应的ViewPager Item 42 final UUID crimeId=(UUID)getIntent().getSerializableExtra(CrimeFragment.EXTRA_CRIME_ID); 43 for(int i=0;i<mCrimes.size();i++){ 44 if(mCrimes.get(i).getId().equals(crimeId)){ 45 mViewPager.setCurrentItem(i); 46 setTitle(mCrimes.get(i).getTitle()); 47 break; 48 } 49 } 50 51 // 将当前的ViewPage的Title改为对应的Crime Title 52 mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 53 @Override 54 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 55 56 } 57 58 @Override 59 public void onPageSelected(int position) { 60 Crime crime=mCrimes.get(position); 61 if(crime.getTitle()!=null){ 62 setTitle(crime.getTitle()); 63 } 64 } 65 66 @Override 67 public void onPageScrollStateChanged(int state) { 68 69 } 70 }); 71 } 72 }
CrimeFragment继承Fragment,点击显示时间的DateButton,弹出DatePickerFragment对话框,用于选择时间,在onActivityResult方法中接收选中的事件信息,并作出响应。此外,为了得到对应的Crime数据,CrimeFragment的类方法newInstance(UUID crimeId)中,在fragment中设置Crime Id作为arguments。以便使用newInstance产生实例,能在onCreate中取回数据,对frament做初始化。
package tina.criminalintent; 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.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.EditText; import java.util.Date; import java.util.UUID; public class CrimeFragment extends Fragment { public static final String EXTRA_CRIME_ID="tina.criminalintent.crime_id"; private static final String DIALOG_DATE="date"; private static final int REQUEST_DATE=0; private Crime mCrime; private EditText mTitleField; private Button mDateButton; private CheckBox mSolvedCheckBox; public CrimeFragment() { // Required empty public constructor } 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 onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UUID id=(UUID) getArguments().getSerializable(EXTRA_CRIME_ID); mCrime=CrimeLab.getInstance(getActivity()).getCrime(id); } public void updateDate(){ mDateButton.setText(mCrime.getDate().toString()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View v=inflater.inflate(R.layout.fragment_crime, container, false); mTitleField=(EditText)v.findViewById(R.id.crime_title); mTitleField.setText(mCrime.getTitle()); mTitleField.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { mCrime.setTitle(s.toString()); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { } }); mDateButton=(Button)v.findViewById(R.id.crime_date); updateDate(); mDateButton.setOnClickListener(new View.OnClickListener() { @Override 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); } }); mSolvedCheckBox=(CheckBox)v.findViewById(R.id.crime_solved); mSolvedCheckBox.setChecked(mCrime.isSolved()); mSolvedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { mCrime.setSolved(isChecked); } }); return v; } @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); updateDate(); } } }
对应的布局文件fragment_crime.xml如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="tina.criminalintent.CrimeFragment"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/crime_title" android:hint="@string/crime_title_hint" android:layout_below="@+id/textView" android:layout_alignParentStart="true"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/crime_title_label" android:id="@+id/textView" android:layout_alignParentTop="true" android:layout_alignParentStart="true" style="?android:listSeparatorTextViewStyle"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/crime_details_label" android:id="@+id/textView2" android:layout_below="@+id/crime_title" android:layout_alignParentStart="true" style="?android:listSeparatorTextViewStyle"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/crime_date" android:layout_below="@+id/textView2" android:layout_centerHorizontal="true"/> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/crime_solved_label" android:id="@+id/crime_solved" android:layout_below="@+id/crime_date" android:layout_alignParentStart="true"/> </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文件夹中,对布局进行调整,调整后的布局内容如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="tina.criminalintent.CrimeFragment"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/crime_title" android:hint="@string/crime_title_hint" android:layout_below="@+id/textView" android:layout_alignParentStart="true"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/crime_title_label" android:id="@+id/textView" android:layout_alignParentTop="true" android:layout_alignParentStart="true" style="?android:listSeparatorTextViewStyle"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/crime_details_label" android:id="@+id/textView2" android:layout_below="@+id/crime_title" android:layout_alignParentStart="true" style="?android:listSeparatorTextViewStyle"/> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/textView2" android:layout_alignParentStart="true" android:layout_marginLeft="16dp" android:layout_marginRight="16dp"> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:id="@+id/crime_date" android:layout_weight="1"/> <CheckBox android:layout_width="0dp" android:layout_height="wrap_content" android:text="@string/crime_solved_label" android:id="@+id/crime_solved" android:layout_weight="1" android:layout_marginBottom="78dp"/> </LinearLayout> </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 18 public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener{ 19 public static final String EXTRA_DATE="tina.criminalintent.date"; 20 21 private Date mDate; 22 23 public static DatePickerFragment newInstance(Date date){ 24 Bundle args=new Bundle(); 25 args.putSerializable(EXTRA_DATE, date); 26 27 DatePickerFragment fragment=new DatePickerFragment(); 28 fragment.setArguments(args); 29 return fragment; 30 } 31 32 33 @Override 34 public Dialog onCreateDialog(Bundle savedInstanceState) { 35 mDate=(Date)getArguments().getSerializable(EXTRA_DATE); 36 Calendar calendar=Calendar.getInstance(); 37 calendar.setTime(mDate); 38 int year=calendar.get(Calendar.YEAR); 39 final int month=calendar.get(Calendar.MONTH); 40 final int day=calendar.get(Calendar.DAY_OF_MONTH); 41 42 return new DatePickerDialog(getActivity(),this,year,month,day); 43 } 44 45 @Override 46 public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { 47 mDate = new GregorianCalendar(year, monthOfYear, dayOfMonth).getTime(); 48 if(getTargetFragment()==null) 49 return; 50 51 Intent intent=new Intent(); 52 intent.putExtra(EXTRA_DATE,mDate); 53 getTargetFragment().onActivityResult(getTargetRequestCode(),Activity.RESULT_OK,intent); 54 } 55 56 }
至此,Demo的布局文件和Activity设计完毕。
下面是上面的文件中用到的Value文件:
strings.xml
<resources> <string name="app_name">CriminalIntent</string> <!-- TODO: Remove or change this placeholder text --> <string name="hello_blank_fragment">Hello blank fragment</string> <string name="title_activity_crime">CrimeActivity</string> <string name="crime_title_hint">Enter a title for the crime.</string> <string name="crime_title_label">title</string> <string name="crime_details_label">details</string> <string name="crime_solved_label">Solved?</string> <string name="crimes_title">Crimes</string> <string name="date_picker_title">Date of crime:</string> </resources>
还有,为ViewPager创建的ids.xml。由于这里的ViewPager是用代码产生的(mViewPager = new ViewPager(this)),而ViewPager是一个Fragment的Container,必须提供一个resource id才能被FragmentManager使用。
<?xml version="1.0" encoding="utf-8"?> <resources> <item name="viewPager" type="id"/> </resources>
至此,Demo结束。
3、Android Studio中的Fragment模板
AndroidStudio中的Fragment(Blank)模板使用的是android.app.Fragment。
Fragment(List)模板是用Frament和布局文件中的ListView相结合,没有直接使用ListFragment,模板里面有很多东西,初看有点复杂,有两个布局文件,分别用于大小屏幕(也就是手机和平板吧),大屏的那个布局文件可以放GridView。
对于上面的Demo,用模板写的CrimeListFragment大致如下:
package tina.criminalintent; import android.content.Intent; import android.os.Bundle; import android.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.TextView; import java.util.ArrayList; // ///** // * A fragment representing a list of Items. // * <p/> // * Large screen devices (such as tablets) are supported by replacing the ListView // * with a GridView. // * <p/> // * Activities containing this fragment MUST implement the {@link OnFragmentInteractionListener} // * interface. // */ public class CrimeListFragment2 extends Fragment implements AbsListView.OnItemClickListener { private ArrayList<Crime> mCrimes; // private OnFragmentInteractionListener mListener; /** * The fragment's ListView/GridView. */ private AbsListView mListView; /** * The Adapter which will be used to populate the ListView/GridView with * Views. */ private CrimeAdapter mAdapter; /** * Mandatory empty constructor for the fragment manager to instantiate the * fragment (e.g. upon screen orientation changes). */ public CrimeListFragment2() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getActivity().setTitle(R.string.crimes_title); mCrimes=CrimeLab.getInstance(getActivity()).getCrimes(); mAdapter=new CrimeAdapter(mCrimes); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_crimelist, container, false); // Set the adapter mListView = (AbsListView) view.findViewById(android.R.id.list); ((AdapterView) mListView).setAdapter(mAdapter); // Set OnItemClickListener so we can be notified on item clicks mListView.setOnItemClickListener(this); return view; } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Crime crime=((CrimeAdapter)(parent.getAdapter())).getItem(position); // Intent intent=new Intent(getActivity(),CrimeActivity.class); Intent intent=new Intent(getActivity(),CrimePagerActivity.class); intent.putExtra(CrimeFragment.EXTRA_CRIME_ID, crime.getId()); startActivity(intent); } private class CrimeAdapter extends ArrayAdapter<Crime>{ public CrimeAdapter(ArrayList<Crime> crimes) { super(getActivity(), 0, crimes); } @Override public View getView(int position, View convertView, ViewGroup parent) { if(convertView==null){ convertView=getActivity().getLayoutInflater() .inflate(R.layout.list_item_crime,null); } Crime c=getItem(position); TextView titleTextView=(TextView)convertView.findViewById(R.id.crime_list_item_title); titleTextView.setText(c.getTitle()); TextView dateTextView=(TextView)convertView.findViewById(R.id.crime_list_item_date); dateTextView.setText(c.getDate().toString()); CheckBox solvedCheckBox=(CheckBox)convertView.findViewById(R.id.crime_list_item_solvedCheckBox); solvedCheckBox.setChecked(c.isSolved()); return convertView; } } @Override public void onResume() { super.onResume(); ((CrimeAdapter)mListView.getAdapter()).notifyDataSetChanged(); } }
刚刚接触Fragment,除了模板不兼容Android3.0以下版本以外,我觉得里面的结构也有点复杂,不过Fragment的使用方法很多,具体不知道这种模板是不是用得比较普遍。以后再看吧。
4、运行效果