This is the 15th day of my participation in the August Text Challenge.More challenges in August

TabLayout

    • The paper
    • A simple example
    • This section describes the TabLayout property
      • tabIndicatorFullWidth
      • tabRippleColor
      • tabTextAppearance
      • tabMode
      • tabIndicatorColor
      • tabIndicatorHeight
      • tabIndicatorGravity
    • Set an interval drawable for TabLayout

The paper

TabLayout Android is the support of a control Android. Support. The design. The widget. TabLayout, Google after upgrading the AndroidX, Will go to the com TabLayout migrated to material package below. Google. Android. Material. Tabs. TabLayout, under the original support TabLayout from 29 start will no longer maintain the API. So if your project has been upgraded to AndroidX, it’s recommended to go straight to the latter. TabLayout is generally used in combination with ViewPager+Fragment to implement a sliding TAB selector.

Like the news TAB switch



Take a look at the TabLayout inheritance, as shown below

Support package below



Material package below

TabLayout inherits the HorizontalScrollView, so it supports sliding left and right.

A simple example

activity_tab.xml


      
<androidx.constraintlayout.widget.ConstraintLayout 
	xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:tabTextColor="@color/colorPrimary"
        app:tabSelectedTextColor="@color/colorPrimaryDark"
        />
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tab_layout"
        />

</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code

ConstraintLayout Consists of a TabLayout and a ViewPager. The tabSelectedTextColor and tabTextColor properties set the text color of the selected and unselected TAB states, respectively. The other properties are explained later. TabFragment.java

public class TabFragment extends Fragment {
    public static TabFragment newInstance(String label) {
        Bundle args = new Bundle();
        args.putString("label", label);
        TabFragment fragment = new TabFragment();
        fragment.setArguments(args);
        return fragment;
    }
    
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab, container, false);
    }

    @Override
    public void onStart(a) {
        super.onStart();
        String label = getArguments().getString("label");
        TextView text = getView().findViewById(R.id.tv_bg);
        text.setText(label);
        text.setBackgroundColor(Color.rgb((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255))); }}Copy the code

A TabFragment contains only one TextView. Use different text and background colors for each Fragment to determine which TextView is currently in the Fragment. The Fragment layout file is as follows: fragment_tab.xml


      
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tv_bg"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:paddingTop="100dp"
    />
Copy the code

TabActivity.java

public class TabActivity extends AppCompatActivity {

    private String[] tabs = {"tab1"."tab2"."tab3"};
    private List<TabFragment> tabFragmentList = new ArrayList<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tab);
        TabLayout tabLayout = findViewById(R.id.tab_layout);
        ViewPager viewPager = findViewById(R.id.view_pager);
        / / add TAB
        for (int i = 0; i < tabs.length; i++) {
            tabLayout.addTab(tabLayout.newTab().setText(tabs[i]));
            tabFragmentList.add(TabFragment.newInstance(tabs[i]));
        }
        
        viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager(), FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
            @NonNull
            @Override
            public Fragment getItem(int position) {
                return tabFragmentList.get(position);
            }

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

            @Nullable
            @Override
            public CharSequence getPageTitle(int position) {
                returntabs[position]; }});// Set TabLayout and ViewPager linkage
        tabLayout.setupWithViewPager(viewPager,false); }}Copy the code

Simple 3 steps:

  1. Add a TAB for TabLayout
  2. Set adapter to ViewPager
  3. Set TabLayout and ViewPager linkage

Take a look at the results:



Ok, the basic functionality has been implemented. Here’s a caveat:

NewTab ().settext (tabs[I]) (tabs[I])) (tabs[I]) (tabs[I])) (tabs[I]) (tabs[I])) (tabs[I])) (tabs[I]) (tabs[I])) (tabs[I])) (tabs[I])) (tabs[I])) (tabs[I])) (tabs[I])) (tabs[I])) (tabs[I])) The reason is very simple, is in tabLayout setupWithViewPager, tabLayout put all tabs remove, and then take the PagerAdapter getPageTitle return value added in the TAB. Look at the source

