標籤:字串資源 property listener undle final lint ada android pac
CriminalIntent項目開發1.fragment的引入
採用fragment而不是activity來管理應用UI,可繞開Android系統activity使用規則的限制。
fragment是一種控制器對象,activity可委派它完成一些任務。
這些任務通常就是系統管理使用者介面。受管的使用者介面可以是一整屏或是整屏的一部分。系統管理使用者介面的fragment又稱為UI fragment。
它自己也有產生於布局檔案的視圖。fragment視圖包含了使用者可以互動的可視化UI元素。
利用fragment,可輕鬆實現選擇不同的清單項目就顯示對應的明細視圖Activity負責以一個明細fragment替換另一個明細fragment,1.1所示。
這樣,視圖切換的過程中,就不用銷毀activity了。
圖1.1
2.fragment與支援庫
我們要用到兩個重要的支援庫類,一個是Fragment類( android.support.v4.app.Fragment )。
另一個是FragmentActivity類( android.support.v4.app.Fragment- Activity )。
使用fragment的前提是:activity知道如何管理fragment、FragmentActivity類知道如何管理支援版本的fragment。
3.定義[內容] 檢視建立fragment容器布局(activity_crime.xml)如下
<
FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/fragment_container"android:layout_width="match_parent"android:layout_height="match_parent"/>
4.定義CrimeFragment布局
CrimeFragment視圖將顯示包含在Crime類執行個體中的資訊。
該布局包括一個垂直LinearLayout布局(含有一個EditText組件)。
EditText組件有一塊地區,可供使用者添加或編輯文字資訊。
fragment視圖的布局檔案(fragment_crime.xml)如下
<
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><
EditText android:id="@+id/crime_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="@string/crime_title_hint"/></LinearLayout>
5.建立CrimeFragment類繼承Fragment類(CrimeFragment.java)如下
public class CrimeFragment extends Fragment {}
修改代碼繼承Fragment類時 ,我們需要選擇Fragment(android.support.v4.app)包
6.實現fragment生命週期覆蓋Fragment.onCreate(Bundle)方法(CrimeFragment.java)如下
public class CrimeFragment extends Fragment {private Crime mCrime;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mCrime = new Crime();}}
Fragment.onCreate(Bundle)是公用方法,而Activity.onCreate(Bundle)是保護方法。
這是因為只有Fragment.onCreate(...)方法及其他Fragment生命週期方法是公用方法,託管fragment的activity才能調用它們。
7.覆蓋onCreateView(...)方法(CrimeFragment.java)如下
@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View v = inflater.inflate(R.layout.fragment_crime, container, false);return v;}
在onCreateView(...)方法中,fragment的視圖是直接通過調用LayoutInflater.inflate(...)方法並傳入布局的資源ID產生的。
第二個參數是視圖的父視圖,因為我們通常需要父視圖來正確配置組件。
第三個參數告知布局產生器是否將產生的視圖添加給父視圖(這裡,我們傳入了false參數,因為我們將以activity代碼的方式添加視圖。)
8.在fragment中關聯組件產生並使用EditText組件(CrimeFragment.java)如下
public class CrimeFragment extends Fragment {private Crime mCrime;private EditText mTitleField;
@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_crime, container, false); mTitleField = (EditText)v.findViewById(R.id.crime_title); mTitleField.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged( CharSequence s, int start, int count, int after) { // This space intentionally left blank}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {mCrime.setTitle(s.toString());}@Overridepublic void afterTextChanged(Editable s) {// This one too}});return v;}}
Fragment.onCreateView(...)方法中的組件引用幾乎等同於Activity.onCreate(...)方法的處理。唯一的區別是我們調用了fragment視圖的View.findViewById(int)方法。
9.添加UI fragment到FragmentManager
FragmentManager 類具體管理的是:
? fragment隊列;
? fragment交易回復棧。
擷取FragmentManager(CrimeActivity.java)如下
FragmentManager fm = getSupportFragmentManager();
添加一個CrimeFragment(CrimeActivity.java)如下
Fragment fragment = fm.findFragmentById(R.id.fragment_container);if (fragment == null) {fragment = new CrimeFragment();fm.beginTransaction().add(R.id.fragment_container, fragment).commit();}
fragment事務被用來添加、移除、附加、分離或替換fragment隊列中的fragment。這是使用fragment在運行時組裝和重新組裝使用者介面的關鍵。
FragmentManager管理著fragment交易回復棧。
10.使用布局與組件建立使用者介面
開啟Crime.java檔案,新增兩個執行個體變數。
Date變數表示crime發生的時間,boolean變數表示crime是否已得到處理。
添加更多變數(Crime.java)如下
private Date mDate;private boolean mSolved;public Crime() {mId = UUID.randomUUID();mDate = new Date();}
添加新組件(fragment_crime.xml)如下
為CrimeFragment的布局添加四個組件:兩個TextView組件、一個Button組件以及一個CheckBox組件
<
TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="@string/crime_title_label"style="?android:listSeparatorTextViewStyle"/><
EditText android:id="@+id/crime_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="16dp"android:layout_marginRight="16dp"android:hint="@string/crime_title_hint"/><
TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="@string/crime_details_label"style="?android:listSeparatorTextViewStyle"/><
Button android:id="@+id/crime_date"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="16dp"android:layout_marginRight="16dp"/><CheckBox android:id="@+id/crime_solved"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="16dp"android:layout_marginRight="16dp"android:text="@string/crime_solved_label"/>
添加字串資源(strings.xml)如下
<string name="crime_title_label">Title</string><string name="crime_details_label">Details</string><string name="crime_solved_label">Solved</string>
添加組件執行個體變數(CrimeFragment.java)如下
接下來,要讓CheckBox顯示Crime是否已得到處理。使用者勾選清除CheckBox時,Crime的mSolved變數的狀態值也需得到相應的更新。
private Button mDateButton;private CheckBox mSolvedCheckBox;
設定Button上的文字顯示(CrimeFragment.java)如下
mDateButton = (Button)v.findViewById(R.id.crime_date);mDateButton.setText(mCrime.getDate().toString());mDateButton.setEnabled(false);
禁用按鈕可以確保它不響應使用者的單擊事件。禁用後,按鈕的外觀樣式也會發生改變(變為灰色),表明它已處于禁用狀態。
偵聽CheckBox狀態的變化(CrimeFragment.java)如下
mSolvedCheckBox = (CheckBox)v.findViewById(R.id.crime_solved);mSolvedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {// Set the crime‘s solved propertymCrime.setSolved(isChecked);}});
建立OnCheckedChangeListener時需要匯入android.widget.CompoundButton的包。
11.使用RecyclerView
首先要匯入recyclerview-v7支援庫
在布局檔案中添加RecyclerView視圖(fragment_crime_list.xml)如下
<android.support.v7.widget.RecyclerViewxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/crime_recycler_view"android:layout_width="match_parent"android:layout_height="match_parent"/>
為CrimeListFragment配置視圖(CrimeListFragment.java)如下
private RecyclerView mCrimeRecyclerView;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_crime_list, container, false);mCrimeRecyclerView = (RecyclerView) view.findViewById(R.id.crime_recycler_view);mCrimeRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));return view;}
RecyclerView類的任務就是回收再利用以及定位螢幕上的TextView視圖。
實際上,定位的任務被委託給了LayoutManager。
除了在螢幕上定位清單項目,LayoutManager還負責定義螢幕滾動行為。
因此,沒有LayoutManager,RecyclerView也就無法正常工作了。
12.從fragment中啟動activity
在CrimeListFragment的CrimeHolder類裡,用啟動CrimeActivity執行個體的代碼,替換Toast訊息處理代碼。
啟動CrimeActivity(CrimeListFragment.java)如下
Intent intent = new Intent(getActivity(), CrimeActivity.class);startActivity(intent);
13.使用ViewPager
為UI添加ViewPager後,使用者可滑動螢幕,切換查看不同清單項目的明細頁面。
建立ViewPager(CrimePagerActivity.java)如下
public class CrimePagerActivity extends FragmentActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_crime_pager);}}
注意:必須使用ViewPager的包名全稱(android.support.v4.view.ViewPager)。13.1所示。
圖13.1
設定pager adapter(CrimePagerActivity.java)如下
public class CrimePagerActivity extends FragmentActivity { private ViewPager mViewPager; private List<Crime> mCrimes;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_crime_pager); mViewPager = (ViewPager) findViewById(R.id.activity_crime_pager_view_pager); mCrimes = CrimeLab.get(this).getCrimes(); FragmentManager fragmentManager = getSupportFragmentManager(); mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) { @Override public Fragment getItem(int position) { Crime crime = mCrimes.get(position); return CrimeFragment.newInstance(crime.getId()); }@Override public int getCount() {
return mCrimes.size(); }});}}
在activity視圖中找到ViewPager後,我們從CrimeLab中(crime的List)擷取資料集,然後擷取activity的FragmentManager執行個體。
設定adapter為FragmentStatePagerAdapter的一個匿名執行個體。建立Fragment-StatePagerAdapter執行個體需要FragmentManager。
建立newIntent方法(CrimePagerActivity.java)如下
private static final String EXTRA_CRIME_ID ="com.bignerdranch.android.criminalintent.crime_id";
public static Intent newIntent(Context packageContext, UUID crimeId) {Intent intent = new Intent(packageContext, CrimePagerActivity.class);intent.putExtra(EXTRA_CRIME_ID, crimeId);return intent;}
UUID crimeId = (UUID) getIntent().getSerializableExtra(EXTRA_CRIME_ID);
然後需要修改CrimeListFragment,使得使用者單擊某個清單項目時,CrimeListFragment啟動的是CrimePagerActivity執行個體。
配置啟動CrimePagerActivity(CrimeListFragment.java)
Intent intent = CrimePagerActivity.newIntent(getActivity(), mCrime.getId());
Android開發3、4周——Criminallntent項目