Android Tab layout: Wrap tab indicator width with

2020-05-14 08:34发布

Is there any way to wrap tab indicator width with respect to tab title ?

Current

Required

10条回答
相关推荐>>
2楼-- · 2020-05-14 08:57

As of support library 28 you can do the following:

app:tabIndicatorFullWidth="false"
app:tabPaddingStart="25dp"
app:tabPaddingEnd="25dp"

You can set the desired padding that affects the tab indicator.

Also you can now do this:

app:tabIndicator="@drawable/tab_indicator"

this will set a custom drawable as indicator.

example of custom drawable:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="@color/colorPrimary"/>
    <corners android:radius="5dp"/>
</shape>
查看更多
家丑人穷心不美
3楼-- · 2020-05-14 08:57

Short answer is "no". Here is explanation.

There is private class SlidingTabStrip within TabLayout that draws indicator

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        // Thick colored underline below the current selection
        if (mIndicatorLeft >= 0 && mIndicatorRight > mIndicatorLeft) {
            canvas.drawRect(mIndicatorLeft, getHeight() - mSelectedIndicatorHeight,
                    mIndicatorRight, getHeight(), mSelectedIndicatorPaint);
        }
    }

I believe mIndicatorLeft and mIndicatorRight is what you need. These fields are set in the same class:

    private void setIndicatorPosition(int left, int right) {
        if (left != mIndicatorLeft || right != mIndicatorRight) {
            // If the indicator's left/right has changed, invalidate
            mIndicatorLeft = left;
            mIndicatorRight = right;
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }

where left and right parameters are calculated in next method:

private void updateIndicatorPosition() {
        final View selectedTitle = getChildAt(mSelectedPosition);
        int left, right;
        if (selectedTitle != null && selectedTitle.getWidth() > 0) {
            left = selectedTitle.getLeft();
            right = selectedTitle.getRight();
            if (mSelectionOffset > 0f && mSelectedPosition < getChildCount() - 1) {
                // Draw the selection partway between the tabs
                View nextTitle = getChildAt(mSelectedPosition + 1);
                left = (int) (mSelectionOffset * nextTitle.getLeft() +
                        (1.0f - mSelectionOffset) * left);
                right = (int) (mSelectionOffset * nextTitle.getRight() +
                        (1.0f - mSelectionOffset) * right);
            }
        } else {
            left = right = -1;
        }
        setIndicatorPosition(left, right);
    }

And the worst thing is that SlidingTabStrip field in TabLayout is private and final.

private final SlidingTabStrip mTabStrip;

I don't see how it's possible to achieve what you need without creating totally new TabLayout.

查看更多
孤傲高冷的网名
4楼-- · 2020-05-14 08:58

You can do it using styles.

In the layout xml:

<android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        style="@style/AppTabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

in the styles.xml:

<style name="AppTabLayout" parent="Widget.Design.TabLayout">
    <item name="android:layout_marginLeft">40dp</item>
    <item name="android:layout_marginRight">40dp</item>
</style>
查看更多
戒情不戒烟
5楼-- · 2020-05-14 09:00

I'm note sure about the SDK Version needed, but you can do it directly in your XML file, adding the padding attribute using app namespace.

Just make your TabLayout looks like this:

        <android.support.design.widget.TabLayout
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/tab"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            ...
            app:tabPaddingEnd="0dp"
            app:tabPaddingStart="0dp"
        </android.support.design.widget.TabLayout>

You can move the xmlns:app="http://schemas.android.com/apk/res-auto" for your parent layou too, but its your choice :)

Thanks leon for his answer, that lead me to achieve that by XML.

查看更多
对你真心纯属浪费
6楼-- · 2020-05-14 09:03

I tried 2 hours for various solutions but none of those have a perfect effect.
The problem lies on the tabView's padding - even if I set its padding to all 0,
Different tabs still have different padding and therefore the text inside its TextView varies in size.

Then I found this library which perfectly solved it.
https://github.com/H07000223/FlycoTabLayout
As @Stas Melnychenko said, we probably can't do it unless we re-write a TabLayout. And this library does re-write a TabLayout...

查看更多
来,给爷笑一个
7楼-- · 2020-05-14 09:04

One simple solution is:

tabLayout.setTabIndicatorFullWidth(false);

But it works with latest dependency like

implementation 'com.android.support.constraint:constraint-layout:1.1.2'
implementation 'com.android.support:design:28.0.0'
查看更多
登录 后发表回答