Search code examples
androidandroid-layoutandroid-fragmentsandroid-viewpagerandroid-tabhost

Fragment dont show content of TabHost in second time


Well... I'm working with fragments, android.support.v4.widget.DrawerLayout, TabHost and ViewPager ... I have the following code:

main_base.xml

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

<ListView
        android:id="@+id/listado_pintado"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#fff"/>

my Activity:

Main_Activity

package com.examples.planets;

import android.annotation.SuppressLint;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TabHost;

import com.examples.planets.TabsFragmentos;
import com.examples.planets.fragmentos.mercury.TabFragmentDescribeMercury;
import com.examples.planets.fragmentos.mercury.TabFragmentShowMercury;
import com.examples.planets.paginadores.AdaptadorDePaginas;
import com.examples.planets.utilidades.enums.Menu_;

import java.util.HashMap;
import java.util.List;
import java.util.Vector;

public class Main_Activity extends FragmentActivity{


    public DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mAccionadorDelDrawer;

    private CharSequence mDrawerTitulo;
    private CharSequence mTitulo;
    private String[] menuPrincipal;


    public void cargarMenu(){
        //Titulo
        mTitulo = mDrawerTitulo = getTitle();

        //Main_Activity Principal
        menuPrincipal = getResources().getStringArray(R.array.menu_principal_array);

        //Diseñador del Layout
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);


        mDrawerList = (ListView) findViewById(R.id.listado_pintado);


        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);


        mDrawerList.setAdapter(new ArrayAdapter<String>(this,
                R.layout.menu_listado, menuPrincipal));


        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());


        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        mAccionadorDelDrawer = new ActionBarDrawerToggle(
                this,                  /* host Activity */
                mDrawerLayout,         /* DrawerLayout object */
                R.drawable.ic_drawer,  /* Imagen del Accionador del menu */
                R.string.drawer_open,  /* "open drawer" description for accessibility */
                R.string.drawer_close  /* "close drawer" description for accessibility */
        ) {
            public void onDrawerClosed(View view) {
                getActionBar().setTitle(mTitulo);
                invalidateOptionsMenu();
            }

            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(mDrawerTitulo);
                invalidateOptionsMenu();
            }
        };
        mDrawerLayout.setDrawerListener(mAccionadorDelDrawer);
    }

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

        cargarMenu();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        //inflater.inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }


    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content view
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        //menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        if (mAccionadorDelDrawer.onOptionsItemSelected(item)) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            selectItem(position);
        }
    }


    private void selectItem(int position) {
        android.support.v4.app.FragmentManager manager = super.getSupportFragmentManager();
        TabsFragmentos firstFragment = new TabsFragmentos(position, this, super.getSupportFragmentManager());
        manager.beginTransaction()
                .replace(R.id.content_frame, firstFragment).commit();


        mDrawerList.setItemChecked(position, true);
        setTitle(menuPrincipal[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
        //cargarMenu();
    }

    @Override
    public void setTitle(CharSequence title) {
        mTitulo = title;
        getActionBar().setTitle(mTitulo);
    }

    /**
     * Cuando usamos el ActionBarDrawerToggle, se debería llamar este durante el
     * onPostCreate() y el onConfigurationChanged()...
     */

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        onRestoreInstanceState.
        mAccionadorDelDrawer.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mAccionadorDelDrawer.onConfigurationChanged(newConfig);
    }



}

And the TabFragments is Fragment:

package com.examples.planets.fragmentos;


import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import android.annotation.SuppressLint;
import android.content.Context;
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.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TabHost.TabContentFactory;

....

/**
 * @author roldan
 *
 */
@SuppressLint("ValidFragment")
public class TabsFragmentos extends Fragment implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {

    private TabHost mTabHost;
    private HashMap<String, TabInfo> mapTabInfo = new HashMap<String, TabInfo>();
    private TabInfo mLastTab = null;
    private AdaptadorDePaginas mAdaptadorPaginas;
    private ViewPager mViewPager;


    private int posicion;
    private FragmentManager supportFragmentManager;
    private static Menu_Principal menu_principal;

    public static TabsFragmentos newInstance() {
        return new TabsFragmentos();
    }


    public TabsFragmentos(){

    }

    public TabsFragmentos(int position, Menu_Principal menu_principal, FragmentManager supportFragmentManager) {
        this.posicion = position;
        this.menu_principal = menu_principal;
        this.supportFragmentManager = supportFragmentManager;
    }

    /**
     *
     * @author mwho
     *
     */
    private class TabInfo {
         private String tag;
         private Class<?> clss;
         private Bundle args;
         private android.support.v4.app.Fragment fragment;
         TabInfo(String tag, Class<?> clazz, Bundle args) {
             this.tag = tag;
             this.clss = clazz;
             this.args = args;
         }

    }
    /**
     *
     * @author mwho
     *
     */
    class TabFactory implements TabContentFactory {

        private final Context mContext;

        /**
         * @param context
         */
        public TabFactory(Context context) {
            mContext = context;
        }

        /** (non-Javadoc)
         * @see android.widget.TabHost.TabContentFactory#createTabContent(String)
         */
        public View createTabContent(String tag) {
            View v = new View(mContext);
            v.setMinimumWidth(0);
            v.setMinimumHeight(0);
            return v;
        }

    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //int posicion = getArguments().getInt(ARGUMENTO_);

