Rahul
Rahul

Reputation: 381

How to keep selected tab in TabLayout remain selected when returned from another fragment in android?

Here is the screen shot of my app

enter image description here

The app contains an activity which contains a FrameLayout and four buttons at the bottom.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <LinearLayout
        android:id="@+id/layoutParent"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_gravity="bottom"
        android:orientation="horizontal">
        <Button
            android:id="@+id/fragmentOne"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:clickable="true"
            android:gravity="center"
            android:textColor="@color/selector_task_bar_text"
            android:background="@drawable/selector_tab_layout_bg"
            android:layout_weight="1"
            android:text="One"/>
        <Button
            android:id="@+id/fragmentTwo"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:clickable="true"
            android:gravity="center"
            android:textColor="@color/selector_task_bar_text"
            android:background="@drawable/selector_tab_layout_bg"
            android:layout_weight="1"
            android:text="Two"/>
        <Button
            android:id="@+id/fragmentThree"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:clickable="true"
            android:gravity="center"
            android:textColor="@color/selector_task_bar_text"
            android:background="@drawable/selector_tab_layout_bg"
            android:layout_weight="1"
            android:text="Three"/>
        <Button
            android:id="@+id/fragmentFour"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:clickable="true"
            android:gravity="center"
            android:textColor="@color/selector_task_bar_text"
            android:background="@drawable/selector_tab_layout_bg"
            android:layout_weight="1"
            android:text="Four"/>
    </LinearLayout>

</LinearLayout>

At each of the button click the activity adds a fragment to the FrameLayout(for the time being I'm using only one fragment class named ContentFragment).

The fragments contain a TabLayout and a ViewPager as follows

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.design.widget.TabLayout
        android:id="@+id/tabs_sub"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/CustomTabLayout" />
    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

The ViewPager has three items which shows different items on swiping or selecting on the tabs in the TabLayout. Currently I've added this layout for all the pages in the ViewPager

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textInfo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/app_name"
android:textSize="20sp"/>

Now what i need to do is when a user selects a particular button in the bottom(ONE, TWO, THREE, FOUR) and a particular tab from the top, and then switch to any other button, then when he goes back to the previously selected button he should find the TabLayout tab remain selected for that button.

For examples:

  1. User selects button ONE and ViewPager tab 1
  2. User goes to button THREE and selects tab 2.
  3. User comes back to button ONE, should find ViewPager tab 1 remain selected.
  4. Goes to button THREE, should find tab 2 remain selected.

How can this be done?

Here is my MainActivity

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = MainActivity.class.getSimpleName();
    private TextView fragmentOneButton;
    private TextView fragmentTwoButton;
    private TextView fragmentThreeButton;
    private TextView fragmentFourButton;

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

    private void initLayout() {
        fragmentOneButton = (TextView) findViewById(R.id.fragmentOne);
        fragmentTwoButton = (TextView) findViewById(R.id.fragmentTwo);
        fragmentThreeButton = (TextView) findViewById(R.id.fragmentThree);
        fragmentFourButton = (TextView) findViewById(R.id.fragmentFour);

        fragmentOneButton.setOnClickListener(this);
        fragmentTwoButton.setOnClickListener(this);
        fragmentThreeButton.setOnClickListener(this);
        fragmentFourButton.setOnClickListener(this);

        if (getSupportFragmentManager().findFragmentById(R.id.fragment_container) == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container,
            ContentFragment.newInstance(1,"TabOne")).commit();
        }
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.fragmentOne:
                getSupportFragmentManager().beginTransaction()
                        .replace(R.id.fragment_container, ContentFragment.newInstance(1,"TabOne")).commit();
                break;
            case R.id.fragmentTwo:
                getSupportFragmentManager().beginTransaction()
                        .replace(R.id.fragment_container, ContentFragment.newInstance(2,"TabTwo")).commit();
                break;
            case R.id.fragmentThree:
                getSupportFragmentManager().beginTransaction()
                        .replace(R.id.fragment_container, ContentFragment.newInstance(3,"TabThree")).commit();
                break;
            case R.id.fragmentFour:
                getSupportFragmentManager().beginTransaction()
                        .replace(R.id.fragment_container, ContentFragment.newInstance(4,"TabFour")).commit();
                break;
            default:
                break;
        }
    }
}

