TabLayout修改

文章目录

文章修修补补添加了不少,主要分3个时间段

  1. 最早实现,就是在tab切换的时候在下边画一条线
  2. 不画线了,因为看源码知道线条宽度和tabview一样的,所以反射修改TabView的宽度
  3. viewPager?.addOnPageChangeListener 根据offset,动态计算view当前的位置,线条应该偏移的位置。
  4. 进化后,想画啥画啥,不一定是线条,反正位置都算出来了。

结构分析

QQ截图20171026091245.png

TabLayout这个导航控件,父类关系如下
public class TabLayout extends HorizontalScrollView
public class HorizontalScrollView extends FrameLayout
里边子空间的类型
class TabView extends LinearLayout implements OnLongClickListener
private class SlidingTabStrip extends LinearLayout
tablayout的结构图

QQ截图20171025161612.png

大概看下源码,整体布局的添加如下,首先加了一个SlidingTabStrip也就是个线性布局.

 public TabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        ThemeUtils.checkAppCompatTheme(context);

        // Disable the Scroll Bar
        setHorizontalScrollBarEnabled(false);

        // Add the TabStrip
        mTabStrip = new SlidingTabStrip(context);
        super.addView(mTabStrip, 0, new HorizontalScrollView.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));

完事通过绑定viewPager或者直接addTab来添加TabView

private void addTabView(Tab tab) {
        final TabView tabView = tab.mView;
        mTabStrip.addView(tabView, tab.getPosition(), createLayoutParamsForTabs());
    }

添加的tabView的params如下,根据mode和gravity设置为比重为1或是wrap

    private LinearLayout.LayoutParams createLayoutParamsForTabs() {
        final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        updateTabViewLayoutParams(lp);
        return lp;
    }
    private void updateTabViewLayoutParams(LinearLayout.LayoutParams lp) {
        if (mMode == MODE_FIXED && mTabGravity == GRAVITY_FILL) {
            lp.width = 0;
            lp.weight = 1;
        } else {
            lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
            lp.weight = 0;
        }
    }

至于TabView,最上边也说了也是个线性布局,垂直布局的,简单看下,默认的布局,里边添加了一个图片和一个TextView,自定义的就不说了。添加自定义的也就是把这两个默认的隐藏,完事add那个自定义的控件到TabView里而已

if (mCustomView == null) {
                // If there isn't a custom view, we'll us our own in-built layouts
                if (mIconView == null) {
                    ImageView iconView = (ImageView) LayoutInflater.from(getContext())
                            .inflate(R.layout.design_layout_tab_icon, this, false);
                    addView(iconView, 0);
                    mIconView = iconView;
                }
                if (mTextView == null) {
                    TextView textView = (TextView) LayoutInflater.from(getContext())
                            .inflate(R.layout.design_layout_tab_text, this, false);
                    addView(textView);
                    mTextView = textView;
                    mDefaultMaxLines = TextViewCompat.getMaxLines(mTextView);
                }
                TextViewCompat.setTextAppearance(mTextView, mTabTextAppearance);
                if (mTabTextColors != null) {
                    mTextView.setTextColor(mTabTextColors);
                }
                updateTextAndIcon(mTextView, mIconView);
            }

说了半天貌似和线条都没关系,好吧,再看下SlidingTabStrip的代码。里边有个onDraw方法,线条就是在这里加的

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

我们要做的就是如何修改这个线条的左右边界。下边先说下老的做法和思路

前提条件

下边都是为了修改mode=fixed,tabGravity="fill"这种,完事要求线条宽度和文字宽度差不多这种需求。
如果是mode=scollable这种,你要求文字和线条宽度一样,那么设置如下属性基本都能满足需求的

      app:tabMinWidth="2dp"
        app:tabPadding="1dp"
        app:tabPaddingStart="1dp"
        app:tabPaddingEnd="1dp"

简单分析下,一些默认属性

