【问题标题】:FragmentTabHost getting empty fragments after popBackStackFragmentTabHost 在 popBackStack 后得到空片段
【发布时间】:2015-09-11 21:29:00
【问题描述】:

我已经尝试过 StackOverflow 中的每个帖子,但都没有成功,我有一个带有标签 A B C D E 的 FragmentTabHost 活动

当我转到选项卡 A 然后转到选项卡 B 一切正常,但如果我返回选项卡 A 为空白,则返回选项卡 B 也是空白!!

A -> B -> A = 空白 -> B = 空白

我关注了这篇文章以使其工作Dynamically changing the fragments inside a fragment tab host?,但选项卡之间的转换不起作用。

我尝试将我的 BaseContainerFragment 更改为使用 getSupportFragmentManager 而不是 getChildFragmentManager 但不成功,此时我还删除了 addToBackStack(null) 我没有想法,这里的任何帮助将不胜感激,谢谢。

这是包含使用片段创建选项卡的代码的 mainActivity。

public class ActivityMain extends FragmentActivity {

    public static final String TAB_1_TAG = "tab_1";
    public static final String TAB_2_TAG = "tab_2";
    public static final String TAB_3_TAG = "tab_3";
    public static final String TAB_4_TAG = "tab_4";
    public static final String TAB_5_TAG = "tab_5";
    private FragmentTabHost mTabHost;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
        mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
        mTabHost.getTabWidget().setDividerDrawable(null);
        mTabHost.getTabWidget().setStripEnabled(false);

        mTabHost.addTab(mTabHost.newTabSpec(TAB_1_TAG).setIndicator("", getResources().getDrawable(R.drawable.tab_account)), FragmentAccountContainer.class, null);
        mTabHost.addTab(mTabHost.newTabSpec(TAB_2_TAG).setIndicator("", getResources().getDrawable(R.drawable.tab_discounts)), FragmentPromotionsContainer.class, null);
        mTabHost.addTab(mTabHost.newTabSpec(TAB_3_TAG).setIndicator("", getResources().getDrawable(R.drawable.tab_payment)), FragmentAccountContainer.class, null);
        mTabHost.addTab(mTabHost.newTabSpec(TAB_4_TAG).setIndicator("", getResources().getDrawable(R.drawable.tab_gas)), FragmentAccountContainer.class, null);
        mTabHost.addTab(mTabHost.newTabSpec(TAB_5_TAG).setIndicator("", getResources().getDrawable(R.drawable.tab_rest)), FragmentAccountContainer.class, null);
    }

    @Override
    public void onBackPressed() {
        boolean isPopFragment = false;

        String currentTabTag = mTabHost.getCurrentTabTag();
        Log.e("ActivityMain", "currentTabTag: " + currentTabTag);
        if (currentTabTag.equals(TAB_1_TAG)) {
            isPopFragment = ((BaseContainerFragment) getSupportFragmentManager().findFragmentByTag(TAB_1_TAG)).popFragment();
        } else if (currentTabTag.equals(TAB_2_TAG)) {
            isPopFragment = ((BaseContainerFragment) getSupportFragmentManager().findFragmentByTag(TAB_2_TAG)).popFragment();
        } else if (currentTabTag.equals(TAB_3_TAG)) {
            isPopFragment = ((BaseContainerFragment) getSupportFragmentManager().findFragmentByTag(TAB_3_TAG)).popFragment();
        } else if (currentTabTag.equals(TAB_4_TAG)) {
            isPopFragment = ((BaseContainerFragment) getSupportFragmentManager().findFragmentByTag(TAB_4_TAG)).popFragment();
        } else if (currentTabTag.equals(TAB_5_TAG)) {
            isPopFragment = ((BaseContainerFragment) getSupportFragmentManager().findFragmentByTag(TAB_5_TAG)).popFragment();
        }
        Log.e("ActivityMain", "isPopFragment: " + isPopFragment);
        if (!isPopFragment) {
            finish();
        }
    }
}

这是我的 BaseContainerFragment,它允许回溯和替换片段

public class BaseContainerFragment extends Fragment {

    public void replaceFragment(Fragment fragment, boolean addToBackStack) {
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        if (addToBackStack) {
            transaction.addToBackStack(null);
        }
        transaction.replace(R.id.container_framelayout, fragment);
        transaction.commit();
        getChildFragmentManager().executePendingTransactions();
    }

