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