BNR Android Demo学习笔记(一)——CrimeIntent

开发环境: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;
    }
}
View Code

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;
    }
}
View Code

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();
        }
    }
}
View Code

其对应的布局文件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 }
View Code

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();
        }
    }


}
View Code

对应的布局文件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 }
View Code

至此,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();
    }
}
View Code

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

4、运行效果

原文地址:https://www.cnblogs.com/tt2015-sz/p/4647609.html