7

我正在构建一个应用程序,MainActivity它扩展FragmentActivity并具有一个带有三个选项卡的 ActionBar。在每个选项卡上,我想附上一个ParentFragment应该控制内部页面之间滑动的选项卡。结果应该是,用户应该从不同的实例中更改按标签,而在每个实例ParentFragment之间滑动他应该更改。 现在我可以完美地在三个选项卡之间切换,但问题是没有正确显示,似乎它甚至没有创建,因为我什至看不到LogCat 视图中的和功能。TextViewFragmentsParentFragment
ParentFragmentonCreate()onCreateView()onViewCreated()
我认为问题出在自定义 TabListener 类及其函数中,但我无法真正理解问题所在。我尝试在许多网站上进行搜索,并且查看了很多示例,但没有一个与相同情况有关。
我想念什么或我在这里做错了什么?

这是我的主要活动:

    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;
    }

}

这是我的 ParentFragment,它现在扩展了 android.support.v4.app.Fragment 类:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.viewpagerindicator.IconPageIndicator;
import com.viewpagerindicator.PageIndicator;

public class ParentFragment extends Fragment {

    public static final String TAG = ParentFragment.class.getSimpleName();

    MyAdapter fragmentAdapter;
    ViewPager mPager;
    PageIndicator mIndicator;



    public static ParentFragment newInstance() {
 System.out.println(TAG + " - newInstance()");
    System.out.println(TAG + " - " + methodName());
        ParentFragment fragment = new ParentFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
System.out.println(TAG + " - onCreate()");
        System.out.println(TAG + " - " + methodName());

        super.onCreate(savedInstanceState);
        setRetainInstance(true);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

System.out.println(TAG + " - onCreateView()");
        System.out.println(TAG + " - " + methodName());
        fragmentAdapter = new MyAdapter(getFragmentManager());

        View view = inflater.inflate(R.layout.simple_icons, container, false);
        mPager = (ViewPager) view.findViewById(R.id.pager);
        mPager.setAdapter(fragmentAdapter);

        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        System.out.println(TAG + " - onViewCreated()" );
        System.out.println(TAG + " - " + methodName());
        super.onViewCreated(view, savedInstanceState);

        mIndicator = (IconPageIndicator) getActivity().findViewById(R.id.indicator);
        mIndicator.setViewPager(mPager);          
    }
}

这是 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();
            }
        } 
}

最后一个 TextViewFragment 类:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

public class TextViewFragment extends Fragment {

    public static final String POSITION_KEY = "POSITION";
    public static final String TITLE_KEY = "TITLE";

    public static TextViewFragment newInstance(Bundle args) {
        TextViewFragment fragment = new TextViewFragment();
        fragment.setArguments(args);
        return fragment;
    }

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

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

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        TextView textview = (TextView) view.findViewById(R.id.textViewPosition);
        final int position;
        if (getArguments() != null) {
            position = getArguments().getInt(POSITION_KEY);
            textview.setText(Integer.toString(position));
        } else {
            position = 0;
            textview.setText("Child Fragment");
        }

        textview.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                Toast.makeText(v.getContext(), "Clicked Position: " + position,
                        Toast.LENGTH_LONG).show();
            }
        });
    }    
}

----- 编辑:解决方案 -----

由于“声誉低下”,我无法回答我自己的问题,但无论如何我都会分享解决方案,以帮助其他人并希望收回一些选票。

我终于找到了让事情对我有用的方法,我希望这对遇到同样问题的其他人有所帮助。正如我所怀疑的,问题出在 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");
    }
}

根本区别在于commit()以下每一行之后的添加:

mActivity.getSupportFragmentManager().executePendingTransactions();

这个问题的文档记录真的很差,可能只在特定条件下发生,但我希望这个解决方案可以为遇到同样问题的其他人节省一些时间!

4

1 回答 1

3

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

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();
      }
  }

}

于 2013-08-09T05:17:49.053 回答