Android fragments Android:ActionBar、TabListener和support.v4.Fragment

Android fragments Android:ActionBar、TabListener和support.v4.Fragment,android-fragments,android-actionbar,android-tabs,Android Fragments,Android Actionbar,Android Tabs,我正在用MainActivity构建一个应用程序,它扩展了FragmentActivity,并有一个带有三个选项卡的操作栏。在每个选项卡上,我想附加一个ParentFragment,它应该控制内部页面之间的滑动。结果应该是,按下选项卡,用户应该从ParentFragment的不同实例中进行更改,并在每个ParentFragment内的TextViewFragments中进行切换 现在我可以在三个选项卡之间完美切换,但问题是ParentFragment没有正确显示,它似乎甚至没有创建,因为我甚至看

我正在用
MainActivity
构建一个应用程序,它扩展了
FragmentActivity
,并有一个带有三个选项卡的操作栏。在每个选项卡上,我想附加一个
ParentFragment
,它应该控制内部页面之间的滑动。结果应该是,按下选项卡,用户应该从
ParentFragment
的不同实例中进行更改,并在每个
ParentFragment
内的
TextViewFragments
中进行切换
现在我可以在三个选项卡之间完美切换,但问题是
ParentFragment
没有正确显示,它似乎甚至没有创建,因为我甚至看不到LogCat视图中的
onCreate()
onCreateView()
onViewCreated()
函数。
我认为问题在于自定义TablListener类及其函数,但我不能真正理解问题是什么。我试着在许多网站上搜索,我已经研究了很多例子,但没有一个与相同的情况相关。
我错过了什么,或者我做错了什么

这是我的主要活动:

    import java.util.Random;
    import android.app.ActionBar;
    import android.app.ActionBar.Tab;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.app.FragmentTransaction;
    import android.support.v4.view.ViewPager;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    import android.widget.Toast;
    import com.viewpagerindicator.PageIndicator;

public class MainActivity extends FragmentActivity {

    MyAdapter mAdapter;
    ViewPager mPager;
    PageIndicator mIndicator;    
    private View mCustomView; 
    private static final Random RANDOM = new Random();

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

        // Set up the action bar.
        ActionBar.LayoutParams params = new ActionBar.LayoutParams(
                ActionBar.LayoutParams.MATCH_PARENT,
                ActionBar.LayoutParams.MATCH_PARENT, Gravity.CENTER);
        final ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setDisplayUseLogoEnabled(false);
        actionBar.setDisplayShowHomeEnabled(false);


            actionBar.addTab(actionBar
                    .newTab()
                    .setIcon(getIcon(0, true))
                    .setTabListener(
                            new TabListener<ParentFragment>(this, "home",
                                    ParentFragment.class)));

            actionBar.addTab(actionBar
                    .newTab()
                    .setIcon(getIcon(1, false))
                    .setTabListener(
                            new TabListener<ParentFragment>(this, "apps",
                                    ParentFragment.class)));

