natuan241
natuan241

Reputation: 751

How to create app bar with icons using TabLayout Android Design?

I'm trying to use the new TabLayout in the android design library to create app bar with icons.

public void setupTabLayout(TabLayout tabLayout) {
    tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
    tabLayout.setTabGravity(TabLayout.GRAVITY_CENTER);
    tabLayout.setupWithViewPager(mViewpager);
    tabLayout.getTabAt(0).setIcon(R.drawable.ic_tabbar_library);
    tabLayout.getTabAt(1).setIcon(R.drawable.ic_tabbar_recents);
    tabLayout.getTabAt(2).setIcon(R.drawable.ic_tabbar_favorites);
    tabLayout.getTabAt(3).setIcon(R.drawable.ic_tabbar_notifications);
    tabLayout.getTabAt(4).setIcon(R.drawable.ic_tabbar_settings);
}

Result:

app bar with icons

Please help me to create app bar similar:

app bar with icons

Sorry my english is not good.Thanks is advance !

Upvotes: 19

Views: 26802

Answers (4)

Chris Dinon
Chris Dinon

Reputation: 566

From the documentation :

https://developer.android.com/reference/android/support/design/widget/TabLayout.Tab.html#setCustomView(android.view.View)

Set a custom view to be used for this tab. This overrides values set by setText(CharSequence) and setIcon(Drawable).

you will have to set the title values yourself

From your example:

public void setupTabLayout(TabLayout tabLayout) {
    tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
    tabLayout.setTabGravity(TabLayout.GRAVITY_CENTER);
    tabLayout.setupWithViewPager(mViewpager);

    TextView tab = (TextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
    tab.setText("Library");
    tab.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.ic_tabbar_library, 0, 0);
    tabLayout.getTabAt(0).setCustomView(tab);
    //..
}

custom_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tab" />

Update

The api has changed to allow you to set a custom id so you don't have to set the text/drawable manually. It'll use the adapter's values.

If the provided view contains a TextView with an ID of text1 then that will be updated with the value given to setText(CharSequence). Similarly, if this layout contains an ImageView with ID icon then it will be updated with the value given to setIcon(Drawable).

Upvotes: 28

DarkLeafyGreen
DarkLeafyGreen

Reputation: 70466

When you use vector drawables as icons you might want to reuse a single drawables for different states, by simply tinting it differently. This way you can reduce the apk size and the allocation of resources. First define a custom FragmentPagerAdapter (I am using kotlin instead of java here)

class TabPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {

    override fun getCount(): Int = 2

    override fun getItem(position: Int): Fragment = when (position) {
        0 -> FirstFragment.newInstance()
        else -> SecondFragment.newInstance()
    }

    fun getPageIcon(context: Context, position: Int): Drawable = when (position) {
        0 -> ContextCompat.getDrawable(context, R.drawable.ic_whatshot)
        else -> ContextCompat.getDrawable(context, R.drawable.ic_face)
    }
}

Instead of implementing getPageTitle we create a getPageIcon method, that returns a drawable for a specific tab. Next we create a custom TabLayout:

class IconTabLayout : TabLayout {

    private var viewPager: ViewPager? = null

    constructor(context: Context) : super(context)
    constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
    constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)

    override fun onAttachedToWindow() {
        if (viewPager == null) {
            if (parent is ViewPager) viewPager = parent as ViewPager
        }
        super.onAttachedToWindow()
    }

    override fun setupWithViewPager(viewPager: ViewPager?, autoRefresh: Boolean) {
        this.viewPager = viewPager
        super.setupWithViewPager(viewPager, autoRefresh)
    }

    override fun addTab(@NonNull tab: Tab, position: Int, setSelected: Boolean) {
        if (viewPager != null && viewPager!!.adapter is TabPagerAdapter) {
            val icon: Drawable = DrawableCompat.wrap((viewPager!!.adapter as TabPagerAdapter).getPageIcon(context, position))
            DrawableCompat.setTintList(icon.mutate(), ContextCompat.getColorStateList(context, R.color.tab_color))
            tab.icon = icon
        }
        super.addTab(tab, position, setSelected)
    }
}

So the magic happens in the addTab method, where the icon and the color state list are set. The color state list has following structure:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Non focused states -->
    <item android:color="@color/tab_not_active" android:state_focused="false" android:state_pressed="false" android:state_selected="false" />
    <item android:color="@color/tab_active" android:state_focused="false" android:state_pressed="false" android:state_selected="true" />

    <!-- Focused states -->
    <item android:color="@color/tab_not_active" android:state_focused="true" android:state_pressed="false" android:state_selected="false" />
    <item android:color="@color/tab_active" android:state_focused="true" android:state_pressed="false" android:state_selected="true" />

    <!-- Pressed -->
    <item android:color="@color/tab_not_active" android:state_pressed="true" />
</selector>

Upvotes: 1

nlt
nlt

Reputation: 555

You can use the attribute android:layout of TabItem to set custom view. In custom view xml file, remember to set id of icon and text view to @android:id/icon and android:id="@android:id/text1", then the library will take care the rest.

Here's an example:

. custom_tab_item.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

  <ImageView
      android:id="@android:id/icon"
      android:layout_width="16dp"
      android:layout_height="16dp"
      android:layout_marginTop="4dp"
      android:scaleType="centerInside"/>

  <TextView
      android:id="@android:id/text1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginLeft="8dp"
      android:textSize="16dp"/>

</LinearLayout>

. main.xml

<android.support.design.widget.TabLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

  <android.support.design.widget.TabItem
      android:id="@+id/ti_activities"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:icon="@drawable/ic_question"
      android:layout="@layout/custom_tab_item"
      android:text="@string/activities"/>

  <android.support.design.widget.TabItem
      android:id="@+id/ti_profile"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:icon="@drawable/ic_question"
      android:layout="@layout/custom_tab_item"
      android:text="@string/Profile"/>

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

Hope this help.

Upvotes: 3

Amir
Amir

Reputation: 16607

As documentation said You can add items to TabLayout through the xml by use of TabItem. An example usage is like:

 <android.support.design.widget.TabLayout
         android:layout_height="wrap_content"
         android:layout_width="match_parent">

     <android.support.design.widget.TabItem
             android:text="@string/tab_text"/>

     <android.support.design.widget.TabItem
             android:icon="@drawable/ic_android"/>

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

Upvotes: 2

Related Questions