    public boolean popFragment() {
        Log.e("test", "pop fragment: " + getChildFragmentManager().getBackStackEntryCount());
        boolean isPop = false;
        if (getChildFragmentManager().getBackStackEntryCount() > 0) {
            isPop = true;
            getChildFragmentManager().popBackStack();
        }
        return isPop;
    }
}

这是第一个选项卡的容器(此选项卡包含 2 个活动,一个是主要活动,另一个在 listview Click 上调用)

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    myPrefs = this.getActivity().getSharedPreferences("getLogin", Context.MODE_PRIVATE);
    idUser = myPrefs.getInt("idUser", 0);

    d(TAG, "idUser: " + idUser);
    /*
    Map<String,?> keys = myPrefs.getAll();

    for(Map.Entry<String,?> entry : keys.entrySet()){
        Log.d("map values",entry.getKey() + ": " +
                entry.getValue().toString());
    }
    */
    context = getActivity();
    pDialog = new SweetAlertDialog(context, PROGRESS_TYPE);


    // Check if Internet present
    if (!isOnline(context)) {
        // Internet Connection is not present
        makeText(context, "Error en la conexion de Internet",
                LENGTH_LONG).show();
        // stop executing code by return
        return;
    }

    new asyncGetFeedClass(context).execute();

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.activity_cardholder, container, false);

    toolbar = (Toolbar) v.findViewById(R.id.toolbar);
    TextView mTitle = (TextView) toolbar.findViewById(toolbar_title);
    mTitle.setText("TARJETAS");

    list = (ListView) v.findViewById(R.id.list);

    // Click event for single list row
    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                                int position, long id) {

            FragmentAccount fragment = new FragmentAccount();
            // if U need to pass some data
            Bundle bundle = new Bundle();

            if (listBalance.get(position).get(TAG_ACCOUNT_BANKACCOUNTS_ID) != null) {
                bundle.putString("idBankAccount", listBalance.get(position).get(TAG_ACCOUNT_BANKACCOUNTS_ID));
                bundle.putString("idGiftCard", "0");
            } else if (listBalance.get(position).get(TAG_ACCOUNT_GIFTCARDS_ID) != null) {
                bundle.putString("idGiftCard", listBalance.get(position).get(TAG_ACCOUNT_GIFTCARDS_ID));
                bundle.putString("idBankAccount", "0");
            } else {
                bundle.putString("idBankAccount", "0");
                bundle.putString("idGiftCard", "0");
            }

            fragment.setArguments(bundle);
            ((BaseContainerFragment) getParentFragment()).replaceFragment(fragment, false);
        }
    });

    return v;
}

Tab #1 的主类

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    myPrefs = this.getActivity().getSharedPreferences("getLogin", Context.MODE_PRIVATE);
    idUser = myPrefs.getInt("idUser", 0);

    d(TAG, "idUser: " + idUser);
    /*
    Map<String,?> keys = myPrefs.getAll();

    for(Map.Entry<String,?> entry : keys.entrySet()){
        Log.d("map values",entry.getKey() + ": " +
                entry.getValue().toString());
    }
    */
    context = getActivity();
    pDialog = new SweetAlertDialog(context, PROGRESS_TYPE);

    // Check if Internet present
    if (!isOnline(context)) {
        // Internet Connection is not present
        makeText(context, "Error en la conexion de Internet",
                LENGTH_LONG).show();
        // stop executing code by return
        return;
    }

    Bundle bundle = this.getArguments();
    idBankAccount = Integer.parseInt(bundle.getString(FragmentCardHolder.TAG_ACCOUNT_BANKACCOUNTS_ID, "0"));
    idGiftCard = Integer.parseInt(bundle.getString(FragmentCardHolder.TAG_ACCOUNT_GIFTCARDS_ID, "0"));

    if(idBankAccount > 0){
        new asyncGetBankTransactions(context).execute();
    } else if(idGiftCard > 0) {
        new asyncGetGiftCardTransactions(context).execute();
    } else {
        new asyncGetX111Transactions(context).execute();
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.activity_account, container, false);

    toolbar = (Toolbar) v.findViewById(id.toolbar);
    TextView mTitle = (TextView) toolbar.findViewById(toolbar_title);
    mTitle.setText("MI CUENTA");
    toolbar.setNavigationIcon(R.drawable.icon_user);
    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            goToCards();
        }
    });

    layoutAccount = (LinearLayout) v.findViewById(id.layoutAccount);
    layoutGetCredit = (LinearLayout) v.findViewById(id.layoutGetCredit);
    layoutTransactions = (LinearLayout) v.findViewById(id.layoutTransactions);

    btnAccount = (Button) v.findViewById(id.btnMyBalance);
    btnGetCredit = (Button) v.findViewById(id.btnGetCredit);
    btnSendCredit = (Button) v.findViewById(id.btnSendCredit);
    btnTransactions = (Button) v.findViewById(id.btnTransactions);

    list = (ListView) v.findViewById(id.list);

    btnTransactions.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            layoutAccount.setVisibility(View.GONE);
            layoutGetCredit.setVisibility(View.GONE);
            layoutTransactions.setVisibility(View.VISIBLE);
        }
    });

    btnGetCredit.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            layoutAccount.setVisibility(View.GONE);
            layoutGetCredit.setVisibility(View.VISIBLE);
            layoutTransactions.setVisibility(View.GONE);
        }
    });

    btnAccount.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            layoutAccount.setVisibility(View.VISIBLE);
            layoutGetCredit.setVisibility(View.GONE);
            layoutTransactions.setVisibility(View.GONE);
        }
    });

    return v;
}

