如何使用 TabLayout Android Design 创建带图标的应用栏?

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

我正在尝试使用 android 设计库中的新 TabLayout 来创建带有图标的应用栏。

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);
}

结果:

请帮我创建类似的应用栏:

对不起我的英语不是good.Thanks是进步!

来自文档:

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).

您必须自己设置标题值

根据你的例子:

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" />

更新

api 已更改为允许您设置自定义 ID,因此您不必手动设置 text/drawable。它将使用适配器的值。

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).

正如 documentation 所说,您可以使用 TabItem 通过 xml 添加项目到 TabLayout。示例用法如下:

 <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>

您可以使用 TabItem 的属性 android:layout 来设置自定义视图。 在自定义视图 xml 文件中,记得将图标和文本视图的 id 设置为 @android:id/iconandroid:id="@android:id/text1",然后库将处理其余部分。

举个例子:

。 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>

希望对您有所帮助。

当你使用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.首先定义一个自定义的FragmentPagerAdapter(我这里使用的是kotlin而不是java)

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)
    }
}

我们创建了一个 getPageIcon 方法,而不是实施 getPageTitle 方法,即 returns 特定选项卡的可绘制对象。接下来我们创建一个自定义的 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)
    }
}

所以魔术发生在 addTab 方法中,其中设置了图标和颜色状态列表。颜色状态列表具有以下结构:

<?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>