HoangVu
HoangVu

Reputation: 33

How to put Tablayout with ViewPager inside a fragment which is belong to a navigation drawer

I am trying to develop an app that has a navigation drawer and inside one of the fragments of that drawer I want to put a Tablayout with ViewPager in it. Everything seem to work fine but there is a problem. Here is my navigation drawer:

enter image description here

When I first start the app, it show me the home fragment with 3 tabs in it like this.

enter image description here

Each tab has only one text in it. The first tab has "search", 2nd tab has "cart" and 3rd tab has "history". When I switch to another fragment of the navigation and switch back to home, I realized the word "search" in 1st tab is not showing up.

enter image description here

I swiped to the 2nd tab and the same thing happened but the 3rd tab still show the word "history". I swiped back to 1st tab and the word "search" is shown but the word in 2nd tab is never shown again despite how many times I swipe back and forth.

So I decided to put Log.d() inside of the method onCreate and onCreateView for every tab fragment to see what is going on. When the app first open, it show home fragment with 3 tabs like I said before but only the onCreate and onCreateView of the 1st and 2nd tab was invoked. When I swipe to second tab, onCreate and onCreateView of 3rd tab is invoked. I swipe to 3rd tab and nothing happen, but when I swipe back to 2nd tab from 3rd tab, onCreateView of 1st tab is invoked.

After that I switch to another fragment of navigation drawer and switch back to home. None of the onCreate and onCreateView method of any tab is invoked so nothing show up. I swipe to 2nd tab, still nothing. But when I swipe to 3rd tab, method onCreate and onCreateView is invoked and the word "history" show up. I swipe back to 2nd tab, onCreateView of 1st tab is invoked instead of 2nd tab so there is nothing on 2nd tab then I swipe to 1st tab, the word "search" show up, no method is invoked. After that, each time I when I swipe from 1st tab to 2nd tab, onCreateView of 3rd tab is invoked and when I swipe from 3rd tab to 2nd tab, onCreateView of 1st tab is invoked. I don't know what cause this behaviour, please help me. Here are the codes:

Navigation drawer Activity:

package activity;
import android.os.Handler;
import android.support.design.widget.NavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;

import com.example.hoangvu.vbuy.R;

import fragment.HomeFragment;
import fragment.ProfileFragment;
import fragment.SettingFragment;
public class NavigationDrawerActivity extends AppCompatActivity {

private NavigationView navigationView;
private DrawerLayout drawer;
private View navHeader;
private Toolbar toolbar;


// index to identify current nav menu item
public static int navItemIndex = 0;

// tags used to attach the fragments
private static final String TAG_HOME = "home";
private static final String TAG_PROFILE = "profile";
private static final String TAG_SETTINGS = "settings";
public static String CURRENT_TAG = TAG_HOME;

// toolbar titles respected to selected nav menu item
private String[] activityTitles;
private Handler mHandler;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_navigation_drawer);
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    mHandler = new Handler();

    drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    navigationView = (NavigationView) findViewById(R.id.nav_view);

    // Navigation view header
    navHeader = navigationView.getHeaderView(0);

    // load toolbar titles from string resources
    activityTitles = getResources().getStringArray(R.array.nav_item_activity_titles);

    // initializing navigation menu
    setUpNavigationView();

    if (savedInstanceState == null) {
        navItemIndex = 0;
        CURRENT_TAG = TAG_HOME;
        loadHomeFragment();
    }
    }

    /***
    * Returns respected fragment that user
    * selected from navigation menu
    */
    private void loadHomeFragment() {
    // selecting appropriate nav menu item
    selectNavMenu();

    // set toolbar title
    setToolbarTitle();

    // if user select the current navigation menu again, don't do anything
    // just close the navigation drawer
    if (getSupportFragmentManager().findFragmentByTag(CURRENT_TAG) != null) {
        drawer.closeDrawers();
        return;
    }

    // Sometimes, when fragment has huge data, screen seems hanging
    // when switching between navigation menus
    // So using runnable, the fragment is loaded with cross fade effect
    // This effect can be seen in GMail app
    Runnable mPendingRunnable = new Runnable() {
        @Override
        public void run() {
            // update the main content by replacing fragments
            Fragment fragment = getHomeFragment();
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.setCustomAnimations(android.R.anim.fade_in,
                    android.R.anim.fade_out);
            fragmentTransaction.replace(R.id.frame, fragment, CURRENT_TAG);
            fragmentTransaction.commitAllowingStateLoss();
        }
    };

    // If mPendingRunnable is not null, then add to the message queue
    if (mPendingRunnable != null) {
        mHandler.post(mPendingRunnable);
    }

    //Closing drawer on item click
    drawer.closeDrawers();

    // refresh toolbar menu
    invalidateOptionsMenu();
    }

    private Fragment getHomeFragment() {
        switch (navItemIndex) {
            case 0:
            // home
                HomeFragment homeFragment = new HomeFragment();
                return homeFragment;
            case 1:
            // Profile
                ProfileFragment profileFragment = new ProfileFragment();
                return profileFragment;
            case 2:
            // settings
                SettingFragment settingsFragment = new SettingFragment();
                return settingsFragment;
            default:
                return new HomeFragment();
        }
    }

    private void setToolbarTitle() {
        getSupportActionBar().setTitle(activityTitles[navItemIndex]);
    }

    private void selectNavMenu() {
        navigationView.getMenu().getItem(navItemIndex).setChecked(true);
    }

    private void setUpNavigationView() {
        //Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {

        // This method will trigger on item Click of navigation menu
        @Override
        public boolean onNavigationItemSelected(MenuItem menuItem) {

            //Check to see which item was being clicked and perform appropriate action
            switch (menuItem.getItemId()) {
                //Replacing the main content with ContentFragment Which is our Inbox View;
                case R.id.nav_home:
                    navItemIndex = 0;
                    CURRENT_TAG = TAG_HOME;
                    break;
                case R.id.nav_profile:
                    navItemIndex = 1;
                    CURRENT_TAG = TAG_PROFILE;
                    break;
                case R.id.nav_settings:
                    navItemIndex = 2;
                    CURRENT_TAG = TAG_SETTINGS;
                    break;
                default:
                    navItemIndex = 0;
            }

            //Checking if the item is in checked state or not, if not make it in checked state
            if (menuItem.isChecked()) {
                menuItem.setChecked(false);
            } else {
                menuItem.setChecked(true);
            }
            menuItem.setChecked(true);

            loadHomeFragment();

            return true;
        }
        });


        ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.openDrawer, R.string.closeDrawer) {

        @Override
        public void onDrawerClosed(View drawerView) {
            // Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
            super.onDrawerClosed(drawerView);
        }

        @Override
        public void onDrawerOpened(View drawerView) {
            // Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank
            super.onDrawerOpened(drawerView);
        }
        };

        //Setting the actionbarToggle to drawer layout
        drawer.addDrawerListener(actionBarDrawerToggle);

        //calling sync state is necessary or else your hamburger icon wont show up
        actionBarDrawerToggle.syncState();
      }
      }