private void goToCards() {
    FragmentCardHolder fragment = new FragmentCardHolder();
    ((BaseContainerFragment) getParentFragment()).replaceFragment(fragment, true);
}

【问题讨论】:

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


    【解决方案1】:

    我认为问题出在代码的隐藏部分,您将第一个片段添加到容器(FragmentAccountContainer 和 FragmentPromotionsContainer 类)。我建议您在 BaseContainerFragment.class 中创建抽象方法并通过示例签名 protected abstract Fragment getFirstFragment(); 因此具体的容器类将覆盖此方法并将第一个片段的新实例返回给超类,然后在父类中使用添加事务将其添加到片段容器中。

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            addFragment(getFirstFragment(), false);
        }
    }
    

    请注意,您应该在添加片段之前检查 savedInstanceState 是否为空,以避免在系统重新创建活动时出现重复。 在嵌套片段中,您可以像使用替换一样使用 ((BaseContainerFragment) getParentFragment()).replaceFragment(___, true);

    另外我对你的代码有一些建议。由于known bug with default back logic and child fragment manager,您不能像@NecipAllef 建议的那样避免在活动中覆盖onBackPressed,但是您可以像

    那样简化对popFragment 的调用
    @Override
    public void onBackPressed() {
        String currentTabTag = mTabHost.getCurrentTabTag();
        boolean isPopFragment = ((BaseContainerFragment) getSupportFragmentManager().findFragmentByTag(currentTabTag)).popFragment();
        if (!isPopFragment) {
            super.onBackPressed();
        }
    }
    

    对于将捆绑包设置为片段,我建议使用结构方法模式,例如

    public class TestFragment extends Fragment {
        public static Fragment newInstance(String text){
            Fragment fragment = new TestFragment();
            Bundle args = new Bundle();
            args.putString("text", text);
            fragment.setArguments(args);
            return fragment;
        }
    }
    

    Ps:我为你创建了一个 simple project 并描述了逻辑

    【讨论】:

    • 我刚刚回到这个项目,给你的答案一个很好的外观,直到最后一部分调用新片段,我说我在 TestFragment 中,我应该如何调用新片段片段 TestFragment2?
    【解决方案2】:

    您为什么要跟踪 Fragments 并自己弹出它们?您不需要这样做,也不应覆盖 onBackPressed()。让 FragmentManager 处理片段事务。

    如果您在活动中包含片段,请使用

    FragmentManager fManager = getFragmentManager();
    

    或者如果您想支持 Android 3.0 之前的设备,请使用

    FragmentManager fManager = getSupportFragmentManager();
    

    如果片段在另一个片段中,则使用

    FragmentManager fManager = getChildFragmentManager();
    

    拥有 fManager 后,要显示片段,请使用

    fManager.beginTransaction().add(R.id.fragment_parent, new FirstTabFragment()).commit();
    

    fragment_parent 是要放置片段的父视图。

    当你想切换到下一个片段时,使用

    fManager.beginTransaction().replace(R.id.fragment_parent, new SecondTabFragment())
                               .addToBackStack(null)
                               .commit();
    

    由于您将它添加到后台堆栈,当您按下返回时,您将看到您的第一个片段。而已。

    此外,由于您很容易意识到这会导致您的片段每次都从头开始创建,您可以通过初始化它们一次并重用它们来防止这种情况。

    HTH

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多