Search code examples
androidandroid-fragmentsandroid-appcompatandroid-tabs

Android fragment transaction with SlidingTabLayout not working in API level < 21


in my app I have an ActionBarActivity (I'm using support library with AppCompat) that uses the SlidingTabLayout class from Google (taken from here). So this is the XML code of the activity's layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_series_details"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SeriesDetailsActivity">

    <com.my.package.SlidingTabLayout
        android:id="@+id/series_details_tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:elevation="2dp"
        android:background="@color/primary_material_dark" />
    <android.support.v4.view.ViewPager
        android:id="@+id/series_details_pager"
        android:layout_height="0dp"
        android:layout_width="match_parent"
        android:layout_weight="1" />
</LinearLayout>

In this activty, when user press an option in the action bar, I want to add a Fragment with a custom animation. This is the code that handle menu click:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        /* ... OTHER CASES ... */
        case R.id.menu_voption:
            newFragment = MyNewFragment.newInstance();                
            getSupportFragmentManager().beginTransaction()
                    .setCustomAnimations(
                            R.anim.slide_up,
                            R.anim.slide_down
                    )
                    .add(R.id.activity_series_details, newFragment)
                    .commit();
            editing = true;
            break;
        default:
            return super.onOptionsItemSelected(item);
    }
    return true;

Doing this, my new fragment is correctly added to the activty and replace the currente fragment but not tab layout, tha remains visible. So I've tryed to add this line before start transaction:

tabsHost.setVisibility(View.GONE);

where tabsHost is the SlidingTabLayout. With this modification, the tabs layout disappear and the new fragment is correctly shown, but only in the API Level >= 21. In my Samsung Galaxy S4 (that runs API 19) and in all other emulators with lesser API level than 21 (my target is 11+), the tabs layout disappear but new fragment is not visible. I'm pretty sure is my fault, but I can't figure why. Thanks all for attention.


Solution

  • Since the SlidingTabLayout is not a fragment, it cannot be managed by the FragmentManager. You would have to make it part of a fragment and add it to your Activity. This is possible with getChildFragmentManager.

    Move your activity layout to a fragment:

    activity_main.xml

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_series_details"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>
    

    fragment_sliding_tab.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_series_details"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <com.my.package.SlidingTabLayout
            android:id="@+id/series_details_tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:elevation="2dp"
            android:background="@color/primary_material_dark" />
        <android.support.v4.view.ViewPager
            android:id="@+id/series_details_pager"
            android:layout_height="0dp"
            android:layout_width="match_parent"
            android:layout_weight="1" />
    </LinearLayout>
    

    SlidingTabFragment.java

    public class SlidingTabFragment extends Fragment {
        private PagerAdapter mPagerAdapter;
        private ViewPager mViewPager;
    
        public static SlidingTabFragment newInstance() {
            SlidingTabFragment fragment = new SlidingTabFragment();
            return fragment;
        }
    
        public SlidingTabFragment() {
            // Required empty public constructor
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
        }
    
        @Override
        public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
    
            mPagerAdapter = new PagerAdapter(getChildFragmentManager());
    
            // Set up the ViewPager with the sections adapter.
            mViewPager = (ViewPager) view.findViewById(R.id.series_details_pager);
            mViewPager.setAdapter(mSectionsPagerAdapter);
    
            SlidingTabLayout tabs = (SlidingTabLayout) view.findViewById(R.id.series_details_tabs);
            tabs.setViewPager(mViewPager);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            return inflater.inflate(R.layout.fragment_sliding_tab, container, false);
        }
    }
    

    Add your fragment in your Activity's onCreate:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Fragment slidingTabFragment = SlidingTabFragment.newInstance();
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.activity_series_details, slidingTabFragment).commit();
    }