【问题标题】:Assigning Fragments to tabs in the ActionBar with different orientations将片段分配给具有不同方向的 ActionBar 中的选项卡
【发布时间】:2015-03-18 14:47:16
【问题描述】:

我有 3 个片段和一个活动。我想启用 ActionBar 上的选项卡,并为 3 个选项卡中的每一个分配一个 Fragment。如何正确连接?

原帖

我正在开发一个应用,使用 Google I/O 应用作为指南。我已经在ActionBar 中实现了标签。他们似乎一直在工作,直到平板电脑的方向发生变化。例如,所有 3 个选项卡都有一个 Fragment。我可以在它们之间切换就好了,但是当我改变方向时,无论我上次查看的Fragment 保持可见,但单击选项卡不再改变视图......就像它们已断开连接一样。正如预期的那样,回到原来的方向并不能“修复”它。

我已经研究过保存和恢复状态,但我不知道这些会有什么帮助。

编辑

模块级别:

Fragment mFragmentA = (Fragment) new AFragmentTab();
Fragment mFragmentB = (Fragment) new BFragmentTab();
Fragment mFragmentC = (Fragment) new CFragmentTab();

我在活动的onCreate中有这样的东西:

ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);

ActionBar.Tab tabA = actionBar.newTab().setText("text a");
ActionBar.Tab tabB = actionBar.newTab().setText("text b");
ActionBar.Tab tabC = actionBar.newTab().setText("text c");

tabA.setTabListener(this);
tabB.setTabListener(this);
tabC.setTabListener(this);

actionBar.addTab(tabA);
actionBar.addTab(tabB);
actionBar.addTab(tabC);

还有一个像这样的TabListener

编辑已删除

class MyTabListener implements ActionBar.TabListener {
    private Fragment mFragment;

    // Called to create an instance of the listener when adding a new tab
    public MyTabListener(Fragment fragment) {
        mFragment = fragment;
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        ft.add(R.id.fragment_content, mFragment, null);
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(mFragment);
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // do nothing
    }
}

编辑

我已经移动了TabListener。我不是一个单独的类,而是在Activity 上实现TabListener。然后在 SelectedUnselected 方法上我有类似的东西:

public void onTabSelected(Tab tab, FragmentTransaction ft) {
    switch (tab.getPosition()) {
    case 0:
        ft.add(R.id.fragment_content, mFragmentA, null);
        break;
    case 1:
        ft.add(R.id.fragment_content, mFragmentB, null);
        break;
    case 2:
        ft.add(R.id.fragment_content, mFragmentC, null);
        break;
    }
}

public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    switch (tab.getPosition()) {
    case 0:
        ft.remove(mFragmentA);
        break;
    case 1:
        ft.remove(mFragmentB);
        break;
    case 2:
        ft.remove(mFragmentC);
        break;
    }
}

它仍然在做同样的事情。我真的不知道发生了什么。

【问题讨论】:

  • 可以告诉我你为此使用了什么解决方案..我面临同样的问题..

标签: android tabs android-actionbar orientation-changes


【解决方案1】:

看来我的答案可以在这里找到:http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.html

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.example.android.apis.app;

import com.example.android.apis.R;


import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.widget.Toast;

/**
 * This demonstrates the use of action bar tabs and how they interact
 * with other action bar features.
 */
public class FragmentTabs extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final ActionBar bar = getActionBar();
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);

        bar.addTab(bar.newTab()
                .setText("Simple")
                .setTabListener(new TabListener<FragmentStack.CountingFragment>(
                        this, "simple", FragmentStack.CountingFragment.class)));
        bar.addTab(bar.newTab()
                .setText("Contacts")
                .setTabListener(new TabListener<LoaderCursor.CursorLoaderListFragment>(
                        this, "contacts", LoaderCursor.CursorLoaderListFragment.class)));
        bar.addTab(bar.newTab()
                .setText("Apps")
                .setTabListener(new TabListener<LoaderCustom.AppListFragment>(
                        this, "apps", LoaderCustom.AppListFragment.class)));
        bar.addTab(bar.newTab()
                .setText("Throttle")
                .setTabListener(new TabListener<LoaderThrottle.ThrottledLoaderListFragment>(
                        this, "throttle", LoaderThrottle.ThrottledLoaderListFragment.class)));

        if (savedInstanceState != null) {
            bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
    }

    public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
        private final Activity mActivity;
        private final String mTag;
        private final Class<T> mClass;
        private final Bundle mArgs;
        private Fragment mFragment;

        public TabListener(Activity activity, String tag, Class<T> clz) {
            this(activity, tag, clz, null);
        }

        public TabListener(Activity activity, String tag, Class<T> clz, Bundle args) {
            mActivity = activity;
            mTag = tag;
            mClass = clz;
            mArgs = args;

            // Check to see if we already have a fragment for this tab, probably
            // from a previously saved state.  If so, deactivate it, because our
            // initial state is that a tab isn't shown.
            mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
            if (mFragment != null && !mFragment.isDetached()) {
                FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
                ft.hide(mFragment);
                ft.commit();
            }
        }

        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            if (mFragment == null) {
                mFragment = Fragment.instantiate(mActivity, mClass.getName(), mArgs);
                ft.add(android.R.id.content, mFragment, mTag);
            } else {
                ft.show(mFragment);
            }
        }

        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            if (mFragment != null) {
                ft.hide(mFragment);
            }
        }

        public void onTabReselected(Tab tab, FragmentTransaction ft) {
            Toast.makeText(mActivity, "Reselected!", Toast.LENGTH_SHORT).show();
        }
    }
}

