我正在处理TabHost
,其标签与Fragment
相关联(每个标签不同)。这些Fragment
中的每一个都在另一个Fragment
的实例中,这是一个具有两种状态的登录栏:登录或不登录。
退出示例
登录示例
在布局术语中,这些状态中的每一个都已关联View
(非登录情况下为TextView
,登录情况为LinearLayout
,因此如果其中一个是VISIBLE
,则另一个是GONE
。根据选项卡内容,这是其中一个(firsttab.xml
)的代码示例:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.android.gms.ads"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0000FF"
android:orientation="vertical">
<!-- That's the login bar -->
<fragment
android:id="@+id/firsttab_loginrow"
class="com.mydomain.myproject.LoginRowFragment"
android:tag="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/firsttab_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
内部片段(com.mydomain.myproject.LoginRowFragment
)以这种方式定义:
<!-- If the user is not logged in -->
<TextView
android:id="@+id/identification_nologin"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textColor="#FFFFFF" />
<!-- if the user is logged in -->
<LinearLayout
android:id="@+id/identification_didlogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
...
</LinearLayout>
一般模式可能是这样的:
当我通过attach()
或detach()
对应的父母Fragment
(在这种情况下,firsttab.xml
处理标签更改事件时,问题就出现了)。在连接/分离父级之前,我尝试detach()
登录Fragment
(内部登录),但它不会触发onDetach()
回调。 attach()
时会发生同样的情况。奇怪的是,如果我用.detach()
替换.remove()
,它就可以了。
@Override
public void onTabChanged(final String tag) {
final TabInfo newTab = mTabInfo.get(tag);
if (lastTab != newTab) {
final FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction();
if ((lastTab != null) && (lastTab.getFragment() != null)) {
// This is where it fails detaching. tabInfo is just a structure where I store some data
// about the tabs to handle them. If I use remove() instead of the next detach() on loginFrag,
// the onAttach()/onDetach() callbacks are not called. I'm quite sure everything is ok, loginFrag
// is not null, it's actually the Fragment that should be detached, etc.
final Fragment loginFrag = (Fragment) lastTab.getFragment().getActivity().getSupportFragmentManager().findFragmentById(lastTab.getLoginFragId());
ft.detach(loginFrag);
ft.detach(lastTab.getFragment());
}
if (newTab != null) {
if (newTab.getFragment() == null) {
final TabFragmentInflater tabInf = new TabFragmentInflater();
newTab.setFragment(Fragment.instantiate(this, tabInf.getClass().getName(), newTab.getArgs()));
ft.add(R.id.realtabcontent, newTab.getFragment(), newTab.getTag());
}
else
ft.attach(newTab.getFragment());
}
ft.commit();
this.getSupportFragmentManager().executePendingTransactions();
lastTab = newTab;
}
}
所以问题如下:
为什么 onAttach()
/ onDetach()
回调在使用LoginRowFragment
或.attach()
时未在.detach()
课程中触发,但如果我分别使用.add()
或.remove()
会被解雇?
答案 0 :(得分:4)
您无法删除已在布局XML文件中声明的片段实例(按设计)
使用FragmentTransactions时,您将操纵包含片段布局的ViewGroups。
在布局中声明片段/类时,它是View层次结构的一部分,因此您无法将其删除。
但是,您可以在该布局中添加一个新片段,因为它将充当容器。
尝试从以下位置更改布局:
<fragment
android:id="@+id/firsttab_loginrow"
class="com.mydomain.myproject.LoginRowFragment"
android:tag="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
为:
<FrameLayout
android:id="@+id/firsttab_loginrow"
android:tag="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
根据您的目的创建一个FragmentTransaction
来添加/替换/显示/隐藏。