1

I have MainActivity which has FragmentTabHost with several tabs. Each fragment in tab can be replaced with another fragment, so if we navigate back, we will see first displayed fragment for this tab (own stack for each tab). I have a quite working solution.

The below example demonstrates TabHost with 2 tabs and fragment classes for the first tab.

Is there any simpler, better or more elegant way to achieve this result?

AbstractPrimaryFragment.java. This class is a root fragment class that replaces fragments inside it. Other tab fragment classes can extend this superclass.

public abstract class AbstractPrimaryFragment extends Fragment {

// Simple framelayout.
private static final int RES_ID = R.layout.primary_fragment_layout;

protected static final int CONTENT_LAYOUT_ID = R.id.primary_fragment_layout;

protected Fragment mActiveFragment;

public AbstractPrimaryFragment()
{
    setRetainInstance(true);
}

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

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

    // Check if active fragment is in layout, if not, make default fragment for this tab.
    mActiveFragment = getChildFragmentManager().findFragmentById(CONTENT_LAYOUT_ID);
    if (mActiveFragment == null)
    {
        mActiveFragment = makeDefaultActiveFragment();
        String tag = getDefaultFragmentTag();
        getChildFragmentManager().beginTransaction().add(CONTENT_LAYOUT_ID, mActiveFragment, tag).commit();
    }
}

public boolean onBackPressed()
{
    boolean backPressed = false;
    final FragmentManager fragmentManager = getChildFragmentManager();
    if (fragmentManager.getBackStackEntryCount() > 0)
    {
        fragmentManager.addOnBackStackChangedListener(new OnBackStackChangedListener()
        {
            @Override
            public void onBackStackChanged()
            {
                mActiveFragment = fragmentManager.findFragmentById(CONTENT_LAYOUT_ID);
                fragmentManager.removeOnBackStackChangedListener(this);
            }
        });
        fragmentManager.popBackStack();
        backPressed = true;
    }

    return backPressed;
}

protected abstract Fragment makeDefaultActiveFragment();

protected abstract String getDefaultFragmentTag(); }

Tab1PrimaryFragment.java

public class Tab1PrimaryFragment extends AbstractPrimaryFragment implements OnTab1Fragment1Listener {

private static final String FRAGMENT1_TAG = "tab1_fragment1";
private static final String FRAGMENT2_TAG = "tab2_fragment2";

@Override
protected Fragment makeDefaultActiveFragment()
{
    return new Tab1Fragment1();
}

@Override
protected String getDefaultFragmentTag()
{
    return FRAGMENT1_TAG;
}

@Override
public void onTab1Fragment1ButtonClick(Tab1Fragment1 tab1Fragment1)
{
    Tab1Fragment2 tab1Fragment2 = new Tab1Fragment2();
    getChildFragmentManager().beginTransaction().replace(CONTENT_LAYOUT_ID, tab1Fragment2, FRAGMENT2_TAG).addToBackStack(tab1Fragment1.getTag()).commit();
    mActiveFragment = tab1Fragment2;
}}

Tab1Fragment1.class (default active fragment)

public class Tab1Fragment1 extends Fragment {

public interface OnTab1Fragment1Listener
{
    public void onTab1Fragment1ButtonClick(Tab1Fragment1 tab1Fragment1);
}

private OnTab1Fragment1Listener mOnTab1Fragment1Listener;

public void setOnTab1Fragment1Listener(OnTab1Fragment1Listener onTab1Fragment1Listener)
{
    mOnTab1Fragment1Listener = onTab1Fragment1Listener;
}


@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    Fragment parentFragment = getParentFragment();
    if (parentFragment != null && parentFragment instanceof OnTab1Fragment1Listener)
    {
        mOnTab1Fragment1Listener = (OnTab1Fragment1Listener) parentFragment;
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    Button button = new Button(getActivity());
    button.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View v)
            {   
                if(mOnTab1Fragment1Listener != null)
                {
                   mOnTab1Fragment1Listener.onTab1Fragment1ButtonClick(Tab1Fragment1.this);
                }
            }
        });
    return button; }}

Tab1Fragment2.java. Dummy fragment. This fragment is displayed when onTab1Fragment1ButtonClick is called.

public class Tab1Fragment2 extends Fragment {}

And MainActivity.java

public class MainActivity extends FragmentActivity {
private static final int RES_ID = R.layout.main_activity;
private static final int TAB_CONTENT_ID = android.R.id.tabcontent;
private static final int TABHOST_ID = android.R.id.tabhost;

private static final String TAB1_PRIMARY_FRAGMENT_TAG = "tab1_primary_fragment";
private static final String TAB2_PRIMARY_FRAGMENT_TAG = "tab2_primary_fragment"

private FragmentTabHost mTabHost;

@Override
protected void onCreate(Bundle bundle)
{
    super.onCreate(bundle);

    setContentView(RES_ID);
    initializeTabHost();
}

private void initializeTabHost()
{
    mTabHost = (FragmentTabHost) findViewById(TABHOST_ID);
    mTabHost.setup(this, getSupportFragmentManager(), TAB_CONTENT_ID);
    LayoutInflater inflater = LayoutInflater.from(this);
    mTabHost.addTab(mTabHost.newTabSpec(TAB1_PRIMARY_FRAGMENT_TAG).setIndicator(inflater.inflate(R.layout.smth1, null)), Tab1PrimaryFragment.class, null);
    mTabHost.addTab(mTabHost.newTabSpec(TAB2_PRIMARY_FRAGMENT_TAG).setIndicator(inflater.inflate(R.layout.smth2, null)), Tab2PrimaryFragment.class, null); 
}

@Override
public void onBackPressed()
{
    Fragment fragment = getSupportFragmentManager().findFragmentById(TAB_CONTENT_ID);
    if (fragment != null && fragment instanceof AbstractPrimaryFragment)
    {
        if (((AbstractPrimaryFragment) fragment).onBackPressed())
        {
            return;
        }
    }

    super.onBackPressed();
}}
Alexander
  • 35
  • 4

0 Answers0