mMode = a.getInt(R.styleable.TabLayout_tabMode, MODE_FIXED);
mTabGravity = a.getInt(R.styleable.TabLayout_tabGravity, GRAVITY_FILL);//横屏的时候默认style里这个是center
        final Resources res = getResources();
        mScrollableTabMinWidth = res.getDimensionPixelSize(R.dimen.design_tab_scrollable_min_width);
  //添加tabview的时候会setminwidth的,就是调用如下方法获取最小宽度
  //可以看到tab是有个最小宽度的,design_tab_scrollable_min_width手机是72dp,pad之类的是160dp
    private int getTabMinWidth() {
        if (mRequestedTabMinWidth != INVALID_WIDTH) {
            // If we have been given a min width, use it
            return mRequestedTabMinWidth;
        }
        // Else, we'll use the default value
        return mMode == MODE_SCROLLABLE ? mScrollableTabMinWidth : 0;
    }

老的做法和思路

最早比较笨的想法,既然你这线条是画出来了,那我也画一个好了,不过因为那线条左右边界是动态的,想着麻烦,就弄个固定的好了,也就是tab切换的时候才改变线条,少了滑动效果。
我们的需求是线条和文字宽度差不多,那第一步肯定是获取到文字的宽度了,文字的宽度哪来的,当然是获取到tabView里的那个TextView的宽度了。

获取方法有两种,第一种反射,第二种直接getChildAt

QQ截图20171025170903.png

看下Tab里的那个mView就是我们要的TabView,里边就包含有TextView
下边就是重写TabLayout,给他画条线,缺点就是线不能滑动,我们通过监听tab选中状态的改变,来invalidate这个布局刷新线条。另外因为有了自己的线条了,所以需要把TabLayout的线条高度设置为0或者线条颜色弄为透明
那个factor就是线条长度和文字宽度的比例,为1就是一样,比1大就是稍微出去一点

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        TabCheck();
        canvas.drawRect(rectF.left,getHeight()-indicatorHeight,rectF.right,getHeight(),paintLine);

    }
    RectF rectF=new RectF();
    private void TabCheck(){
        try {
            //通过反射获取那个textView
            Tab tab=getTabAt(getSelectedTabPosition());
            Field field=tab.getClass().getDeclaredField("mView");
            field.setAccessible(true);
            LinearLayout linearLayout= (LinearLayout) field.get(tab);
            /**child1就是tab上的文字控件,第一个是图片控件,第二个就是这个文本控件*/
            View child1=linearLayout.getChildAt(1);//
            float add=(factor-1)*child1.getWidth()/2;
            rectF.left=linearLayout.getLeft()+child1.getLeft()-add;
            rectF.right=linearLayout.getLeft()+child1.getRight()+add;
        } catch (Exception e) {
            e.printStackTrace();
        }
        //根据整体控件的结构,我们也能拿到那个textView
//        int selectedPosition=getSelectedTabPosition();
//        LinearLayout slidingTabStrip=(LinearLayout)getChildAt(0);
//        LinearLayout tabView= (LinearLayout) slidingTabStrip.getChildAt(selectedPosition);
//        View textView=tabView.getChildAt(1);
    }

新的做法和思路

SlidingTabStrip里有下边的代码是来计算线条左右边距的,根据viewpager的偏移量动态改变
left 和right就是对应的线条的左右点位置

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

既然线条的宽度位置都和tabView有关,那么我们改变tabView的大小即可,默认的tabView的大小就是平分TabLayout的。
这里再强调下,我们的这个自定义只支持下边的属性,默认的就是这两个

app:tabGravity="fill"
app:tabMode="fixed"

完整的代码如下

import android.content.Context
import android.support.design.widget.TabLayout
import android.util.AttributeSet
import android.view.ViewTreeObserver
import android.widget.LinearLayout
import android.widget.TextView
import java.lang.reflect.Field

/**
 * Created by Sage on 2017/10/25.
 * Description:此控件只适用于 app:tabMode="fixed"
 */