            actionBar.addTab(actionBar
                    .newTab()
                    .setIcon(getIcon(2, false))
                    .setTabListener(
                            new TabListener<ParentFragment>(this, "settings",
                                    ParentFragment.class)));

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

    }


    public static class TabListener<T extends Fragment> implements
            ActionBar.TabListener {

        private Fragment mFragment;
        private final FragmentActivity mActivity;
        private final String mTag;
        private final Class<T> mClass;
        private final Bundle mArgs;
        private FragmentTransaction fft;
            public static final String TAG = TabListener.class.getSimpleName();

        public TabListener(FragmentActivity activity, String tag, Class<T> clz) {

            this(activity, tag, clz, null);
        }

        public TabListener(FragmentActivity activity, String tag, Class<T> clz,
                Bundle args) {

            mActivity = activity;
            mTag = tag;
            mClass = clz;
            mArgs = args;

            mFragment = mActivity.getSupportFragmentManager()
                    .findFragmentByTag(mTag);
            if (mFragment != null && !mFragment.isDetached()) {

                fft = mActivity.getSupportFragmentManager().beginTransaction();
                fft.detach(mFragment);
                fft.commit();
            }
        }

        public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {

            System.out.println(TAG + (" - ") + " -> mTag "
                    + mTag + " selected!");
            fft = mActivity.getSupportFragmentManager().beginTransaction();

            if (mFragment == null) {
                mFragment = Fragment.instantiate(mActivity, mClass.getName());

                fft.add(android.R.id.content, mFragment, mTag);

            } else {
                System.out.println(TAG + (" - ") + " -> Fragment con mTag = " + mTag
                        + " trovato con tag!");
                fft.attach(mFragment);
                fft.commit();
            }
        }

        @Override
        public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {

        }

        @Override
        public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {

            mFragment = mActivity.getSupportFragmentManager()
                    .findFragmentByTag(mTag);
            System.out.println(TAG + (" - ") + " -> mTag "
                    + mTag + " unselected!");

            if (mFragment != null && !mFragment.isDetached()) {
                fft = mActivity.getSupportFragmentManager().beginTransaction();
                fft.detach(mFragment);
                fft.commit();
            }
        }

    }

    public Drawable getIcon(int tabPosition, boolean selected) {

        switch (tabPosition) {
        case 0:
            return getResources().getDrawable(R.drawable.actionbar_home);

        case 1:
            return getResources().getDrawable(R.drawable.actionbar_apps);

        case 2:
            return getResources().getDrawable(R.drawable.actionbar_settings);

        }
        return null;
    }

}
这是MyAdapter类:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import com.viewpagerindicator.IconPagerAdapter;

public class MyAdapter extends PagerAdapter  {

    FragmentManager myFragmentMgr;
    private FragmentTransaction mCurTransaction;

    protected static final String[] CONTENT = new String[] { "This", "Is", "A", "Test", };
    protected static final int[] ICONS = new int[] {
            R.drawable.icon_page_indicator,
            R.drawable.icon_page_indicator,
            R.drawable.icon_page_indicator,
            R.drawable.perm_group_calendar,
            R.drawable.perm_group_camera,
            R.drawable.perm_group_device_alarms,
            R.drawable.perm_group_location
    };

    private int mCount = CONTENT.length;

    public MyAdapter(FragmentManager fm) {
        super();
        myFragmentMgr = fm;
    }

    @Override
    public int getCount() {

        return 3;
    }

    @Override
    public Object instantiateItem(ViewGroup viewGroup, int position) {

        ParentFragment fragment = ParentFragment.newInstance(); 
        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup viewGroup, int position, Object obj) {

        if (mCurTransaction == null) {
            mCurTransaction = myFragmentMgr.beginTransaction();
        }
        mCurTransaction.detach((Fragment)obj);
    }   

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return false;
    }

    public Fragment getItem(int position) {
        Bundle args = new Bundle();
        args.putInt(TextViewFragment.POSITION_KEY, position);
        return TextViewFragment.newInstance(args);
    }

    @Override
    public CharSequence getPageTitle(int position) {

        return "Fragment # " + position;
    }

    public int getIconResId(int index) {

        return ICONS[index % ICONS.length];
    }

     public void setCount(int count) {
            if (count > 0 && count <= 10) {
                mCount = count;
                notifyDataSetChanged();
            }
        } 
}
----编辑:解决方案---

我不能回答我自己的问题,因为“低声誉”,但无论如何,我分享解决方案,以帮助其他人,并希望恢复一些选票