        super.onCreate(savedInstanceState);

        if (savedInstanceState != null) {
            mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); //set the tab as per the saved state
        }

        View rootView = null;
        if (Menu_.MERCURY.getPosicion()== posicion){
            //rootView = inflater.inflate(R.layout.fragmento_palabra_bk, container, false);
            rootView = inflater.inflate(R.layout.fragmentos_base, container, false);



            initialiseTabHost(rootView, savedInstanceState);

            intialiseViewPager(rootView);

        }
        return rootView;
    }

    /** (non-Javadoc)
     * @see android.support.v4.app.FragmentActivity#onSaveInstanceState(android.os.Bundle)
     */
    public void onSaveInstanceState(Bundle outState) {
        outState.putString("tab", mTabHost.getCurrentTabTag()); //save the tab selected
        super.onSaveInstanceState(outState);
    }

    /**
     * Initializando el TabHost
     */
    private void initialiseTabHost(View rootView, Bundle args) {
        mTabHost = (TabHost)rootView.findViewById(android.R.id.tabhost);
        //mTabHost = (TabHost)findViewById(android.R.id.tabhost);

        mTabHost.setup();
        TabInfo tabInfo = null;
        TabsFragmentos.addTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab2").setIndicator("Buscar"), ( tabInfo = new TabInfo("Tab1", TabFragmentOne.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);
        TabsFragmentos.addTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab1").setIndicator("Crear"), ( tabInfo = new TabInfo("Tab2", TabFragmentTwo.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);

        // Default to first tab
        this.onTabChanged("Tab1");
        mTabHost.setOnTabChangedListener(this);
    }

    private void intialiseViewPager(View rootView) {


        List<android.support.v4.app.Fragment> fragments = new Vector<android.support.v4.app.Fragment>();
        fragments.add(android.support.v4.app.Fragment.instantiate(menu_principal, TabFragmentOne.class.getName()));
        fragments.add(android.support.v4.app.Fragment.instantiate(menu_principal, TabFragmentTwo.class.getName()));

        this.mAdaptadorPaginas  = new AdaptadorDePaginas(supportFragmentManager, fragments);
        //
        this.mViewPager = (ViewPager)rootView.findViewById(R.id.tabviewpager);
        this.mViewPager.setAdapter(this.mAdaptadorPaginas);
        this.mViewPager.setOnPageChangeListener(this);
    }

    /**
     * @param activity
     * @param tabHost
     * @param tabSpec
     */
    private static void addTab(TabsFragmentos activity, TabHost tabHost, TabHost.TabSpec tabSpec, TabInfo tabInfo) {
        // Attach a Tab view factory to the spec
        tabSpec.setContent(activity.new TabFactory(menu_principal));
        String tag = tabSpec.getTag();

        // 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.
        if (tabInfo.fragment != null && !tabInfo.fragment.isDetached()) {
            FragmentTransaction ft = menu_principal.getSupportFragmentManager().beginTransaction();
            ft.detach(tabInfo.fragment);
            ft.commit();
            menu_principal.getSupportFragmentManager().executePendingTransactions();
        }

        tabHost.addTab(tabSpec);
    }

    public void onTabChanged(String tag) {
        try{
        //TabInfo newTab = this.mapTabInfo.get(tag);
        int pos = this.mTabHost.getCurrentTab();
        this.mViewPager.setCurrentItem(pos);
        }catch(Exception e){}
    }

    @Override
    public void onPageScrolled(int i, float v, int i2) {

    }

    @Override
    public void onPageSelected(int position) {
        // TODO Auto-generated method stub
        this.mTabHost.setCurrentTab(position);
    }

    @Override
    public void onPageScrollStateChanged(int i) {

    }


}

whats problem?

the code is working fine the first time... only pressed any option and show the tabs with yours layout associate to the TabFragmentOne or TabFragmentTwo fragments! the second time, this code only show the tabs but dont show the layout associate to the TabFragmentOne or TabFragmentTwo fragments!

what should I do?

Thx 4 advance.


Solution

  • For me, the problem was in my TabsAdapter. The single constructor looked like this:

    public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
        super(activity.getSupportFragmentManager());
        mContext = activity;
        mTabHost = tabHost;
        mViewPager = pager;
        mTabHost.setOnTabChangedListener(this);
        mViewPager.setAdapter(this);
        mViewPager.setOnPageChangeListener(this);
    }
    

    It's calling getSupportFragmentManager which returns the FragmentManager associated with our FragmentActivity. Bad. We need the FM that our current Fragment manages. Creating an alternate (overloaded) constructor that used getChildFragmentManager did the trick.

    public TabsAdapter(Fragment fragment, TabHost tabHost, ViewPager pager) {
        super(fragment.getChildFragmentManager());
        mContext = fragment.getActivity();
        mTabHost = tabHost;
        mViewPager = pager;
        mTabHost.setOnTabChangedListener(this);
        mViewPager.setAdapter(this);
        mViewPager.setOnPageChangeListener(this);
    }
    

    Your problem stems from the same exact issue, just in a different format. Replace your calls to getSupportFragmentManager with getChildFragmentManager in your Fragment.