class TabLayoutIndicatorShort : TabLayout {
    constructor(context: Context?) : super(context) {
        initSomeThing()
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        initSomeThing()
    }

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        initSomeThing()
    }


    private fun initSomeThing() {
        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                changeIndicator()
            }
        })

    }

    val factor = 1.1f
    fun changeIndicator() {
if(tabCount==0){
            return
        }
        val tabLayout:Class<*> = javaClass.superclass
        var tabStrip: Field? = null
        try {
            tabStrip = tabLayout.getDeclaredField("mTabStrip")
        } catch (e: Exception) {
            e.printStackTrace()
            return
        }
        tabStrip!!.isAccessible = true
        var ll_tab: LinearLayout? = null
        try {
            ll_tab = tabStrip.get(this) as LinearLayout
        } catch (e: Exception) {
            e.printStackTrace()
            return
        }
        /**每个tab的宽,总宽度除以tabCount*/
        val widthTab = width / tabCount
        for (i in 0..ll_tab.childCount - 1) {
            val child = ll_tab.getChildAt(i)
            child.setPadding(0, 0, 0, 0)
            try {
                val tv = (child as LinearLayout).getChildAt(1) as TextView
                var margin = ((widthTab - tv.width * factor) / 2).toInt()
                println("i==" + i + "==widthTab=" + widthTab + "==child w=" + tv.width + "==margin=" + margin)
                if (margin < 0) {
                    margin = 0
                }
                val params = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, tv.width.toFloat())
                params.leftMargin = margin
                params.rightMargin = margin
                child.setLayoutParams(params)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

    }

}

最后看下修改后的效果和原生的效果。

QQ截图20171026094315.png

原生的线条是平分的,点击范围也很大,我们修改后的线条是小了,可点击范围也小了。我还是喜欢原生的,可惜啊,很多时候ui设计的都是线条和文字宽度一样。如果不要求滚动的时候线条动画,我还是喜欢老的那种,直接画条线,也不影响点击范围。

最后的实现

以前懒得写啊,最近闲了,就抽空把这个实现吧
先看下效果图


image.png

移动到一半效果如下图


image.png

移动了超过一半,如下图
image.png

移动完成
image.png

简单说下思路:

隐藏掉原生画的线条【把颜色设置为透明,或者你把高度弄为0也可以】
然后给viewpager添加监听滑动的偏移量,我们来计算线条的位置
偏移量在0.5以下,
线条left位置从第一个textview的left位置移动到第一个的中心位置,
线条right位置从第一个textview的right位置移动到第二个textview的中心位置
偏移量0.5到1之间的话,
线条left位置是从第一个textview的中心位置到第二个textview的left位置
线条right位置是从第二个textview的中心位置到第二个textview的rigth位置
库一直在更新,下边的使用design库,新版的androidX也就是material库,TabLayout的tabIndicatorHeight属性默认高度没有了,它是通过一张默认图片获取的高度
所以老的代码,给个默认值,或者xml必须设置一个tabIndicatorHeight的高度才行

 indicotorHeight = a.getDimensionPixelSize(R.styleable.TabLayout_tabIndicatorHeight, 3)

代码如下

import android.content.Context
import android.graphics.Canvas
import android.support.design.widget.TabLayout
import android.support.v4.view.ViewPager
import android.util.AttributeSet
import android.graphics.Color
import android.graphics.Paint
import android.widget.LinearLayout
import android.graphics.RectF
import android.support.design.R
import android.support.v4.view.ViewCompat