我终于找到了让事情为我工作的方法,我希望这能对其他遇到同样问题的人有所帮助。 正如我所怀疑的,问题出在TabListener上。我的问题已解决,使用以下代码更改该部分:

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

    public TabListener(FragmentActivity activity, String tag, Class<T> clz) {

        this(activity, tag, clz, null);
    }

    public TabListener(FragmentActivity activity, String tag, Class<T> clz,
            Bundle args) {

        mActivity = activity;
        mTag = tag;
        mClass = clz;
        mArgs = args;

        System.out.println(TAG + " - " + methodName() + " - Constructor of TabListener -> mTag = "
                + mTag);
        // 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.getSupportFragmentManager()
                .findFragmentByTag(mTag);
        if (mFragment != null && !mFragment.isDetached()) {

            fft = mActivity.getSupportFragmentManager().beginTransaction();
            fft.detach(mFragment);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        }
    }

    public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {

        Fragment tmp = mActivity.getSupportFragmentManager()
                .findFragmentByTag(mTag);

        fft = mActivity.getSupportFragmentManager().beginTransaction();

        if (mFragment == null) {

            System.out.println(TAG + " - " + methodName() + " - add mFragment " + mTag);
            // If not, instantiate and add it to the activity
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            fft.add(android.R.id.content, mFragment, mTag);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        } else {
            System.out.println(TAG + " - " + methodName() + " - attach mFragment " + mTag);
            // If it exists, simply attach it in order to show it
            fft.attach(mFragment);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        }
    }

    @Override
    public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {
        System.out.println(TAG + " - " + methodName() + " - mFragment " + mTag);

    }

    @Override
    public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {

        mFragment = mActivity.getSupportFragmentManager()
                .findFragmentByTag(mTag);

        if (mFragment != null && !mFragment.isDetached()) {
            System.out.println(TAG + " - " + methodName() + " - detach mFragment " + mTag);
            fft = mActivity.getSupportFragmentManager().beginTransaction();
            fft.detach(mFragment);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        }
    }



    public static final String TAG = TabListener.class.getSimpleName();
    private static final int CLIENT_CODE_STACK_INDEX;

    static {
        // Finds out the index of "this code" in the returned stack trace -
        // funny but it differs in JDK 1.5 and 1.6
        int i = 0;
        for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
            i++;
            if (ste.getClassName().equals(TabListener.class.getName())) {
                break;
            }
        }
        CLIENT_CODE_STACK_INDEX = i;
    }

    public static String methodName() {

        if (Thread.currentThread().getStackTrace().length < CLIENT_CODE_STACK_INDEX)
            return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX]
                    .getMethodName() + "()";
        else
            return new String(
                    "methodName() - stackTrace index is out of bound");
    }
}

此问题的文档记录非常糟糕,可能仅在特定情况下才会发生,但我希望此解决方案能为其他有相同问题的人节省一些时间

感谢您的回答,我在支持库中遇到了完全相同的问题,当我尝试在选项卡之间切换时,片段将相互重叠。解决方案中有几个未使用的变量,因此我对其进行了一些清理:

public static class TabListener<T extends Fragment> implements ActionBar.TabListener {

  private Fragment mFragment;
  private final FragmentActivity mActivity;
  private final String mTag;
  private final Class<T> mClass;
  private FragmentTransaction fft;

  public TabListener(FragmentActivity activity, String tag, Class<T> clz) {

      mActivity = activity;
      mTag = tag;
      mClass = clz;

      // 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.getSupportFragmentManager().findFragmentByTag(mTag);
      if (mFragment != null && !mFragment.isDetached()) {

          fft = mActivity.getSupportFragmentManager().beginTransaction();
          fft.detach(mFragment);
          fft.commit();
          mActivity.getSupportFragmentManager()
          .executePendingTransactions();
      }
  }

  @Override
  public void onTabSelected(Tab tab, FragmentTransaction ft) {

      mFragment = mActivity.getSupportFragmentManager().findFragmentByTag(mTag);
      fft = mActivity.getSupportFragmentManager().beginTransaction();

      if (mFragment == null) {

          // If not, instantiate and add it to the activity
          mFragment = Fragment.instantiate(mActivity, mClass.getName());
          ft.add(R.id.content_view, mFragment, mTag);
          //fft.add(android.R.id.content, mFragment, mTag);
          fft.commit();
          mActivity.getSupportFragmentManager().executePendingTransactions();
      } else {

          // If it exists, simply attach it in order to show it
          fft.attach(mFragment);
          fft.commit();
          mActivity.getSupportFragmentManager().executePendingTransactions();
      }
  }