【讨论】:

  • 感觉你需要更新你的链接,或者只在这里提供一些可靠的解决方案。那会更有帮助。谢谢。
  • 这太棒了!我不知何故错过了在构造函数中分离片段
  • 分离将关闭要重新加载的片段,而不是仅仅出现在它的最后状态。改用 hide!
  • 这真的行不通,抱歉。明确地因为 TabListener 的构造函数中的“if (mFragment != null)...”行,当方向发生变化时,已保存的可见片段的实例状态被丢弃!它们将被分离并再次连接 - 失去它们的 savedInstanceState!
  • @AlikElzin-kilaka 我同意你的看法。如果您将附加更改为“显示”并将分离更改为“隐藏”,它会完美运行。片段不会重新创建!
【解决方案2】:

@Metallicraft 提供的链接已经失效,所以这里对那些仍然偶然发现这篇文章的人提供一些帮助。转到here 以获取有关实现选项卡的帮助。

要查看/阅读原始示例,如果您安装了 android 开发环境,您可以转到以下文件夹:android-sdk\samples\android-14\ApiDemos\src\com\example\android\apis\app\FragmentTabs.java

此外,如果在方向更改后片段重叠存在问题,则它与传递的已保存实例状态正确相关。这是来自google tutorial 的复制粘贴,它解释了片段重叠问题以及如何避免它:

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_articles);

        // Check that the activity is using the layout version with
        // the fragment_container FrameLayout
        if (findViewById(R.id.fragment_container) != null) {

            // However, if we're being restored from a previous state,
            // then we don't need to do anything and should return or else
            // we could end up with overlapping fragments.
            if (savedInstanceState != null) {
                return;
            }

            // Create an instance of ExampleFragment
            HeadlinesFragment firstFragment = new HeadlinesFragment();

            // In case this activity was started with special instructions from an Intent,
            // pass the Intent's extras to the fragment as arguments
            firstFragment.setArguments(getIntent().getExtras());

            // Add the fragment to the 'fragment_container' FrameLayout
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, firstFragment).commit();
        }
    }
}

【讨论】:

  • 当 savedInstanceState != null 为我工作时返回 null \O/
【解决方案3】:

创建一个新的 Android 示例项目,选择 Support4Demos 示例。您会在那里找到 FragmentTabs 示例。

【讨论】:

    【解决方案4】:

    我或多或少遇到了同样的问题,但上面介绍的解决方案似乎不适用于我的情况。最终我找到了以下解决方案:

        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            if (mFragment == null) {
                mFragment = Fragment.instantiate(mActivity, mClass.getName());
                ft.replace(android.R.id.content, mFragment, mTag); // Use replace iso add
            }
            else {
                ft.attach(mFragment);
            }
        }
    

    【讨论】:

      【解决方案5】:

      这对我来说非常有用!我遇到了这个问题,每次我更改标签时活动都会重叠:

              mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
              if (mFragment != null && !mFragment.isDetached()) {
                  FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
                  ft.detach(mFragment);
                  ft.commit();
      

      再次感谢!

      【讨论】:

        【解决方案6】:
                @Override
                public void onTabSelected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction fragmentTransaction) {
                    // Check if the fragment is already initialized
        
                    if (mFragment == null) {
                        // If not, instantiate and add it to the activity
                       // Toast.makeText(getApplicationContext(),"TAb "+tab.getPosition(),Toast.LENGTH_LONG).show();
                        if(tab.getPosition() == 1) {
                           mFragment = new HolderFragment();
                            fragmentTransaction.add(android.R.id.content, mFragment, mTag);
                        }
                        else if(tab.getPosition() == 0)
                        {
                            mFragment = new FragmentKnowledge();
                            fragmentTransaction.add(android.R.id.c`enter code here`ontent, mFragment, mTag);
        
                        }
                        /*else
                        {
        
                             mFragment = Fragment.instantiate(mActivity, mClass.getName());
                            fragmentTransaction.add(android.R.id.content, mFragment, mTag);
                        }
        */
                    } else {
                        // If it exists, simply attach it in order to show it
                        fragmentTransaction.attach(mFragment);
                    }
                }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-02-29
          • 2011-12-24
          • 1970-01-01
          • 2012-02-09
          • 1970-01-01
          • 1970-01-01
          • 2023-03-09
          • 2012-10-27
          相关资源
          最近更新 更多