預備知識
嵌套Tab在Android應用中用途廣泛,之前做過的一些東西都是運用了TabActivity。但是由於在Android Developers中說到了“TabActivity was deprecated in API level 13." ,並且建議大家使用Fragment。所以學習了嵌套Fragment的使用,參考了這個部落格中的相關思路和代碼。
在Android Developers中對於Fragment(中文版看這裡)的描述:A Fragment represents a behaviors or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running.
簡單來說,Fragment就是被嵌入在Activity中用來表現UI的一個可模組化和可重用的組件。Fragment在大螢幕裝置中應用可以非常廣泛,開發人員可以通過自己巧妙的設計讓UI更加靈活和美觀。
建立Fragment
建立Fragment,必須建立一個Fragment的子類。
建立一個自己的Fragment,需要建立一個Fragment的子類。Fragment的生命週期和Activity的生命週期類似,它包含了很多與Activity類似的回呼函數。
[java]
public void onCreate (Bundle savedInstanceState)
public void onCreate (Bundle savedInstanceState)建立fragment的時候調用onCreate()方法
[java]
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)在第一次繪製UI的時候系統調用該方法,為了繪製UI,返回一個fragment布局的根View。
將Fragment添加到Activity的方法
1.在layout檔案中聲明fragment
[plain]
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1.0"
android:background="#fffab3" >
</FrameLayout>
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1.0"
android:background="#fffab3" >
</FrameLayout>
2.將一個fragment添加到viewgroup中,使用FragmentTransaction添加、替換或者刪除fragment。
[java]
private void addFragmentToStack(Fragment fragment) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, fragment);
ft.commit();
}
private void addFragmentToStack(Fragment fragment) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, fragment);
ft.commit();
}Fragment生命週期
異常分析
關於解決 java.lang.IllegalStateException The specified child already has a parent. You must call removeView()的方法
在運行調試的時候會發現,在第二次點擊一個相同的tab的時候,會出現上述異常。
這個異常說的是,這個特定的child view已經存在一個parent view了,必須讓parent view調用removeView()方法。
經過對fragment的生命週期的分析
運行順序:點擊tab1,點擊tab2,再點擊tab1.
具體fragment的生命週期是:
對進行分析,可以發現,出問題的是viewpager中的view。當切換不同的viewpager(即fragment,每個fragment中裝載了一個viewpager)時,調用了startActivity()方法的時候,傳入了相同的id,會返回相同的對象。而當我們在第二次調用的時候,傳入了相同的id是複用了原來的view,這就導致了view被指定多個parent view。
所以解決辦法就是,在使用這個view之前首先判斷其是否存在parent view,這調用getParent()方法可以實現。如果存在parent view,那麼就調用removeAllViewsInLayout()方法。代碼如下:
[java]
for (View view : viewList) {
ViewGroup p = (ViewGroup) view.getParent();
if (p != null) {
p.removeAllViewsInLayout();
}
}