@ViewPager.DecorView
public class TabLayout extends HorizontalScrollView {...private void setupWithViewPager(
	      @Nullable final ViewPager viewPager, boolean autoRefresh, boolean implicitSetup) {
		if(viewPager ! =null) {
			this.viewPager = viewPager; .final PagerAdapter adapter = viewPager.getAdapter();
	      	if(adapter ! =null) {
	        	// Now we'll populate ourselves from the pager adapter, adding an observer if
	        	// autoRefresh is enabledsetPagerAdapter(adapter, autoRefresh); }... }else {
	      // We've been given a null ViewPager so we need to clear out the internal state,
	      // listeners and observers
	      this.viewPager = null;
	      setPagerAdapter(null.false); }}void setPagerAdapter(@Nullable final PagerAdapter adapter, final boolean addObserver) {...// Finally make sure we reflect the new adapter
	    populateFromPagerAdapter();
	  }
	
	void populateFromPagerAdapter(a) {
	    removeAllTabs();
	
	    if(pagerAdapter ! =null) {
	      final int adapterCount = pagerAdapter.getCount();
	      for (int i = 0; i < adapterCount; i++) {
	        addTab(newTab().setText(pagerAdapter.getPageTitle(i)), false); }... }}... }Copy the code

Can see populateFromPagerAdapter method that executes removeAllTabs () method, and then take a pagerAdapter. GetPageTitle (I) method returns a value to add TAB, so remember to rewrite getPageTitle method. Instead of adding tabs dynamically in code, you can also add tabItems directly in XML.

<com.google.android.material.tabs.TabLayout
    android:id="@+id/tab_layout"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:tabTextColor="@color/grey"
    app:tabSelectedTextColor="@color/colorAccent"
    >
    <com.google.android.material.tabs.TabItem
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="tab1"/>
    <com.google.android.material.tabs.TabItem
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="tab2"/>
</com.google.android.material.tabs.TabLayout>
Copy the code

This section describes the TabLayout property

TabLayout has a number of properties that you can use. Here are a few.

tabIndicatorFullWidth

As you can see from the above results, the full width of the indicator fills the screen. Sometimes projects need the width of the indicator line to match the width of the text. Then you can set the tabIndicatorFullWidth property to false

tabRippleColor

By default, a gradient background color appears when each TAB is clicked



To remove the click background, set the tabRippleColor property to a transparent background color

<com.google.android.material.tabs.TabLayout
        .
        app:tabRippleColor="@android:color/transparent"/>
Copy the code

tabTextAppearance

In some cases, if the designer wants to make the selected TAB font bold and larger, but TabLayout does not set the font size and style directly, we can do this by setting a custom tabTextAppearance, whose value is a custom style.

<style name="TabLayoutTheme">
        <item name="android:textSize">16sp</item>
        <item name="android:textStyle">bold</item>
</style>

<com.google.android.material.tabs.TabLayout
        .
        app:tabTextAppearance="@style/TabLayoutTheme"
        >
Copy the code



You can see that all the TAB fonts have changed, which is not what we want. TabLayout can set OnTabSelectedListener to listen for events and dynamically set TAB styles by selecting state changes. Let’s look at the implementation logic

Create a tab_text_layout.xml


      
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:gravity="center"
    />
Copy the code

Then create new checked and unchecked styles in styles.xml

<style name="TabLayoutTextSelected">
        <item name="android:textSize">16sp</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textColor">@color/colorAccent</item>
</style>

 <style name="TabLayoutTextUnSelected">
        <item name="android:textSize">14sp</item>
        <item name="android:textStyle">normal</item>
        <item name="android:textColor">@color/grey</item>
</style>
Copy the code

Finally, add listening events to the TabLayout

tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
	@Override
    public void onTabSelected(TabLayout.Tab tab) {
       View customView = tab.getCustomView();
         if (customView == null) {
             tab.setCustomView(R.layout.tab_text_layout);
         }
         TextView textView = tab.getCustomView().findViewById(android.R.id.text1);
         textView.setTextAppearance(TabActivity.this, R.style.TabLayoutTextSelected);
     }

     @Override
     public void onTabUnselected(TabLayout.Tab tab) {
         View customView = tab.getCustomView();
         if (customView == null) {
             tab.setCustomView(R.layout.tab_text_layout);
         }
         TextView textView = tab.getCustomView().findViewById(android.R.id.text1);
         textView.setTextAppearance(TabActivity.this, R.style.TabLayoutTextUnSelected);
     }

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

Get the CustomView in TAB, set it to our own tab_TEXt_layout if empty, find the ID of the textView, and set the TextAppearance property to the textView. Note that the ID of textView must be Android.r.d.ext1, because you can see from the source that CustomView gets Android.R.D.ext1.

public class TabLayout extends HorizontalScrollView {...public final class TabView extends LinearLayout {...final void update(a) {
			final Tab tab = this.tab;
	      	finalView custom = tab ! =null ? tab.getCustomView() : null; . customTextView = custom.findViewById(android.R.id.text1); . }}}Copy the code

After all modifications are complete, rerun to see the effect:



It seems to work, but there is a slight problem. The first time we go in, the default style is still used for the unselected TAB. Our custom style does not work because the unselected TAB does not execute the onTabUnselected method in OnTabSelectedListener. The solution is to simply set an initial TabLayoutTextUnSelected style to the TabLayout control’s tabTextAppearance property.

<com.google.android.material.tabs.TabLayout
	.
    app:tabTextAppearance="@style/TabLayoutTextUnSelected" />
Copy the code

Then look at the results:

tabMode

The tabMode property is used to set whether a TAB can scroll horizontally. The options are Fixed (default), auto, and Scrollable.

In order to see a better contrast, we have added a few more tabs. When fixed is set to the default, all tabs will be crowded onto the screen



When scrollable is set



Generally, fixed is used for a small number of tabs and Scrollable is used for a large number of tabs, depending on the project.

tabIndicatorColor

This is the color of the property Settings indicator line, nothing to talk about, okay

tabIndicatorHeight

This property sets the height of the indicator. If we do not need to display the indicator, we can do this by setting tabIndicatorHeight to 0

tabIndicatorGravity

This property sets the display position of the indicator. The options are bottom(default), Center, top, and Stretch.

bottom

center

top

stretch



There are some other attributes that you can go towebsiteGet to know.

Set an interval drawable for TabLayout

By default, TabLayout has no space between each Tab. In actual projects, you may need to set a small vertical line between each Tab.

LinearLayout linearLayout = (LinearLayout) tabLayout.getChildAt(0);
linearLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
linearLayout.setDividerDrawable(ContextCompat.getDrawable(this,
                R.drawable.layout_divider_vertical));
Copy the code

Customize a drawable file, where you define a line layout_divider_vertical.xml


      
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#ff0000"/>
    <size android:width="1dp"/>
</shape>
Copy the code

You can see that the line height fills the entire TabLayout. If we need to keep the line height shorter, we can set DividerPadding to do this.

LinearLayout linearLayout = (LinearLayout) tabLayout.getChildAt(0);
linearLayout.setDividerPadding(10);
Copy the code

The running results are as follows:

That’s it for the basic use of TabLayout. If there are mistakes in the article, please point out!