  @Override
  public void onTabReselected(Tab tab, FragmentTransaction ft) {

  }

  @Override
  public void onTabUnselected(Tab tab, FragmentTransaction ft) {

      mFragment = mActivity.getSupportFragmentManager().findFragmentByTag(mTag);

      if (mFragment != null && !mFragment.isDetached()) {
          fft = mActivity.getSupportFragmentManager().beginTransaction();
          fft.detach(mFragment);
          fft.commit();
          mActivity.getSupportFragmentManager().executePendingTransactions();
      }
  }
公共静态类TabListener实现ActionBar.TabListener{
私人碎片;
私人最终碎片活动;
私有最终字符串mTag;
私人期末班;
私人碎片交易;
公共TabListener(FragmentActivity活动、字符串标记、类clz){
活动性=活动性;
mTag=标签;
mClass=clz;
//检查一下,看看我们是否已经有了这个标签的一个片段,可能吧
//从以前保存的状态。如果是,请将其停用,因为
//初始状态是不显示选项卡。
MFFragment=mActivity.getSupportFragmentManager().findFragmentByTag(mTag);
if(mffragment!=null&&!mffragment.isDetached()){
fft=mActivity.getSupportFragmentManager().beginTransaction();
fft.分离(mFragment);
fft.commit();
mActivity.getSupportFragmentManager()
.executePendingTransactions();
}
}
@凌驾
已选择的公共事务(选项卡,碎片事务ft){
MFFragment=mActivity.getSupportFragmentManager().findFragmentByTag(mTag);
fft=mActivity.getSupportFragmentManager().beginTransaction();
if(mFragment==null){
//如果不是,则实例化并将其添加到活动中
MFFragment=Fragment.instantiate(mActivity,mClass.getName());
ft.add(R.id.content_视图、mFragment、mTag);
//fft.add(android.R.id.content、mFragment、mTag);
fft.commit();
mActivity.getSupportFragmentManager().executePendingTransactions();
}否则{
//如果存在,只需将其附加以显示即可
fft.attach(mFragment);
fft.commit();
mActivity.getSupportFragmentManager().executePendingTransactions();
}
}
@凌驾
已重新选择公共无效页签(页签,碎片事务){
}
@凌驾
已选择公共空页(选项卡,碎片事务ft){
MFFragment=mActivity.getSupportFragmentManager().findFragmentByTag(mTag);
if(mffragment!=null&&!mffragment.isDetached()){
fft=mActivity.getSupportFragmentManager().beginTransaction();
fft.分离(mFragment);
fft.commit();
mActivity.getSupportFragmentManager().executePendingTransactions();
}
}

}

在我的例子中,添加
executependingtransactions
引发递归错误。无论如何,我在没有调用的情况下使用了你的代码,它成功了。警告:在这些回调中,你不能为片段事务调用commit()。系统会为你调用它,如果你自己调用它,它可能会抛出异常。您也不能将这些片段事务添加到后台堆栈中,
commit
上没有任何异常吗?
   public static class TabListener<T extends Fragment> implements
            ActionBar.TabListener {
    private Fragment mFragment;
    private final FragmentActivity mActivity;
    private final String mTag;
    private final Class<T> mClass;
    private final Bundle mArgs;
    private FragmentTransaction fft;

    public TabListener(FragmentActivity activity, String tag, Class<T> clz) {

        this(activity, tag, clz, null);
    }

    public TabListener(FragmentActivity activity, String tag, Class<T> clz,
            Bundle args) {

        mActivity = activity;
        mTag = tag;
        mClass = clz;
        mArgs = args;

        System.out.println(TAG + " - " + methodName() + " - Constructor of TabListener -> mTag = "
                + mTag);
        // 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.getSupportFragmentManager()
                .findFragmentByTag(mTag);
        if (mFragment != null && !mFragment.isDetached()) {

            fft = mActivity.getSupportFragmentManager().beginTransaction();
            fft.detach(mFragment);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        }
    }

    public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {

        Fragment tmp = mActivity.getSupportFragmentManager()
                .findFragmentByTag(mTag);

        fft = mActivity.getSupportFragmentManager().beginTransaction();

        if (mFragment == null) {

            System.out.println(TAG + " - " + methodName() + " - add mFragment " + mTag);
            // If not, instantiate and add it to the activity
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            fft.add(android.R.id.content, mFragment, mTag);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        } else {
            System.out.println(TAG + " - " + methodName() + " - attach mFragment " + mTag);
            // If it exists, simply attach it in order to show it
            fft.attach(mFragment);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        }
    }

    @Override
    public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {
        System.out.println(TAG + " - " + methodName() + " - mFragment " + mTag);

    }

    @Override
    public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {

        mFragment = mActivity.getSupportFragmentManager()
                .findFragmentByTag(mTag);

        if (mFragment != null && !mFragment.isDetached()) {
            System.out.println(TAG + " - " + methodName() + " - detach mFragment " + mTag);
            fft = mActivity.getSupportFragmentManager().beginTransaction();
            fft.detach(mFragment);
            fft.commit();
            mActivity.getSupportFragmentManager()
                    .executePendingTransactions();
        }
    }



    public static final String TAG = TabListener.class.getSimpleName();
    private static final int CLIENT_CODE_STACK_INDEX;

    static {
        // Finds out the index of "this code" in the returned stack trace -
        // funny but it differs in JDK 1.5 and 1.6
        int i = 0;
        for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
            i++;
            if (ste.getClassName().equals(TabListener.class.getName())) {
                break;
            }
        }
        CLIENT_CODE_STACK_INDEX = i;
    }