ContentFragment

    public class ContentFragment extends android.support.v4.app.Fragment {
    private static final String TAG = ContentFragment.class.getSimpleName();
    private int mName = 0;
    private ViewPager mFragmentsPager;
    private TabLayout       mFragmentsTab;
    private PagerAdapter pagerAdapter;
    private String tabName = "";

    public static ContentFragment newInstance(int position,String tabName) {
        ContentFragment contentFragment = new ContentFragment();
        Bundle bundle = new Bundle();
        bundle.putString("TAB_NAME",tabName);
        bundle.putInt("KEY_POSITION",position);
        contentFragment.setArguments(bundle);
        return contentFragment;
    }

    public ContentFragment(){}

    @Override
    public void onAttachFragment(Fragment childFragment) {
        super.onAttachFragment(childFragment);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.main_frag,container,false);

        final int position = getArguments().getInt("KEY_POSITION");
        tabName = getArguments().getString("TAB_NAME");

        initViews(view,position);

        return view;
    }

    private void initViews(View view, int position) {
        mName = position;

        mFragmentsPager = (ViewPager) view.findViewById(R.id.viewPager);
        mFragmentsPager.setOffscreenPageLimit(1);

        pagerAdapter = new FragmentStateAdapter(getChildFragmentManager());

        mFragmentsPager.setOffscreenPageLimit(3);
        mFragmentsPager.setAdapter(pagerAdapter);

        mFragmentsTab = (TabLayout) view.findViewById(R.id.tabs_sub);
        mFragmentsTab.setupWithViewPager(mFragmentsPager,false);

    }

    private class FragmentStateAdapter extends FragmentStatePagerAdapter {
        public FragmentStateAdapter(FragmentManager fragmentManager) {
            super(fragmentManager);
        }

        @Override
        public Fragment instantiateFragment(int position) {
            if (getFragment(position)!=null) {
                return getFragment(position);
            } else {
                return ViewPagerContentFragment.newInstance(position,tabName);
            }

        }

        @Override
        public int getCount() {
            return 3;
        }

        public CharSequence getPageTitle(int position) {
            return String.valueOf(position);
        }


        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            super.destroyItem(container, position, object);
        }
    }
}

ViewPagerContentFragment

    public class ViewPagerContentFragment extends 
android.support.v4.app.Fragment {
    private static final String TAG = ViewPagerContentFragment.class.getSimpleName();
    private TextView showOtherButton;

    public static ViewPagerContentFragment newInstance(int position,String tabName) {
        ViewPagerContentFragment contentFragment = new ViewPagerContentFragment();
        Bundle bundle = new Bundle();
        bundle.putInt("KEY_POSITION",position);
        bundle.putString("TAB_NAME",tabName);
        contentFragment.setArguments(bundle);
        return contentFragment;
    }

    public ViewPagerContentFragment(){}

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

        View view = inflater.inflate(R.layout.pager_content,container,false);

        final int position = getArguments().getInt("KEY_POSITION");
        final String tabName = getArguments().getString("TAB_NAME");

        showOtherButton = (TextView) view.findViewById(R.id.textInfo);
        showOtherButton.setText(tabName+"\n"+position);
        showOtherButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });
        return view;
    }
}

I cannot replace the bottom bar with any other layout.

Upvotes: 2

Views: 3637

Answers (1)

Rahul
Rahul

Reputation: 381

This is how I solved it:

Created a Constant class with field to store the currently selected tab in each fragment added on click of the button in the bottom bar

    public class Constant {
    public static final Map<String,Integer> fragmentTabs = new HashMap<>();
}

And then in the ContentFragment class added these codes in initViews method.

    final Bundle bundle = getFragmentManager().findFragmentById(R.id.fragment_container).getArguments();
try {
    if (Constant.fragmentTabs.containsKey(bundle.getString("TAB_NAME"))) {
        mFragmentsTab.getTabAt(Constant.fragmentTabs.get(bundle.getString("TAB_NAME"))).select();
    }
} catch (NullPointerException e) {
    e.printStackTrace();
}


mFragmentsPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
        Constant.fragmentTabs.put(bundle.getString("TAB_NAME"),position);
    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }
});

Upvotes: 1

Related Questions