class TabLayoutFixedFill : TabLayout {
    constructor(context: Context) : this(context, null)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr){
        initAttrs(context,attrs,defStyleAttr)
    }

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs,R.attr.tabStyle)

    private fun initAttrs(context: Context, attrs: AttributeSet?,defStyleAttr: Int) {
        val a = context.obtainStyledAttributes(attrs, R.styleable.TabLayout,
                defStyleAttr, R.style.Widget_Design_TabLayout)
        indicotorHeight = a.getDimensionPixelSize(R.styleable.TabLayout_tabIndicatorHeight, 0)
        paintLine.color = a.getColor(R.styleable.TabLayout_tabIndicatorColor, 0)
        a.recycle()
        setSelectedTabIndicatorColor(Color.TRANSPARENT)//隐藏掉原生画的线
    }

    var factor = 1f//线条的长度和文字宽度的比例,因为有的需求是比文字稍微长点。所以这里可以修改
    var indicotorHeight = 2;//线条的高度
    var paintLine = Paint()
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.drawRect(rectIndicator.left, getHeight().toFloat() - indicotorHeight, rectIndicator.right, getHeight().toFloat(), paintLine);
    }

    override fun setupWithViewPager(viewPager: ViewPager?, autoRefresh: Boolean) {
        super.setupWithViewPager(viewPager, autoRefresh)
        viewPager?.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            override fun onPageScrollStateChanged(state: Int) {
            }

            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                updateIndicator(position, positionOffset)
            }

            override fun onPageSelected(position: Int) {
            }
        })

    }

    var rectIndicator = RectF()//记录下要画的线条的left和right位置
    fun updateIndicator(position: Int, positionOffset: Float) {
    if(position>=tabCount){
            return
        }
        var rectF = getTextViewRect(position)
        var rectF2 = rectF
        if (position < tabCount - 1) {
            rectF2 = getTextViewRect(position + 1)
        }
        if (positionOffset < 0.5) {
            rectIndicator.left = rectF.left + rectF.width * positionOffset //第一个最左边移动到第一个的中心位置
            rectIndicator.right = rectF.right + (rectF2.center - rectF.right) * positionOffset * 2 //移动范围,从第一个右边,移动到另一个控件的中心位置
        } else {
            rectIndicator.left = rectF2.left - (rectF2.left - rectF.center) * (1 - positionOffset) * 2 //移动范围,从第一个中心到另一个最左边
            rectIndicator.right = rectF2.left + rectF2.width * positionOffset//第二个中心点到第二个的右边
        }
        ViewCompat.postInvalidateOnAnimation(this@TabLayoutFixedFill)
    }

    /**找出某个tabview里Textview的left和right位置*/
    private fun getTextViewRect(selectedPosition: Int): ViewOption {
        var slidingTabStrip = getChildAt(0) as LinearLayout
        var tabView = slidingTabStrip.getChildAt(selectedPosition) as LinearLayout
        var textView = tabView.getChildAt(1);
        val add = (factor - 1) * textView.width / 2
        return ViewOption(tabView.left + textView.left - add, tabView.left + textView.right + add)
    }

    /**记录下view的left,right,center ,and  width*/
    data class ViewOption(var left: Float, var right: Float, var center: Float = (right + left) / 2f, var width: Float = (right - left))
}

如果有人说我没有绑定viewpager咋办,也很简单,我上边的updateIndicator方法,你可以在切换tab的时候调用这个方法也可以。或者你也可以直接用最老的那种方法,就是画条线的那个也可以。

带背景的

上边介绍的是画了一条线,其实画啥都行,只要你愿意。
看下这种效果,就是在上边的代码上稍微修改下线条的高度,弄个圆角就可以了


20181119_134552.gif

布局如下
设置下左右的padding,完事设置下高度。padding是高度的一半,为了实现两边半圆的效果,这样弄最简单。
不想设置高度,你自己在里边算下文本的高度,然后自己算下padding也随你了,

    <com.charliesong.demo0327.pathanim.TabLayoutFixedWrap
        android:id="@+id/tabfixed"
        app:tabPaddingStart="20dp"
        app:tabPaddingEnd="20dp"
        android:layout_width="wrap_content"
        android:layout_height="40dp"/>

代码如下
增加了2个参数 var tabPaddingStart=0
var tabPaddingEnd=0;其实正常这两个是一样的,要不圆角就不一样拉。
然后onDraw里画个带圆角的
canvas.drawRoundRect(rect,tabPaddingStart/1f,height/2f, paintLine)