    public static String methodName() {

        if (Thread.currentThread().getStackTrace().length < CLIENT_CODE_STACK_INDEX)
            return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX]
                    .getMethodName() + "()";
        else
            return new String(
                    "methodName() - stackTrace index is out of bound");
    }
}
mActivity.getSupportFragmentManager().executePendingTransactions();
public static class TabListener<T extends Fragment> implements ActionBar.TabListener {

  private Fragment mFragment;
  private final FragmentActivity mActivity;
  private final String mTag;
  private final Class<T> mClass;
  private FragmentTransaction fft;

  public TabListener(FragmentActivity activity, String tag, Class<T> clz) {

      mActivity = activity;
      mTag = tag;
      mClass = clz;

      // 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.getSupportFragmentManager().findFragmentByTag(mTag);
      if (mFragment != null && !mFragment.isDetached()) {

          fft = mActivity.getSupportFragmentManager().beginTransaction();
          fft.detach(mFragment);
          fft.commit();
          mActivity.getSupportFragmentManager()
          .executePendingTransactions();
      }
  }

  @Override
  public void onTabSelected(Tab tab, FragmentTransaction ft) {

      mFragment = mActivity.getSupportFragmentManager().findFragmentByTag(mTag);
      fft = mActivity.getSupportFragmentManager().beginTransaction();

      if (mFragment == null) {

          // If not, instantiate and add it to the activity
          mFragment = Fragment.instantiate(mActivity, mClass.getName());
          ft.add(R.id.content_view, mFragment, mTag);
          //fft.add(android.R.id.content, mFragment, mTag);
          fft.commit();
          mActivity.getSupportFragmentManager().executePendingTransactions();
      } else {

          // If it exists, simply attach it in order to show it
          fft.attach(mFragment);
          fft.commit();
          mActivity.getSupportFragmentManager().executePendingTransactions();
      }
  }

  @Override
  public void onTabReselected(Tab tab, FragmentTransaction ft) {

  }

  @Override
  public void onTabUnselected(Tab tab, FragmentTransaction ft) {

      mFragment = mActivity.getSupportFragmentManager().findFragmentByTag(mTag);

      if (mFragment != null && !mFragment.isDetached()) {
          fft = mActivity.getSupportFragmentManager().beginTransaction();
          fft.detach(mFragment);
          fft.commit();
          mActivity.getSupportFragmentManager().executePendingTransactions();
      }
  }