I am MainActivity application with MainActivity that extends FragmentActivity and has an ActionBar with three tabs. On each tab, I would like to add a ParentFragment that should control the swipe among the inner pages. The result should be that clicking the tabs that the user needs to change from different instances of the ParentFragment , and scrolling, it should change among the TextViewFragments inside each ParentFragment .
Now I can switch between the three tabs perfectly, but the problem is that the ParentFragment not display correctly, it seems that it has not even been created, because I do not even see the functions onCreate() , onCreateView() and onViewCreated() in the LogCat view.
I think the problem lies in the TabListener custom class and its functions, but I cannot figure out what the problem is. I tried to search many sites, and I looked at a lot of examples, but none of them were related to the same situation. What am I missing or what am I doing wrong here?
This is my MainActivity:
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; } }
And this is my ParentFragment, which now extends the android.support.v4.app.Fragment class:
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); } }
This is the MyAdapter class:
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(); } } }
and the last TextViewFragment class:
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(); } }); } }
----- EDIT: SOLUTION -----
I canโt answer my question because of the โlow reputationโ, but I still share the decision to help someone else and hopefully restore some voices.
I finally found a way to make me work, I hope this can be useful to everyone who is experiencing the same problem. As I suspected, the problem was in TabListener. My problem was solved with changing this part with this code:
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);
The main difference was adding the following line after each commit() :
mActivity.getSupportFragmentManager().executePendingTransactions();
This problem was really poorly documented and probably only occurs under certain conditions, but I hope this solution saves time when someone else has the same problems!