編輯:關於Android編程
Fragment代表了在Activity中的一種或者一部分行為,你可以在單個的activity中連接多個fragment來構建一個多面板的UI,並且在多個activity中重復使用一個fragment,你可以把fragment想象成為activity的一個模塊化片段,它有它自己的生命周期,接收它自己的輸入事件,還有就是當activity運行的時候,你也能添加或者移除fragment。
一個frgment必須被嵌入在一個activit中,並且這個fragment的生命周期直接被它的主activity的生命周期所影響。例如,當activity被暫停的時候,在它裡面的fragment也會被暫停,當activity被銷毀的時候,在它裡面的fragment也會被銷毀。但是,當activity運行的時候(它恢復了生命周期狀態),你可以獨立的維護每一個fragment,比如添加或者移除他們。當你執行這樣一個fragment事件的時候,你可以把它添加到被這個activity所管理的回退棧中,在activity中的每一個回退棧記錄了fragment的事件的發生。通過按返回按鈕,回退棧允許用戶返回一個fragment事件(向後導航)。
當你添加的fragment作為activity布局的一部分的時候,它就寄居在activity的視圖結構的一個ViewGroup中,而且fragment定義了它自己的布局。你可以在activity的布局文件中定義fragment來插入到你的activity中,像
這個文檔描述了怎樣用fragment構建你的應用程序,包括當fragment被添加到activity的回退棧的時候,fragment如何維護他們的狀態,還有跟activity共享事件以及在activity中的其它fragment,貢獻給activity的動作條等等。
Android在3.0中引入了fragment,主要是為了在大屏上支持更多的動態的和固定UI設計,像平板。由於平板的屏幕比手持設備的要大,也就有更多的空間鏈接並且與UI組件交互了。像這樣的fragment設計讓你避免了管理復雜的視圖結構。通過把activity的布局分隔為fragment,你能夠在運行時修改activity的外觀,並且會在activity管理的回退棧中維持這些改變。
例如,一個新聞應用程序可以使用一個fragment在左邊展示一個文章列表,另一個fragment在右邊展示文章,這兩個fragment都出現在一個activity中,緊挨著,並且每一個fragment有它自己的生命周期回調方法還有它們自己的用戶輸入事件。因此,代替使用activity選擇一個文章,並且另一個activity來讀這個文章,用戶能在同一個activity中選擇文章並且讀文章。在平板中的插圖如圖:
你應當把fragment設計成為一個模塊化的並且可以重復使用的activity組件。也就是說,由於每一個fragment定義了它自己的布局以及用它自己的生命周期回調定義了自己的行為,你可以在多個activity中包含一個fragment。這是非常重要的,因為一個模塊化的fragment允許你改變你的fragment來連接不通尺寸的屏幕。當設計你的應用程序既支持平板又支持手持設備的時候,你可以基於有效的屏幕空間在不同的布局配置中重復使用你的fragment來優化用戶體驗。例如,在一個手持設備上,當超過一個fragment的時候在activity中不能適配,也許就需要分隔fragment來提供一個單個的UI。
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+Cjxicj4KPC9wPgo8cD4KwP3I5y28zND4yrnTw9DCzsXTptPDs8zQ8sD919MttbHUy9DQ1NrSu7j2xr2w5bXnxNS089ChtcTJ6LG4yc+1xMqxuvKjrNTaYWN0aXZpdHkgQdbQo6zTptPDs8zQ8r/J0tTHtsjrwb249mZyYWdtZW50oaO1q8rH1NrSu7j2ytaz1sbBxLvJz6Osw7vT0Nfjubu1xL/VvOS4+MG9uPZmcmFnbWVudKOs0vK0y0FjdGl2aXR5sPy6rM6o0ru1xGZyYWdtZW50uPjOxNXCwdCx7aOstvjH0rWx08O7p9Gh1PHBy9K7uPbOxNXCtcTKsbryo6zL/L+qxvTBy0FjdGl2aXR5IEKjrNXiuPZhY3Rpdml0ebD8uqzBy7Xatv649mZyYWdtZW50wLS2wdXiuPbOxNXCoaPS8rTL08Oyu82stcTX6brPzai5/dbYuLTKudPDZnJhZ21lbnSjrNOm08OzzNDyvMjWp7PWxr2w5dKy1qez1srWs9ahozwvcD4KPHA+Cjxicj4KPC9wPgo8cD4K08Oyu82stcRmcmFnbWVudNfpus+4+LK7zay1xMbBxLvF5NbDyei8xsTjtcTTptPDs8zQ8rXEuPy24NDFz6KjrMfrv7QgU3VwcG9ydGluZyBUYWJsZXRzIGFuZCBIYW5kc2V0c6GjPGJyPgo8L3A+CjxwPgo8YnI+CjwvcD4KPGgyPgq0tL2o0ru49kZyYWdtZW50PC9oMj4KPGhyPgo8cD4KPGJyPgo8L3A+CjxwPgrOqsHLtLS9qNK7uPZGcmFnbWVudKOsxOOx2NDryrXP1rS0vajSu7j2RnJhZ21lbnS1xNfTwOAou/LV38v8tcTX08DgtcTX08DgKaGjRnJhZ21lbnS1xLT6wuu4+mFjdGl2aXR5tcS/tMbwwLS63M/xoaPL/LD8uqy1xLvYtfe3vbeouPpBY3Rpdml0edKyutzP4CYjMjAyODQ7oaPP8W9uQ3JlYXRlKCksb25TdGFydCgpLG9uUGF1c2UoKbu509BvblN0b3AoKaGjysLKtcnPo6zI57n7xOPKudPDZnJhZ21lbnTAtNequ7vSu7j20tG+rbTm1Nq1xEFuZHJvaWTTptPDs8zQ8qOsxOO/ydLUtNPE47XEYWN0aXZpdHm1xLvYtfe3vbeo1tC88rWltcSw0bT6wuvSxravtb3P4NOmtcRmcmFnbWVudLXEu9i197e9t6jW0KGjPC9wPgo8cD4KPGltZyBzcmM9"/uploadfile/Collfiles/20141221/20141221091010267.png" title="fragment_lifecycle.png" alt="\">
通常,你應該至少實現生命周期中的下面三個方法:
onCreate()
當創建fragment的時候系統調用。在你的實現裡,你應該初始化fragment需要的組件,這個組件是當你的fragment被暫停或者停止的時候被回收的,然後恢復。
onCreateView()
當fragment第一次繪制它的UI的時候系統調用它。為了給你的fragment繪制UI,你必須從這個方法中返回你的fragment布局的根View。如果fragment不提供UI,你可以返回null。
onPause()
當檢測到用戶要離開這個fragment的時候系統調用它。這個方法應該通過當前用戶session是通常你應該提交應該持久化的數據的地方。
大多數的應用程序為每個fragment至少應該實現那三個方法,但是有幾個其它的回調方法你也應該用於操作fragment生命周期的不同階段。 所有的生命周期回調方法被詳細的討論在 Handling the Fragment Lifecycle。
也有幾個可能你想擴展的子類代替Fragment基類:
DialogFragment
展示一個浮動的對話框。使用這個類創建對話框,在Activity類中使用對話框幫助器方法是一個不錯的選擇。因為你可以把一個fragment對話框合並到被activity管理的回退棧中。allowing the user to return to a dismissed fragment(這裡先pending)。
ListFragment
展示一個被適配器管理的項列表(像SimpleCursorAdapter),與ListActivity是相似的。它提供了幾個方法來管理列表視圖,像onListItemClick()回調來持有點擊事件。
PreferenceFragment
展示一個Preference對象的結構列表,跟PreferenceActivity相似。當在你的應用程序中創建一個“settings”的activity是有效的。
一個fragment通常被用於activity的用戶接口的一部分而且把自己的布局提供給activity。為了給一個fragment提供一個布局,你必須實現一個onCreateView()回調方法,當fragment繪制它的布局的時候,這個方法被調用,你的這個方法的實現必須返回你的fragment的布局的根View。
注意:如果你的fragment是ListFragment的子類,從onCreateView()中默認返回一個ListView,因此你不需要實現它。
為了從onCreateView()中返回一個布局,你可以從一個被定義在XML中的布局資源填充它。為了幫助你做這些,onCreateView()提供了一個LayoutInflater對象。
例如,這是個Fragment的子類從example_fragment.xml文件中載入一個布局:
public static class ExampleFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.example_fragment,false); } }
被傳遞給容器的參數是父ViewGroup(來自於Activity的布局),在這個ViewGroup中,你的fragment布局被插入。參數savedInstanceState是一個Bundle,如果fragment被恢復,這個對象提供了前面的fragment的實例的數據。
inflate()帶有三個參數:
你想要填充的布局的ID
ViewGroup是被填充布局的父ViewGroup,對被填充的即將要進入的被指定的父視圖布局的根視圖為了讓系統應用布局參數,傳遞container是重要的。
一個布爾值,檢查是否在填充期間被填充的布局應當被綁定到ViewGroup(第二個參數)。
現在你已經看到了提供一個布局如何創建一個fragment。接下來,你需要把fragment添加到你的activity中。
通常,fragment給主activity提供了一部分的UI,它作為activity所有視圖結構的一部分被嵌入。有兩種方式你能給activity布局添加一個fragment。
在這個例子中,你能給fragment像視圖一樣指定布局屬性。例如,下面的布局文件中兩個fragment組成了一個activity:
在
注意:如果activity被重啟(並且你能用它獲取fragment來執行事物,像移除它),每一個fragment要求有一個唯一的系統可以用來恢復fragment的標示符。有三種方式可以給fragment提供一個ID:
提供android:id屬性支持一個唯一ID
提供android:tag屬性支持唯一ID
如果你沒有提供前面的兩個屬性,系統會使用容器視圖ID。
在任何時候,當你的activity運行的時候,你可以給你的activity布局添加fragment。你只需要在這個activity中指定一個放置fragment的ViewGroup。
為了在你的activity中制造fragment事物(像添加,移除,替換一個fragment),你必須使用FragmentTransaction的API。你可以從你的Activity中獲得FragmentTransaction的實例,像這樣:
FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
然後你可以使用add()方法添加一個fragment,指定fragment去添加,並且使用這個視圖插入它。例如:
ExampleFragment fragment = new ExampleFragment(); fragmentTransaction.add(R.id.fragment_container,fragment); fragmentTransaction.commit();
傳遞給add()的第一個參數是通過指定的資源ID放置frament的ViewGroup,並且第二個參數是要被添加的fragment。
一旦你用FragmentTransaction做了改變,你必須調用commit()來讓改變生效。
上面的例子展示了如果給你的activity添加一個fragment來提供一個UI。然而,你可以使用一個fragment在沒有額外的UI的情況下給這個activity提供一個後台行為。
為了添加一個沒有UI的fragment,使用add(Fragment,String)從activity中添加fragment(給fragment提供唯一的字符串“tag”,而不是一個視圖ID)。這就添加了fragment,但是,由於它在activity布局中沒有跟一個視圖關聯,它也就不會接收一個onCreateView()的調用。因此你不需要實現這個方法。
給非UI的fragment提供一個字符串標簽不是強制的,你也能給有UI的fragment提供字符串標簽-但是如果fragment沒有頭UI,那麼這個字符串tag就是辨識它的唯一方式。如果你想在以後從activity中獲取fragment,你需要使用findFragmentByTag()。
為了管理你的activity中的fragment,你需要使用FragmentManager。為了獲取它,從你的activity中調用getFragmentManager()。
你可以用FragmentManager做下面的事情:
用findFragmentById()(對於在activity布局中提供了UI的fragment)或者findFragmentByTag()(給沒有提供UI的fragment)獲取在activity存在的fragment。
使用popBackStack()從回退棧中彈出fragment。
用addOnBacktackChangeListener()注冊一個監聽器到回退棧中。
關於那些方法和其它的更多的信息,請看FragmentManager類文檔。
像在前面的片段中顯示的,你也能使用FragmentManager打開一個fRAGMENTtRANSACTION。這個FagmentTransaction允許你執行像添加和移除frament的事務。
在你的activity中使用fragment的更大的一個特性是在你的用戶交互上使用這些fragment能添加,移除,替換和執行其它的動作。每一個你提交到activity的改變都調用了一個事務並且你可以使用FragmentTransaction的API執行。你也可以保存每一個事務到一個被這個activity管理的回退棧,通過fragment的改變允許用戶導航回退(類似於通過activity回退)。
你可以從FragmentManager請求一個FragmentTransaction實例,像這樣:
FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
每一個事務是一組你想要在同一時間執行的改變。你可以給一個被給定的事務使用像add(),remove()和replace()方法設置所有你想要執行的改變。然後,給這個activity應用事務,你就必須調用commit()。
在你調用commit()方法以前,然後,為了添加事務到一個fragment事務的回退棧中,你也許想調用addToBackStack()。這個後台站被這個activity所管理並且允許用戶通過按返回按鈕返回到前一個fragment狀態。
例如,下面的例子是用一個fragment替換另一個fragment的,在回退棧中維持遷移個的狀態:
//Create new fragment and transaction Fragment newFragment = new ExampleFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); //Replace whatever is in the fragment_container view with this fragment, //and add the transaction to the back stack transaction.replace(R.id.fragment_container,newFragment); transaction.addToBackStack(null); //Commit the transaction transaction.commit();
在這個例子中,不管在當前的布局文件中的fragment是什麼,newFragment會用被標示的R.id.fragment_container的ID替換掉它。通過調用addToBackStack()替換被爆粗你在回退棧中的事務,因此用戶可以維持這個事務並且通過按下返回按鈕回到前一個fragment。
如果你給事務添加了多個改變(像另一個add()或者remove())並且調用addToBackStack(),那麼在你提交以前所有被應用的改變作為一個單獨的事務會被添加到回退棧,並且返回按鈕將一起回退它們。
你添加到一個FragmentTransaction鐘的順序是無關緊要的,除了:
你必須最後調用commit()
如果你給相同的容器添加多個fragment,那麼你添加它們的實訓決定了它們在視圖結構中出現的順序。
當你執行一個移除一個fragment的事務的時候,如果你不調用addToBackStack(),那麼當事務被提交的時候,那個fragment會被銷毀,並且用戶就不能導航回到上一個fragment了。反之,當移除一個fragment的時候,如果你調用addToBackStack(),那麼fragment背停止並且如果用戶導航回退,它將被恢復。
建議:對於每一個fragment事務,在你提交之前,你可以通過調用setTranction()應用事務動畫。
調用commit()不會立即執行事務。當然,它會在activity的UI線程中有計劃的執行。如果需要,然後,你可以從你的UI線程中調用executePendingTransaction()來立即執行通過commit()提交的事務。這樣做通常是不需要的,除非這個事務是一個依賴於在其它線程中的任務的。
注意:你可以使用commit()提交一個事務,這個動作僅僅優先於activity保存它的狀態的動作。如果你嘗試在那個點之後提交,將會拋出一個異常。這是因為如果activity需要被恢復,提交後的狀態可能會被丟失。對於這種情況,你可以使用commitAllowingStateLoss()來記錄你丟失的commit。
背景關於Launcher是啥的問題我想這裡就沒必要再強調了。由於一些原因迫使最近開始需要研究一下Launcher3源碼,為了不再像以前那麼傻逼(研究Settings等代碼
1.簡介使用自定義主題或者皮膚,可以將相關配置(顏色、大小等等)放在一個新的apk壓縮文件中,目錄結構保持一致,該apk文件放在任意可以訪問到的目錄即可,類似/syste
主界面開發上一節,我們已經完成了首頁的開發,現在,我們繼續完成主界面的開發,就是添加底部‘首頁’和‘我的’兩個tabbar
引言:記得去年下半年有上傳一份代碼(超逼真仿雅虎天氣界面):http://download.csdn.net/detail/weidi1989/6312271但那僅僅只是