如何在设计支持库的TabLayout中设置选项卡之间的分隔符?

77

我正在使用新的android.support.design.widget.TabLayout库中的v7-appcompat,发现一个问题,就是没有办法设置选项卡之间的分隔符,不知道有没有方法可以设置。

我已经成功地配置了页面适配器和选项卡看起来很好,但是不能设置选项卡之间的分隔符。

我希望能够得到这种类型的选项卡。

Tab1 | Tab2 | Tab3

但目前它正在显示

Tab1  Tab2  Tab3

我的xml文件是

<android.support.design.widget.CoordinatorLayout 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.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" >

        <include layout="@layout/toolbar" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tablayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/shape_tabbar_background"
            app:tabIndicatorColor="@android:color/white"
            app:tabIndicatorHeight="4dp" />
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

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

我通过这种方式添加选项卡

viewPager = (ViewPager) findViewById(R.id.viewpager);
    viewPager.setOffscreenPageLimit(2);
    adapter = new TabAdapterLoginActivity(getSupportFragmentManager(),
            titles);
    viewPager.setAdapter(adapter);
    tabLayout = (TabLayout) findViewById(R.id.tablayout);
    tabLayout.setupWithViewPager(viewPager);

你尝试过以编程方式实现吗?例如 mTabHost.getTabWidget().setDividerDrawable(R.Color.Blue); - Skizo-ozᴉʞS ツ
请按照您的风格设置此项 <item name="android:divider">@color/your_color</item>。 - IntelliJ Amiya
我使用JakeWharton的TabPage ViewPagerIndicator,它解决了我的问题。 - Nick
8个回答

92

TabLayout 其实是 HorizontalScrollView,它的第一个子元素是 LinearLayout

因此,只需使用以下代码即可添加分隔线

    View root = tabLayout.getChildAt(0);
    if (root instanceof LinearLayout) {
        ((LinearLayout) root).setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
        GradientDrawable drawable = new GradientDrawable();
        drawable.setColor(getResources().getColor(R.color.separator));
        drawable.setSize(2, 1);
        ((LinearLayout) root).setDividerPadding(10);
        ((LinearLayout) root).setDividerDrawable(drawable);
    }

以下是样本屏幕截图

屏幕1 在此输入图像描述

屏幕2 在此输入图像描述


2
好的解决方案!非常感谢。对于那些使用图像作为分隔符的人来说,图像将被TabLayout的高度拉伸,有一种方法可以解决这个问题:https://dev59.com/mWgv5IYBdhLWcg3wSe-2 - Phong Nguyen
1
这个答案应该在顶部。 - Andrain
2
它的功能很好,但在第一个选项卡之前显示了分隔符,我无法删除。 - Narender Gusain
5
这个解决方案能够正常工作,但是在使用这种方法后,选项卡左侧会出现奇怪的空白。 - Zulqurnain Jutt
1
@RenatKaitmazov 你需要为那个LinearLayout制作自定义的可绘制对象。你可以参考这个链接 https://stackoverflow.com/a/47680974/842607。 - Jimit Patel
显示剩余12条评论

70

使用Tab的setCustomView方法可以添加分隔符:

TabLayout tabLayout = (TabLayout) findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);

for (int i = 0; i < tabLayout.getTabCount(); i++) {
      TabLayout.Tab tab = tabLayout.getTabAt(i);
      RelativeLayout relativeLayout = (RelativeLayout) 
            LayoutInflater.from(this).inflate(R.layout.tab_layout, tabLayout, false);

      TextView tabTextView = (TextView) relativeLayout.findViewById(R.id.tab_title);
      tabTextView.setText(tab.getText());
      tab.setCustomView(relativeLayout);
      tab.select();
}

