Android TabLayout修改指示器宽度方案汇总

本文详细探讨了Android TabLayout中修改指示器宽度的多种方法,包括通过获取tabSelectedIndicator边界、重写draw()方法以及自定义布局等方案,旨在实现更符合设计需求的指示器效果。
摘要由CSDN通过智能技术生成

前言

TabLayout是一个遵循Material Design设计规范的官方控件,也是日常工作中最常用的控件之一,手机上随便打开一个APP,都能看到它的身影。TabLayout可以为一个多页面的布局提供页面指示器,使得一个Activity或者Fragment中能够展示更加丰富的内容。结合ViewPage使用更是可以实现丰富的页面切换效果,并能带来流畅的页面切换体验。

TabLayout的功能强大,使用灵活,许多属性都支持使用者自由的定义,甚至可以直接给Tab指定一个布局。然而如此强大的控件却偏偏不支持修改底部指示器的宽度,不得不说,写这个控件的工程师的心思是真的难以捉摸啊!
在这里插入图片描述
看看这个效果,是不是有些难以直视。再看看主流的APP,几乎都会对这个指示器宽度做一定的修改。UI设计的时候,这里通常也会带有公司的风格。指示器的宽度这么长,再好看的指示器也会被拉伸到变形的。这里就给出几种常见的修改方案

TabLayout的视图结构

TabLayout继承自HorizontalScrollView,具有横向滚动的功能。它拥有ScrollView的特点,即内部只能有一个子布局。TabLayout初始化时,会调用一次addView()来添加这个布局。

super.addView(slidingTabIndicator, 0, new HorizontalScrollView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));

同样我们也可以根据index = 0来获取这个布局

View view = tabLayout.getChildAt(0);

它是一个SlidingTabIndicator,继承自LinearLayout。翻译过来就是滑动标签指示器,也是TabView的直接父布局。你可能疑惑了,指示器不是指的TabView底部的横线么,怎么这个TabLayout的唯一子布局也叫指示器呢?

简单理解来说,TabView底部的指示器是视觉上的指示器,其作用是给用户标识当前被选中的Tab。我们常说的改指示器宽度就是修改它的宽度,它并不是一个View,本质是SlidingTabIndicator绘制在特定位置的一个Drawable。

而SlidingTabIndicator是数据上的指示器,其作用是给与TabLayout联动的视图,如ViewPager,标识出当前被选中的位置,以便于联动视图做出相应的操作。因此对于联动视图来讲,它也可以叫指示器。

TabLayout持有一个Lis< Tab >来管理各个Tab,每个Tab会有属于自己的视图TabView。当TabLayout增加Tab时,会调用SlidingTabIndicator的addView方法,将Tab的TabView添加进来

public void addTab(@NonNull Tab tab, int position, boolean setSelected) {
   
    ...
    configureTab(tab, position);
    addTabView(tab);
    ...
}

private void addTabView(@NonNull Tab tab) {
   
    final TabView tabView = tab.view;
    tabView.setSelected(false);
    tabView.setActivated(false);
    slidingTabIndicator.addView(tabView, tab.getPosition(), createLayoutParamsForTabs());
}

因此TabLayout的视图结构应该如下图所示。其中指示器并不是一个控件,它是绘制在SlidingTabIndicator底部的一个Drawable。
在这里插入图片描述

TabLayout绘制指示器的过程

前面提到,所谓的指示器其实只是一个TabLayout中的一个Drawable对象,TabLayout还为它提供了相应的getter和setter。

@Nullable Drawable tabSelectedIndicator;

当Tab切换时,对指示器的操作如下
(1) 获取tabSelectedIndicator的边界
(2) 调用tabSelectedIndicator的draw()方法,将tabSelectedIndicator绘制出来

步骤已经明了,如此就可以通过修改某一步骤的过程来实现指示器宽度的修改。

1.从获取tabSelectedIndicator边界着手

1.1 默认情况下的指示器宽度

默认情况下使用被选中TabView的宽度,即文章开始时图中看到的指示器充满整个TabView的情况。它使用当前TabView的宽度作为指示器宽度

.....
View selectedTitle = getChildAt(this.selectedPosition);
int left;
int right;
if (selectedTitle != null && selectedTitle.getWidth() > 0) {
   
    // 使用当前选中项的边界作为指示器的边界
    left = selectedTitle.getLeft();
    right = selectedTitle.getRight();
    ......
}
// 设置指示器的左右边界
setIndicatorPosition(left, right)
1.2 tabIndicatorFullWidth="false"时,指示器宽度

当设置了tabIndicatorFullWidth="false"时,遍历当前TabView的子控件,获取其中left的最小值作为指示器的左边界,right的最大值作为指示器的右边界。在大多数情况下文字才是一个Tab中宽度最大的,因此可以认为这种情况下指示器的宽度与文字宽度相同。

......
if (!tabIndicatorFullWidth && selectedTitle instanceof TabView) {
   
      calculateTabViewContentBounds((TabView) selectedTitle
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值