android TabLayout的指示器宽度问题

最近碰到一个需求,因为是我比较感兴趣的TabLayout的,所以记录一下吧。

  1. 产品需求:希望上部导航栏中的指示器宽度略大于文字宽度;
  2. 技术方案:TabLayout配合ViewPager;
  3. 问题分析: 原生TabLayout的指示器宽度等于每个tab的宽度,远大于 tab内文字标题的宽度。

原因分析:

TabLayout(TL)继承自HorizontalScrollView,其只能添加一个子控件,这个子控件便是TL内部私有类–SlidingTabStrip,其继承自LinearLayout。指示器怎么加上的呢?便是在该类的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,
 mIndicatorRight, getHeight(),
 mSelectedIndicatorPaint);
 }
}

即指示器是与这个SlidingTabStrip容器伴生存在,其宽度,由mIndicatorLeft和mIndicatorRight确定,而这二者,由tab的宽度决定,因为本文不会详细描述TL的源码,所以这里直接报出结论:这个指示器的宽度设置由tab宽度决定,而tab在mode=fix情况下,是符合linearLayout中weight控制的,因此,也没法通过tab的宽度来影响指示器的宽度,比较囧的是,源码中也没给tab设置个Margin什么的,另外,源码中也没有暴露set等方法来改变指示器宽度,否则也不会有此问题了。

解决方案1:

百度的方案基本集中在反射,使用麻烦,有时还不好用。

这个的思路来自stackoverflow,大致过程是 由TL拿到其唯一的子类,即SlidingTabStrip,然后遍历再拿到其各子View,然后为每个子View设置Margin,这就相当于给每个tab设置margin,那么指示器的宽度自然也就跟着改变了。show code:

public static void reduceMarginsInTabs(TabLayout tabLayout, int marginOffset) {
  View tabStrip = tabLayout.getChildAt(0);
  if (tabStrip instanceof ViewGroup) {
   ViewGroup tabStripGroup = (ViewGroup) tabStrip;
   for (int i = 0; i < ((ViewGroup) tabStrip).getChildCount(); i++) {
    View tabView = tabStripGroup.getChildAt(i);
    if (tabView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
     ((ViewGroup.MarginLayoutParams) tabView.getLayoutParams()).leftMargin = marginOffset;
     ((ViewGroup.MarginLayoutParams) tabView.getLayoutParams()).rightMargin = marginOffset;
    }
   }
  tabLayout.requestLayout();
  }
 }

这种方式的限制是:最多只能让指示器与tab等宽,无法继续减小指示器的宽度。

解决方案2:

本方案属于自定制指示器显示,相对比较灵活,能解决方案1的tab等宽问题,但是其缺点是不能保留指示器的动画。具体过程:

TL中tab可以设置自定义view,方法是setCustomView(@Nullable View view) ,也就是说,完全可以不用TL中那套,直接自定义布局即可。在tab源码的update方法中有这么一句:

 mCustomTextView = (TextView) custom.findViewById(android.R.id.text1);
 if (mCustomTextView != null) {
  mDefaultMaxLines = TextViewCompat.getMaxLines(mCustomTextView);
 }
 mCustomIconView = (ImageView) custom.findViewById(android.R.id.icon);

里面的android.R.id.text1和android.R.id.icon就是TL中tab能跟随滑动改变状态的两个view的id,我们自定义的时候可以让对应的view也这么设置id即可。而指示器,大可屏蔽原生TL的,直接在自定义布局的合适位置,加个view就行。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • Android TabLayout设置指示器宽度的方法
(0)