activity_navigation_drawer.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/top_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context="activity.NavigationDrawerActivity">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/MyToolBarTheme"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

</android.support.design.widget.AppBarLayout>

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <FrameLayout
        android:id="@+id/frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
    </FrameLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

 </android.support.v4.widget.DrawerLayout>
 </LinearLayout>

HomeFragment:

package fragment;

import android.content.Context;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.hoangvu.vbuy.R;

import java.util.ArrayList;
import java.util.List;


public class HomeFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";

// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;

private TabLayout tabLayout;
private ViewPager viewPager;
private int tabIcons[] = {R.drawable.ic_search_black_24dp,
                          R.drawable.ic_shopping_cart_black_24dp,
                          R.drawable.ic_receipt_black_24dp};
private OnFragmentInteractionListener mListener;

public HomeFragment() {
    // Required empty public constructor
}

/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 *
 * @param param1 Parameter 1.
 * @param param2 Parameter 2.
 * @return A new instance of fragment HomeFragment.
 */
// TODO: Rename and change types and number of parameters
public static HomeFragment newInstance(String param1, String param2) {
    HomeFragment fragment = new HomeFragment();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d("HomeFragment","onCreate");
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    Log.d("HomeFragment","onCreateView");
    View view = inflater.inflate(R.layout.fragment_home, container, false);
    viewPager = (ViewPager) view.findViewById(R.id.viewpager);
    setupViewPager(viewPager);

    tabLayout = (TabLayout) view.findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(viewPager);
    setupTabIcons();
    return view;
}
private void setupTabIcons() {
    tabLayout.getTabAt(0).setIcon(tabIcons[0]);
    tabLayout.getTabAt(1).setIcon(tabIcons[1]);
    tabLayout.getTabAt(2).setIcon(tabIcons[2]);

    tabLayout.getTabAt(0).getIcon().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
    tabLayout.getTabAt(1).getIcon().setColorFilter(Color.parseColor("#FFBFBFBF"), PorterDuff.Mode.SRC_IN);
    tabLayout.getTabAt(2).getIcon().setColorFilter(Color.parseColor("#FFBFBFBF"), PorterDuff.Mode.SRC_IN);

    tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            tab.getIcon().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);

        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
            tab.getIcon().setColorFilter(Color.parseColor("#FFBFBFBF"), PorterDuff.Mode.SRC_IN);
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });
}
private void setupViewPager(ViewPager viewPager) {
    ViewPagerAdapter adapter = new ViewPagerAdapter(getActivity().getSupportFragmentManager());
    adapter.addFrag(new SearchFragment(), "ONE");
    adapter.addFrag(new CartFragment(), "TWO");
    adapter.addFrag(new BuyHistoryFragment(), "THREE");
    viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFrag(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return null;
    }
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}
@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

/**
 * This interface must be implemented by activities that contain this
 * fragment to allow an interaction in this fragment to be communicated
 * to the activity and potentially other fragments contained in that
 * activity.
 * <p>
 * See the Android Training lesson <a href=
 * "http://developer.android.com/training/basics/fragments/communicating.html"
 * >Communicating with Other Fragments</a> for more information.
 */
}

SearchFragment(this is fragment for 1st tab, the code for 2 remain tabs are also like this):

package fragment;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.hoangvu.vbuy.R;


public class SearchFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";

// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;

private OnFragmentInteractionListener mListener;

public SearchFragment() {
    // Required empty public constructor
}

/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 *
 * @param param1 Parameter 1.
 * @param param2 Parameter 2.
 * @return A new instance of fragment SearchFragment2.
 */
// TODO: Rename and change types and number of parameters
public static SearchFragment2 newInstance(String param1, String param2) {
    SearchFragment fragment = new SearchFragment();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d("SearchFragment","onCreate");
    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    Log.d("SearchFragment","onCreateView");
    return inflater.inflate(R.layout.fragment_search, container, false);
}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}


@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

}

fragment_search.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="fragment.SearchFragment2">

<!-- TODO: Update blank fragment layout -->
<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="Search" />

</FrameLayout>

Upvotes: 2

Views: 2515

Answers (1)

MatnazaroFF
MatnazaroFF

Reputation: 21

I also had such a mistake.
Use getChildFragmentManager() instead of getActivity().getSupportFragmentManager()

Upvotes: 2

Related Questions