【问题标题】:FragmentTabHost randomly goes blank after configuration change (rotation)配置更改(轮换)后,FragmentTabHost 随机变为空白
【发布时间】:2019-05-06 21:59:15
【问题描述】:

我在我的应用程序中遇到了一个令人沮丧的故障。

我的 Activity 中有一个 FragmentTabHost。 此选项卡主机托管 5 个片段,每个片段都正确呈现。

现在,诀窍是当我旋转屏幕时,有时片段没有被渲染。 选项卡小部件仍在呈现且可点击,但未显示与该片段对应的视图。

下面是一个例子。 请注意,我在realtabcontent FrameLayout 上放置了红色背景:

  1. 一切正常

  2. 旋转屏幕:屏幕随机变为部分空白

  3. 切换到其他选项卡执行相关fragment的OnCreate/OnCreateView,但是什么都没有显示

  4. 切换回第一个屏幕甚至不再显示 Fragment 的按钮

请注意: - 我第一次旋转时,仍然有一个按钮出现(它属于应该渲染的片段)。 - 一旦触发错误,我可以切换到其他选项卡。其他选项卡已正确加载(注意操作栏发生变化),但 FrameLayout 中未呈现任何内容 - 如果我回到第一个选项卡,仍然显示的按钮甚至不再呈现

还要注意一个细节:标签的红点消失了,即使设置红点的代码已正确执行。好像选项卡主机没有响应绘图请求。

这里是负责显示红点的代码:

    public void showReddotForTab(int tabIndx, Boolean showFlag){
        try {
            if (tabIndx < mTabHost.getTabWidget().getTabCount()) {
                RelativeLayout tabRootView         = (RelativeLayout) mTabHost.getTabWidget().getChildTabViewAt(tabIndx);
                WhovaNotificationBadge notifBadge  = tabRootView.findViewById(R.id.notif_badge);

                if (showFlag) {
                    notifBadge.setVisibility(View.VISIBLE);
                    notifBadge.setLabel(null);
                }
                else {
                    notifBadge.setVisibility(View.GONE);
                }
            }
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }

这是包含 FragmentTabHost 的 Activity 的布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

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

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

            <FrameLayout
                android:id="@+id/realtabcontent"
                android:background="@color/red"
                android:layout_width="fill_parent"
                android:layout_height="0dp"
                android:layout_weight="1" />

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="2px"
                android:background="@color/separate_gray"/>

            <TabWidget
                android:id="@android:id/tabs"
                android:orientation="horizontal"
                android:background="@color/new_whova_tab_bg"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:paddingTop="6dp"
                android:layout_weight="0"/>

        </LinearLayout>

    </androidx.fragment.app.FragmentTabHost>


    <TextView
        android:id="@+id/text_network"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="40dp"
        android:layout_alignParentTop="true"
        android:background="@color/orange"
        android:text="@string/network_off_indicator_msg"
        android:visibility="gone"
        android:textColor="@color/white"
        android:gravity="center"/>

</RelativeLayout>

这是设置tabhost的代码

        mTabHost = findViewById(android.R.id.tabhost);
        mTabHost.setOnTabChangedListener(tabId -> {
           ...
        })

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

        //! simplified below, but the code is simlar to it
        //! spec is basically TabHost.TabSpec spec = mTabHost.newTabSpec("someID").setImageResource(...).setIndicator(...).setContent(tag -> findViewById(R.id.realtabcontent));
        mTabHost.addTab(spec, FragmentXXXX.class, fragmentBundleXXXX);
        mTabHost.addTab(spec, FragmentXXXX.class, fragmentBundleXXXX);
        mTabHost.addTab(spec, FragmentXXXX.class, fragmentBundleXXXX);
        mTabHost.addTab(spec, FragmentXXXX.class, fragmentBundleXXXX);
        mTabHost.addTab(spec, FragmentXXXX.class, fragmentBundleXXXX);

【问题讨论】:

    标签: android android-fragments fragment-tab-host


    【解决方案1】:

    找到了解决方法,但不知道是什么原因。

    我的操作栏是一个包含AppCompatSpinner 的工具栏。 微调器仅用于图片中显示的选项卡,并设置了setOnItemSelectedListener

    当旋转屏幕时,监听器被调用(不知道为什么,因为初始选择是在设置监听器之前完成的,而不是之后发生的选择。

    无论哪种方式,有时当调用此侦听器时,从 DB 加载的数据仍在后台处理。奇怪的是,一旦完成,我们会刷新 UI,但它保持空白,并且其他选项卡受到影响。 我怀疑监听器的调用方式有问题,它阻塞了其他 UI 事件的处理,但不确定。

    当我在帖子中设置监听器时,问题就消失了

    spinner.post(() -> {
      spinner.setOnItemSelectedListener(...)
    })
    

    【讨论】:

      猜你喜欢
      • 2021-08-15
      • 1970-01-01
      • 2018-05-28
      • 1970-01-01
      • 1970-01-01
      • 2020-03-29
      • 1970-01-01
      • 2013-05-28
      • 1970-01-01
      相关资源
      最近更新 更多