FragmentTabHost显示重叠的片段

时间:2013-02-14 13:53:26

标签: tabs android-fragments android-tabhost overlap

我在一个FragmentActivity中使用一个FragmentTabHost,它有3个标签。 如果我从每个选项卡的第一页更改选项卡它可以正常工作,但如果我在一个选项卡中导航片段然后更改选项卡,它会显示与旧片段重叠的新片段。 有人可以帮帮我吗?

这是FragmentActivity(fragments_tab.xml)的布局:

    <?xml version="1.0" encoding="UTF-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/relativeLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/background_gradient">

    <ImageView
        android:contentDescription="@string/app_name"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:src="@drawable/background_gradient" />

    <android.support.v4.app.FragmentTabHost
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TabWidget
            android:id="@android:id/tabs"
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0"/>

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="0"/>

        <LinearLayout
            android:id="@+id/realtabcontent"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"/>

    </LinearLayout>
    </android.support.v4.app.FragmentTabHost>
    </RelativeLayout>

My FragmentActivity的代码:

    public class MainActivity extends FragmentActivity {

        private FragmentTabHost mTabHost;

        @Override   
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setDB();
            setContentView(R.layout.fragments_tab);

            mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);

            mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);


            mTabHost.addTab(mTabHost.newTabSpec("Home").setIndicator("Home",      getResources().getDrawable(R.drawable.ic_menu_home)),
                    HomeFragment.class, null);

            mTabHost.addTab(mTabHost.newTabSpec("Map").setIndicator("Map", getResources().getDrawable(R.drawable.ic_menu_mapmode)),
                    MapMenuFragment.class, null);
            mTabHost.addTab(mTabHost.newTabSpec("Info").setIndicator("Info", getResources().getDrawable(R.drawable.ic_menu_info_details)),
                    InfoFragment.class, null);
        }
}

创建每个片段:

public class InfoFragment extends Fragment {

    @Override
    public void onActivityCreated(Bundle savedInstanceState) 
    {
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View view = inflater.inflate(R.layout.fragment_info, container, false);
        return view;
    }

有人可以帮我吗?

5 个答案:

答案 0 :(得分:1)

我找到了解决问题的方法。 在我的项目中,每个片段都是一个扩展类Fragment的不同类。当FragmentTabHost尝试分离旧片段时,它找不到Fragment对象,因此它没有删除任何内容。

我不是那么专家,我确​​信有一种更简单的方法,但经过许多头痛后我发现这个解决方案有效。 这就是我所做的:

  • 我将每个标签的当前片段保存到活动中的Object变量中。
  • 我将FragmentTabHost的代码复制到自己的类中,并在调用detach或attach时更改了方法doTabChanged。

(我有3个标签“Home”,“Map”和“Info”)

分离:

//ft.detach(mLastTab.fragment);
if(mLastTab.tag == "Home") ft.detach((Fragment) tabHomeFragment);
else if(mLastTab.tag == "Info") ft.detach((Fragment) tabInfoFragment);
else ft.detach((Fragment) tabMapFragment);

附:

//ft.attach(newTab.fragment);
if(newTab.tag == "Home") ft.attach((Fragment) tabHomeFragment);
else if(newTab.tag == "Info") ft.attach((Fragment) tabInfoFragment);
else ft.attach((Fragment) tabMapFragment);

tabHomeFragment,tabMapFragment和tabInfoFragment包含每个标签的当前片段

答案 1 :(得分:1)

出现问题是因为TabHost无法正确管理您添加的片段。

我遇到了同样的问题,并通过Fragment Container模式解决了。

FragmentContainer是一个从Fragment扩展的自定义类。您可以使用容器初始化每个选项卡。

每个Container通过getChildFragmentManager()管理自己的子片段。 您可以根据需要添加,替换,删除任何内容。

更改Tab后,容器也会切换,没有重叠问题。

这是我写过的一个简单的容器: https://stackoverflow.com/a/15903349/1695108

答案 2 :(得分:1)

我知道这是一个相当古老的问题,但无论如何我都会提供我的解决方案,所以对任何人来说都可以阅读这个问题。 我有同样的问题,我意识到问题是由调用

引起的
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);

因为进行此调用,tabhost将使用mTabHost.addTab方法

中指定的所有片段对此FrameLayout进行初始化

我解决了我的问题

mTabHost.setup(this, getSupportFragmentManager(), R.id.tabcontent);

这样,FrameLayout R.id.tabcontent将被隐藏(width = 0,height = 0),而不是简单地实现OnTabChangeListener,你可以这样做

@Override
    public void onTabChanged(String tabId) {
        FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        if (tabId.equals(Frament1.TAG)) {
            t.replace(R.id.realtabcontent, Fragment1.newInstance());
        } else if (tabId.equals(Frament2.TAG)) {
            t.replace(R.id.realtabcontent, Fragment2.newInstance());
        } else if (tabId.equals(Frament3.TAG)) {
            t.replace(R.id.realtabcontent, Fragment3.newInstance());
        }
        //optional
        t.addTobackStack();

        t.commit()
    }

它应该有用

答案 3 :(得分:0)

我实际上遇到了类似的问题。我在ListFragment中选择项目,然后创建一个新片段并替换选项卡布局中的原始列表片段。我发现当我切换到其他标签时,我会同时出现多个片段的问题,相互重叠,或者我有片段应该显示消失。我的解决方案是在选择新选项卡时清除后台堆栈,尝试将此代码添加到TabListener中的onTabSelected()方法

FragmentManager manager = getSupportFragmentManager();

    if(manager.getBackStackEntryCount() > 0)
    {
        manager.popBackStack(null, 
                             FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

这样做解决了我的问题。

答案 4 :(得分:0)

我遇到过类似情况,以下情况对我有用。

检查savedInstanceState是否为null,在这种情况下,不执行片段事务。它将解决这个问题。

if (homeFragment == null) {
    if (savedStateInstance != null) {
    homeFragment = (HomeFragment) fragmentManager.findFragmentByTag(HOME_FRAGMENT);
    return;
}
// tie new fragment
homeFragment = new HomeFragment();
homeFragment.setArguments(bundle);
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(homeFragment, HOME_FRAGMENT);
transaction.commit();
}

希望这有帮助。