带有分隔线的选项卡自定义布局(tab_layout.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

<!-- Tab title -->
<TextView
    android:id="@+id/tab_title"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:textColor="@drawable/tab_item_selector"/>

<!-- Tab divider -->
<View
    android:layout_width="1dp"
    android:layout_height="match_parent"
    android:layout_alignParentLeft="true"
    android:background="@android:color/black" />
</RelativeLayout>

将TabLayout标签的水平间距设置为0dp

<android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/shape_tabbar_background"
        app:tabIndicatorColor="@android:color/white"
        app:tabIndicatorHeight="4dp"

        app:tabPaddingStart="0dp"
        app:tabPaddingEnd="0dp" />

选项卡标题被选择时的文本颜色选择器(tab_item_selector.xml):

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:color="@color/abc_primary_text_material_dark" />
    <item android:state_focused="true" android:color="@color/abc_primary_text_material_dark" />
    <item android:state_pressed="true" android:color="@color/abc_primary_text_material_dark" />
    <item android:color="@color/abc_secondary_text_material_dark" />
</selector>

1
由于某种奇怪的原因,对我来说它看起来像 | Tab1 | Tab2 | Tab3 - Sekula1991
这是因为布局中的选项卡分隔线是左对齐的。您可以将属性android:layout_alignParentLeft =“true”更改为android:layout_alignParentRight =“true”。此外,如果您希望隐藏第一个选项卡上的分隔线,您可以在tab_layout.xml中为其分配一个ID,在代码中通过findViewById()方法获取它,并在循环中设置其可见性为GONE(如果i == 0)。 - Ivan Kušt
这个可以工作,但是它选择了第二个选项卡。如果我通过编程更改为第一个选项卡,则文本颜色看起来未被选中。 - user3289108
1
@user3289108,你找到获取第一个选项卡的解决方案了吗?我从来没有被选中过,如果我没有点击其他选项卡,XML部分也无法工作。 - RaRa
1
应该从第一个选项卡中删除分隔符,并且在水平方向上使用LinearLayout进一步简化布局。代码示例:for (int i = 1;...) - Samuel
显示剩余2条评论

1

我使用的不是最佳方法,而是当前的替代方法。

在Main.Xml中:

<android.support.design.widget.TabLayout
    android:id="@+id/tabs"
    style="@style/Base.Widget.Design.TabLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/master_color"
    app:elevation="0dp"
    app:tabMode="scrollable"
    app:tabPaddingEnd="2dp"
    app:tabPaddingStart="0dp"
    app:tabSelectedTextColor="@color/white"
    app:tabTextColor="#82c6e6" />

我正在使用Fragment,并在onCreate()中进行如下操作:
if (savedInstanceState == null) {
    replaceFragment(fragmentOne);
}

设置选项卡
私有void setupTabLayout(){
    fragmentOne = new FragmentOne();
    fragmentTwo = new FragmentTwo();

    allTabs.addTab(allTabs.newTab().setText("CURRENT YEAR"), true);
    allTabs.addTab(allTabs.newTab().setText("2015"));
    allTabs.addTab(allTabs.newTab().setText("2014"));
    allTabs.addTab(allTabs.newTab().setText("2013"));
    allTabs.addTab(allTabs.newTab().setText("2012"));
    allTabs.addTab(allTabs.newTab().setText("2011"));

    //Hide Indicator
    allTabs.setSelectedTabIndicatorColor(getResources().getColor(android.R.color.transparent));
    //Set Custom tab Background
    for (int i = 1; i < allTabs.getTabCount(); i++) {
        TabLayout.Tab tab = allTabs.getTabAt(i);
        RelativeLayout relativeLayout = (RelativeLayout)
                LayoutInflater.from(getActivity()).inflate(R.layout.tab_layout, allTabs, false);
        tvTabText = (TextView) relativeLayout.findViewById(R.id.tab_title);
        View view = (View) relativeLayout.findViewById(R.id.deviderView);

        tvTabText.setText(tab.getText());
        tab.setCustomView(relativeLayout);

        if (i == 0) {
            view.setVisibility(View.GONE);
            tab.select();
        }
    }

}

tab_layout.xml

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Tab title -->
    <TextView
        android:id="@+id/tab_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center_horizontal"
        android:padding="10dp"
        android:text="sdasd"
        android:textColor="@drawable/tab_item_selector"
        android:textSize="@dimen/text_size_normal"
        android:textStyle="bold" />

    <!-- Tab divider -->

    <View
        android:id="@+id/deviderView"
        android:layout_width="1dp"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginBottom="15dp"
        android:layout_marginTop="15dp"
        android:background="@android:color/white"
        android:gravity="right" />

</RelativeLayout>

tab_item_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:color="@android:color/white" />
    <item android:state_focused="true" android:color="@android:color/white" />
    <item android:state_pressed="true" android:color="@android:color/white" />
    <item android:color="#82c6e6" />
</selector>

请始终将其视为可选答案。

1
我认为这不可能,除非在创建选项卡时指定自定义视图并添加分隔符,例如一个TextView,并明确地使用TextView.setCompoundDrawablesWithIntrinsicBounds(0, 0,(int)id_of_a_divider, 0);
就像你试图检测它是否是第一个Tab一样。
if(firstTab){
    tabLayout.getTabAt(0).getCustomView()
    .setCompoundDrawablesWithIntrinsicBounds(0, 0,(int)id_of_a_divider, 0);
    //some little casting
}else if(lastTab){
  //dont get any
   tabLayout.getTabAt(index).getCustomView()
    .setCompoundDrawablesWithIntrinsicBounds(0,0,0, 0);
 else{
    //the rest takes two sides,
     tabLayout.getTabAt(index).getCustomView()
    .setCompoundDrawablesWithIntrinsicBounds((int)id_of_a_divider
       , 0,(int)id_of_a_divider, 0);

我希望你能理解我的想法。

你确定没有其他方法或内置功能可用吗? - Gopal Singh Sirvi
只有在没有相反的证据时才是真的,让我们等待直到被证明错误,但如果您查看TabLayout文档,您不会看到任何这样的内容。所以我很确定,直到我不确定为止,但现在你可以欣赏我的努力。 :) @GopalSinghSirvi,对于其他方法,您可以使用xml和样式,这就是我的情报范围。 - Elltz

1

你可以尝试以下解决方法:

1-创建普通的TabLayout。

2-将模式设置为MODE_FIXED。

3-将TabLayout添加到FrameLayout中,在其上方添加水平LinearLayout。

4-在水平布局中添加与选项卡数相同的按钮,并使每个按钮大小相等,每个按钮的layout_wight=1。

5-将按钮背景设置为透明。

6-通过View或任何其他视图在水平LinearLayout布局中添加分隔符,并将其宽度指定为0.5dp或所需宽度。

7-您可以在按钮上添加单击操作或更改按钮以便不处理单击操作的任何其他视图,因此其下的选项卡将接收单击操作 :)

这可能是一个丑陋的解决方案,但它完美地完成了工作。

另一个提示:如果要更改所选选项卡的背景,请将选项卡布局样式中的指示器高度设置为选项卡布局的实际高度。

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent"
    android:orientation="vertical">


    <FrameLayout
        android:id="@+id/content_parent"

        android:layout_width="fill_parent"
        android:layout_height="fill_parent">


        <android.support.v4.view.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1"

            android:background="@android:color/transparent" />




        <android.support.design.widget.TabLayout
            android:id="@+id/sliding_tabs"
            style="@style/MyCustomTabLayout"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_gravity="bottom"
            android:background="#99888888"
            android:clickable="false"
            android:layoutDirection="rtl"

              />


        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="0.5dp"
            android:layout_gravity="bottom"
            android:layout_marginBottom="60dp"
            android:background="#60ffffff"></LinearLayout>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="60dp"
            android:layout_gravity="bottom|right"
            android:background="@android:color/transparent"
            android:orientation="horizontal">


            <Button
                android:id="@+id/button1"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@android:color/transparent"
                android:clickable="true" />



            <LinearLayout
                android:layout_width="0.5dp"
                android:layout_height="60dp"
                android:background="#60ffffff"></LinearLayout>

            <Button
                android:id="@+id/button2"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@android:color/transparent"
                android:clickable="true"

                />

            <LinearLayout
                android:layout_width="0.5dp"
                android:layout_height="60dp"
                android:background="#60ffffff"></LinearLayout>

            <Button
                android:id="@+id/button3"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@android:color/transparent"
                android:clickable="true"

                />

            <LinearLayout
                android:layout_width="0.5dp"
                android:layout_height="60dp"
                android:background="#60ffffff"></LinearLayout>

            <Button
                android:id="@+id/button4"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@android:color/transparent"
                android:clickable="true"

                />

            <LinearLayout
                android:layout_width="0.5dp"
                android:layout_height="60dp"
                android:background="#60ffffff"></LinearLayout>

            <Button
                android:id="@+id/button5"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@android:color/transparent"
                android:clickable="true"

                />

        </LinearLayout>

    </FrameLayout>

and this is for style

 <style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
        <item name="tabIndicatorColor">#50000000</item>
        <item name="tabTextAppearance">@style/MyCustomTabTextAppearance</item>
        <item name="tabIndicatorHeight">60dp</item>
        <item name="tabSelectedTextColor">#222222</item>

自定义视图可能是处理这个问题更优雅的方式,但正如你所说,这确实可行。然而,对于某些视图来说,这可能不可行,因为您需要知道每个选项卡的精确宽度,否则分隔符将无法均匀间隔。此外,仅当选项卡数量在编译时是静态和已知的情况下才适用。 - mpellegr

0

试一下,希望它能正常工作。

tab_activity.xml

<TabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
            </TabWidget>

            <View
                android:layout_width="match_parent"
                android:layout_height="2dp"
                android:background="@color/edt_footer_bg" />

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginTop="15dp"
                android:background="@android:color/transparent" >
            </FrameLayout>
        </LinearLayout>
    </TabHost>

home_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    xmlns:mytextview="http://schemas.android.com/apk/res/com.bne"
    android:layout_height="50dp"
    android:layout_marginRight="2dp"
    android:background="@color/app_bg_inner"
    android:gravity="center"
    android:padding="10dp" >

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@drawable/tab_selector"
        android:textSize="@dimen/txt_12"
        mytextview:txt_custom_font="@string/RobotoRegular" />

</LinearLayout>

-1

尝试使用以下代码在TabHost中设置divdermTabHost.getTabWidget().setDividerDrawable(R.Color.blue);


问题是关于TabLayout,不是TabHost或其他东西。 - mpellegr

-3

添加自定义分隔符的一种方法是通过编程进行设置:

tablayout.getTabWidget().setDividerDrawable(R.drawable.yourdivider image name);

请确保在设置选项卡内容之前调用此函数。如果在之后调用,可能会导致崩溃。

如果上述方法不起作用,您也可以尝试使用此行代码。

if(Build.VERSION.SDK_INT >= 11)
    tablayout.getTabWidget().setShowDividers(TabWidget.SHOW_DIVIDER_MIDDLE);

3
tablayout.getTabWidget()在TabLayout中不存在该方法。 - Gopal Singh Sirvi
你的答案已经过时了,在新的设计支持库中不适用。 - Gopal Singh Sirvi
嗯,看看这些链接,希望它们会有所帮助。https://github.com/ogaclejapan/SmartTabLayout https://github.com/astuetz/PagerSlidingTabStrip - mominapk
我只想使用官方库...请告诉我是否只能使用设计支持库。 - Gopal Singh Sirvi
tablayout中没有名为getTabWidget()的方法。 - SaravanaRaja

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接