The previous article introduced using FragmenttabHost to use TAB navigation; By Android 5.0, TabLayout was available. Therefore, it is necessary to understand tabLayout.

Let’s start with MainActivity, which seems a bit much because it contains the toolbar code:

public class MainActivity extends AppCompatActivity {

    private TabLayout tabLayout;
    private ViewPager viewPager;
    private MyViewPagerAdapter adapter;

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

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        viewPager = (ViewPager) findViewById(R.id.pager);

        int s = 0;

        if (viewPager != null) {
            setupViewPager(viewPager);
        }
    }

    private void setupViewPager(ViewPager viewPager) {
        adapter = new MyViewPagerAdapter(getSupportFragmentManager(), this);
        adapter.addFragment(new TabFragment1().newInstance("Page1"), "Tab 1");
        adapter.addFragment(new TabFragment2().newInstance("Page2"), "Tab 2");
        adapter.addFragment(new TabFragment3().newInstance("Page3"), "Tab 3");
        viewPager.setAdapter(adapter);
        tabLayout.setupWithViewPager(viewPager);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
}
Copy the code

Initialize tabLayout and viewPager. Then create an instance of MyViewPagerAdapter and add fragments to it.

Let’s take a look at the mysterious MyViewPagerAdapter.

public class MyViewPagerAdapter extends FragmentStatePagerAdapter { private final List<Fragment> myFragments = new ArrayList<>(); private final List<String> myFragmentTitles = new ArrayList<>(); private Context context; public MyViewPagerAdapter(FragmentManager fm, Context context) { super(fm); this.context = context; } public void addFragment(Fragment fragment, String title) { myFragments.add(fragment); myFragmentTitles.add(title); } @Override public Fragment getItem(int position) { return myFragments.get(position); } @Override public int getCount() { return myFragments.size(); } @Override public CharSequence getPageTitle(int position) { return myFragmentTitles.get(position); }}Copy the code

Here we have overridden several of these methods: getItem, getCount, and getPageTitle. Can we transfer our quantity in this way?

Never mind, when we call the setAdapt, we’re actually passing the adapt into the ViewPager, and when we need to fetch a quantity, we just call this method.

TabLayout. SetupWithViewPager (viewPager) is the TAB with the ViewPage, so when change to change, together in TabLaout, You can get the adapt we just wore by using viewpager. getAdapt; So they both have the variable adapt.

public void setupWithViewPager(ViewPager viewPager) { PagerAdapter adapter = viewPager.getAdapter(); if(adapter == null) { throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set"); } else { this.setTabsFromPagerAdapter(adapter); viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(this)); this.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager)); }}Copy the code

Look at the source can be found that tabLayout and viewPager set each other or add listeners, so that either slide viewPager, or click TAB can realize the view switch, the two can be synchronized.

public static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {
        private final ViewPager mViewPager;

        public ViewPagerOnTabSelectedListener(ViewPager viewPager) {
            this.mViewPager = viewPager;
        }

        public void onTabSelected(TabLayout.Tab tab) {
            this.mViewPager.setCurrentItem(tab.getPosition());
        }

        public void onTabUnselected(TabLayout.Tab tab) {
        }

        public void onTabReselected(TabLayout.Tab tab) {
        }
    }
Copy the code

Can we see the ViewPagerOnTabSelectedListener concrete, find its implementation TabLayout. OnTabSelectedListener interface, in the constructor, the viewPager variables assigned to the internal variables, In this way, when a TAB is selected, obtain the position of the selected TAB, and then set the fragment to display the same position.

public static class TabLayoutOnPageChangeListener implements OnPageChangeListener {
        private final WeakReference<TabLayout> mTabLayoutRef;
        private int mScrollState;

        public TabLayoutOnPageChangeListener(TabLayout tabLayout) {
            this.mTabLayoutRef = new WeakReference(tabLayout);
        }

        public void onPageScrollStateChanged(int state) {
            this.mScrollState = state;
        }

        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            TabLayout tabLayout = (TabLayout)this.mTabLayoutRef.get();
            if(tabLayout != null) {
                tabLayout.setScrollPosition(position, positionOffset, this.mScrollState == 1);
            }

        }

        public void onPageSelected(int position) {
            TabLayout tabLayout = (TabLayout)this.mTabLayoutRef.get();
            if(tabLayout != null) {
                tabLayout.getTabAt(position).select();
            }

        }
    }
Copy the code

When you swipe the page back, onPageSelected, and pass in the pager currently selected, specify the corresponding TAB. So the two are in sync pretty well.

Let’s look at the layout file again:

<? The XML version = "1.0" encoding = "utf-8"? > <android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context=".MainActivity"> <android.support.design.widget.AppBarLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" app:layout_scrollFlags="scroll|enterAlways" /> <android.support.design.widget.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#eeeeee" app:tabTextColor="#888888" app:tabSelectedTextColor="#000000" app:tabGravity="fill" app:tabMode="fixed"/> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout>Copy the code

The layout file looks complicated because of the Toolbars, but it’s actually quite simple.

Simplified layout (id does not necessarily match, copy from other places) :

<? The XML version = "1.0" encoding = "utf-8"? > <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.design.widget.TabLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tabLayout" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:background="#cdc36e" app:tabMode="fixed" app:tabGravity="fill"/> <android.support.v4.view.ViewPager android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/viewPager" android:layout_below="@+id/tabLayout" android:layout_centerHorizontal="true" /> </RelativeLayout>Copy the code

For fragment files, see the layout in the previous article

FragmentTabHost Example

Or look directly at the source code location:

Github.com/huanshen/Le…