import android.content.Context
import android.graphics.Canvas
import android.support.design.widget.TabLayout
import android.support.v4.view.ViewPager
import android.util.AttributeSet
import android.graphics.Color
import android.graphics.Paint
import android.widget.LinearLayout
import android.graphics.RectF
import android.support.design.R
import android.support.v4.view.ViewCompat

class TabLayoutFixedWrap : TabLayout {
    constructor(context: Context) : this(context, null)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr){
        initAttrs(context,attrs,defStyleAttr)
    }

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs,R.attr.tabStyle)

    private fun initAttrs(context: Context, attrs: AttributeSet?,defStyleAttr: Int) {
        val a = context.obtainStyledAttributes(attrs, R.styleable.TabLayout,
                defStyleAttr, R.style.Widget_Design_TabLayout)
        paintLine.color = a.getColor(R.styleable.TabLayout_tabIndicatorColor, 0)
        val padding = a.getDimensionPixelSize(R.styleable.TabLayout_tabPadding, 0)
        tabPaddingStart = a.getDimensionPixelSize(R.styleable.TabLayout_tabPaddingStart,padding)
        tabPaddingEnd = a.getDimensionPixelSize(R.styleable.TabLayout_tabPaddingEnd,padding)
        a.recycle()
        setSelectedTabIndicatorColor(Color.TRANSPARENT)
    }
    var tabPaddingStart=0
    var tabPaddingEnd=0;
    var factor = 1f//这里没啥用了
    var paintLine = Paint()
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val rect=RectF(rectIndicator.left-tabPaddingStart, 0f, rectIndicator.right+tabPaddingEnd, getHeight().toFloat())
        canvas.drawRoundRect(rect,tabPaddingStart/1f,height/2f, paintLine)
    }

    override fun setupWithViewPager(viewPager: ViewPager?, autoRefresh: Boolean) {
        super.setupWithViewPager(viewPager, autoRefresh)
        viewPager?.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            override fun onPageScrollStateChanged(state: Int) {
            }

            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                updateIndicator(position, positionOffset)
            }

            override fun onPageSelected(position: Int) {
            }
        })

    }

    var rectIndicator = RectF() //记录下要画的线条的left和right位置

     fun updateIndicator(position: Int, positionOffset: Float) {
        if(position>=tabCount){
            return
        }
        var rectF = getTextViewRect(position)
        var rectF2 = rectF
        if (position < tabCount - 1) {
            rectF2 = getTextViewRect(position + 1)
        }
        if (positionOffset < 0.5) {
            rectIndicator.left = rectF.left + rectF.width * positionOffset //第一个最左边移动到第一个的中心位置
            rectIndicator.right = rectF.right + (rectF2.center - rectF.right) * positionOffset * 2 //移动范围,从第一个右边,移动到另一个控件的中心位置
        } else {
            rectIndicator.left = rectF2.left - (rectF2.left - rectF.center) * (1 - positionOffset) * 2 //移动范围,从第一个中心到另一个最左边
            rectIndicator.right = rectF2.left + rectF2.width * positionOffset//第二个中心点到第二个的右边
        }
        ViewCompat.postInvalidateOnAnimation(this@TabLayoutFixedWrap)
    }

    /**找出某个tabview里Textview的left和right位置*/
    private fun getTextViewRect(selectedPosition: Int): ViewOption {
        var slidingTabStrip = getChildAt(0) as LinearLayout
        var tabView = slidingTabStrip.getChildAt(selectedPosition) as LinearLayout
        var textView = tabView.getChildAt(1);
        val add = (factor - 1) * textView.width / 2
        return ViewOption(tabView.left + textView.left - add, tabView.left + textView.right + add)
    }

    /**记录下view的left,right,center ,and  width*/
    data class ViewOption(var left: Float, var right: Float, var center: Float = (right + left) / 2f, var width: Float = (right - left))
}