相关推荐

  • Android TabLayout设置指示器宽度的方法

    anroid 5.0 Design  v7 包中引用了TabLayout 简单快速的写出属于自己的Tab切换效果 如图所示: 但是正常使用中你发现无法设置tablayout指示器的宽度.查看源码你会发现设计师将指示器的宽度设置成TabView最大的宽度.并且设计师并没有给我们暴漏出接口,这导致有时使用TabLayout无法满足一些产品设计要求,这么好的组件无法使用还需要自定义费时费力.这个时候我们可以通过反射机制拿到TabLayout中的指示器对象对它的宽度进行处理就可以满足我们的要求:具体代码

  • android TabLayout的指示器宽度问题

    最近碰到一个需求,因为是我比较感兴趣的TabLayout的,所以记录一下吧. 产品需求:希望上部导航栏中的指示器宽度略大于文字宽度: 技术方案:TabLayout配合ViewPager: 问题分析: 原生TabLayout的指示器宽度等于每个tab的宽度,远大于 tab内文字标题的宽度. 原因分析: TabLayout(TL)继承自HorizontalScrollView,其只能添加一个子控件,这个子控件便是TL内部私有类–SlidingTabStrip,其继承自LinearLayout.指示器

  • android TabLayout使用方法详解

    Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个support库里面,Google给我们提供了更加规范的MD设计风格的控件.最重要的是,Android Design Support Library的兼容性更广,直接可以向下兼容到Android 2.2. 这两天需要做一个仿京东详情的页面,上面的Tab切换,以前都是自己写Viewpager+fragment

  • 解决Android TabLayout 在宽屏幕上tab不能平均分配的问题

    当TabLayout 在宽屏幕的设备上,如平板横屏的时候,tab的宽度超过一定值后,就不在平均分配宽度,而是居中显示. 此时设置 app:tabMode="fixed" 或者 top_table.setTabMode(TabLayout.MODE_FIXED); 不在起作用. app:tabMaxWidth="0dp" 此值即可解决! <android.support.design.widget.TabLayout android:layout_width=&

  • Android实现带有指示器的进度条

    背景 当我们看到UI给我们设计的效果的时候,我们习惯性的思路就是看看google有没有为我们提供相应的控件或者是能否在网上找到一些合适的轮子拿过来直接用.但是,有时候很不巧的是没有这样的轮子供我们直接使用,而且,UI以及产品就需要这样的效果的时候,我们就只能自己进行实现绘制.今天呢,我就带大家从简单的实现一个带有指示器的进度条,帮大家理解一下之定义View的绘制流程. 效果实现图 俗话说,没有效果图,就等于是耍那个啥,所以按照惯例,贴图: 开干 当我们决定要自己进行绘制的时候,我们首先需要对需求

  • Android TabLayout 自定义样式及使用详解

    目录 基本使用 XML静态设置TabItem 联动ViewPager2动态设置TabItem 1. Activity布局代码 2. 创建三个Fragment给ViewPager2设置 3. Fragment对应XML布局 4. 绑定起来 最终效果 根据数据源动态生成TabItem 1.Activity布局代码 2. Activity代码 最终效果 修改TabLayout背景颜色 修改indicator layer-list 制作圆形的indicator 制作圆角矩形indicator 修改边距

  • Android编程中TextView宽度过大导致Drawable无法居中问题解决方法

    本文实例讲述了Android编程中TextView宽度过大导致Drawable无法居中问题解决方法.分享给大家供大家参考,具体如下: 在做项目的时候,很多时候我们都要用到文字和图片一起显示,一般设置TextView的DrawableLeft.DrawableRight.DrawableTop.DrawableBottom就行了.但是有一种情况是当TextView的熟悉是fill_parent或者使用权重的时候并且设置了起Gravity的ceter的时候,Drawable图片是无法一起居中的,为了

  • android获取屏幕高度和宽度的实现方法

    本文实例讲述了android获取屏幕高度和宽度的实现方法.分享给大家供大家参考.具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现.下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即可获取屏幕的尺寸. 在一个Activity的onCreate方法中,写入如下代码: 复制代码 代码如下: DisplayMetrics metric = new DisplayMetrics();     getWindowManager().getDefau

  • Android TabLayout(选项卡布局)简单用法实例分析

    本文实例讲述了Android TabLayout(选项卡布局)简单用法.分享给大家供大家参考,具体如下: 我们在应用viewpager的时候,经常会使用TabPageIndicator来与其配合.达到很漂亮的效果.但是TabPageIndicator是第三方的,而且比较老了,当然了现在很多大神都已经开始自己写TabPageIndicator来满足自己的需求,在2015年的google大会上,google发布了新的Android Support Design库,里面包含了几个新的控件,其中就有一个

  • Android开发实现ImageView宽度顶边显示,高度保持比例的方法

    本文实例讲述了Android开发实现ImageView宽度顶边显示,高度保持比例的方法.分享给大家供大家参考,具体如下: ImageView 图片宽度顶边显示,高度保持比例 1.在布局中设置 <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="5dp" android:paddingR

随机推荐