閱讀49 返回首頁    go 阿裏雲 go 技術社區[雲棲]


You must call removeView() on the child's parent first

首先,Android中的Fragment是什麼?
https://developer.android.com/guide/topics/fundamentals/fragments.html
場景:
現有兩個Fragment(e.g:LoginFragment、HomeFragment)需要在Android程序運行的時候進行動態加載、切換,這種情況下,比較容器出現的一個問題就是:


// java.lang.IllegalStateException: The specified child already has a
// parent. You must call removeView() on the child's parent first.

這裏,貼出處理此問題的幾個代碼片段,備忘之:


// ...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
	Log.i(TAG, "-- onCreateView(...) --");
	mRootView = (View) inflater.inflate(R.layout.fragment_login, container, false);
	return mRootView;
}

// 當FragmentActivity動態切換Fragment的時候,上麵代碼片段中的container設置為null或者其後的參數設置為false,
// 否則會報出異常:
// java.lang.IllegalStateException: The specified child already has a
// parent. You must call removeView() on the child's parent first.
// 另外,對fragment進行remove操作前記得進行非空判斷

// ...
protected void goHome() {
	FragmentTransaction transaction = getFragmentManager().beginTransaction();

	HomeFragment homeFragment = new HomeFragment();

	if (null == getFragmentManager().findFragmentByTag("tag_home")) {
		transaction.add(R.id.fragment_main, homeFragment, "tag_home");
	}
	
	if (null != getFragmentManager().findFragmentByTag("tag_login")) {
		transaction.remove(getFragmentManager().findFragmentByTag("tag_login"));
	}
	transaction.replace(R.id.fragment_main, homeFragment)
			.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
			.commit();
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:andro
    android:
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
</FrameLayout>


The specified child already has a parent. You must call removeView() on the child's parent first.的解決辦法

    出現The specified child already has a parent. You must call removeView() on the child's parent first.這個問題,一般原因是對layout.xml的使用理解不清楚。
    以xml文件方式來設計界麵的布局,如果需要動態的對xml文件中的各類View進行修改的話,在代碼中使用時,不能直接使用this.findViewById(R.id.***)來獲取xml文件中的每個View,然後再將這些View加入到代碼中的Layout中來進行顯示。正確的做法應該是使用inflater。

    舉例如下:

xml布局文件test.xml為:

1<?xml version="1.0" encoding="utf-8"?>
 2<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
 3    android:orientation="vertical" android:layout_width="fill_parent"
 4    android:layout_height="fill_parent">
 5
 6    <TextView android:id="@+id/tv1" android:layout_gravity="center_vertical"
 7        android:layout_width="wrap_content" android:layout_height="wrap_content"
 8 />
 9
10    <TextView android:id="@+id/tv2" android:layout_gravity="center_vertical"
11        android:layout_width="wrap_content" android:layout_height="wrap_content"
12         />
13
14    <TextView android:id="@+id/tv3"
15        android:layout_gravity="center_vertical" android:layout_width="wrap_content"
16        android:layout_height="wrap_content"  />
17
18    <ImageView android:src="@drawable/line" android:layout_width="fill_parent"
19        android:layout_height="fill_parent"  />
20
21</LinearLayout>

如果你需要使用這個布局XML文件,並根據自己的需要,將其中三個TextView的文字做更改,則在代碼中應該這樣去使用:
 1     
 2     LayoutInflater inflate = (LayoutInflater)
 3         getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 4         LinearLayout layout = (LinearLayout)inflate.inflate(R.layout.poemshowlist, null); 
 5         
 6         ((TextView)layout.findViewById(R.id.tv1)).setText(text1);
 7         ((TextView)layout.findViewById(R.id.tv2)).setText(text2);
 8         ((TextView)layout.findViewById(R.id.tv3)).setText(text3);
 9         
10         LinearLayout ll= new LinearLayout(this);
11         ll.addView(layout);
12         setContentView(ll);
13         
14         
15



最後更新:2017-04-02 16:47:43

  上一篇:go android界麵研究 :Activity的Title設置
  下一篇:go tomcat下的work目錄