如果你需要的是那种scrollable的效果,那么添加如下的属性即可
系统默认tabview有个最小宽度的,你不设置的话,可能看到文字很少的tab宽度也很大。

        app:tabMode="scrollable"
        app:tabMinWidth="2dp"

其他一些看源码的收获

如果我们不设置tablayout的高度的话,用个warp,那么他的高度其实是固定的。
图片文字同时存在,是72dp,只有文字的话48dp
看下系统的一些默认值
tab是有最大宽度一说的,而且scroll模式下默认有个最小宽度的design_tab_scrollable_min_width

    <style name="Base.Widget.Design.TabLayout" parent="android:Widget">
        <item name="tabMaxWidth">@dimen/design_tab_max_width</item>
        <item name="tabIndicatorColor">?attr/colorAccent</item>
        <item name="tabIndicatorHeight">2dp</item>
        <item name="tabPaddingStart">12dp</item>
        <item name="tabPaddingEnd">12dp</item>
        <item name="tabBackground">?attr/selectableItemBackground</item>
        <item name="tabTextAppearance">@style/TextAppearance.Design.Tab</item>
        <item name="tabSelectedTextColor">?android:textColorPrimary</item>
    </style>
    <dimen name="design_tab_max_width">264dp</dimen>
    <dimen name="design_tab_scrollable_min_width">72dp</dimen>
    <dimen name="design_tab_text_size">14sp</dimen>
    <dimen name="design_tab_text_size_2line">12sp</dimen>

    <style name="Widget.Design.TabLayout" parent="Base.Widget.Design.TabLayout">
        <item name="tabGravity">fill</item>
        <item name="tabMode">fixed</item>
    </style>

如果是pad的话,values-sw600dp目录默认如下

<dimen name="design_tab_scrollable_min_width">160dp</dimen>
    <style name="Widget.Design.TabLayout" parent="Base.Widget.Design.TabLayout">
        <item name="tabGravity">center</item>
        <item name="tabMode">fixed</item>
    </style>

可以看到,手机默认是fill,而平板默认是center,所以如果不设置tabGravity,平板下你会发现tab不是平分宽度的,而是居中显示的。

补充

除了比较复杂的需求,如果只是要求修改选中的文字的效果,比如加粗,字体方法这些,还是可以简单实现的,还是那句话,tablayout的整体布局结构开头也都说了,那么拿到tab也就拿到了position,有了position自然能拿到那个textview控件了。

        tab_page.addOnTabSelectedListener(object :TabLayout.OnTabSelectedListener{
            override fun onTabReselected(tab: TabLayout.Tab?) {

            }

            override fun onTabUnselected(tab: TabLayout.Tab) {
                changeTextStyle(tab.position,false)
            }

            override fun onTabSelected(tab: TabLayout.Tab) {
                changeTextStyle(tab.position,true)
            }
        })

    private fun changeTextStyle(position: Int,selected:Boolean){
        var parent=tab_page.getChildAt(0) as LinearLayout
        var tabview=parent.getChildAt(position) as LinearLayout
       //tabview也可以通过反射tab的mView这个字段来获取
        var tv=tabview.getChildAt(1) as TextView
        tv.setTypeface(if(selected) Typeface.DEFAULT_BOLD else Typeface.DEFAULT)
        tv.setTextSize(if(selected) 40f else 15f)
    }

问题

需求是2个tab平分显示,可在平板上看到2个tab挤在一起了


image.png

添加如下的属性,修改下最大值,弄大点,另外游标长度默认是和文字长度一样的,下边的true可以保证和tab一样宽

app:tabIndicatorFullWidth="true"
        app:tabMaxWidth="2000dp"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,265评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,274评论 1 288
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,087评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,479评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,782评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,218评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,594评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,316评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,955评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,274评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,803评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,177评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,732评论 3 229
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,953评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,687评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,263评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,189评论 2 258

推荐阅读更多精彩内容