当前位置: 移动技术网 > IT编程>移动开发>Android > TabLayout用法详解及自定义样式

TabLayout用法详解及自定义样式

2019年07月24日  | 移动技术网IT编程  | 我要评论

九把刀之天绝地变态版,地球编年史,颠覆香妃

tablayout的默认样式:

 app:theme="@style/widget.design.tablayout"

从系统定义的该样式继续深入:

 <style name="widget.design.tablayout" parent="base.widget.design.tablayout">
  <item name="tabgravity">fill</item>
  <item name="tabmode">fixed</item>
 </style>
 <style name="base.widget.design.tablayout" parent="android:widget">
  <item name="tabmaxwidth">264dp</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>

接着,看看系统定义tab文本的样式(注意textallcaps这个属性):   

 <style name="textappearance.design.tab" parent="textappearance.appcompat.button">
  <item name="android:textsize">14dp</item>
  <item name="android:textcolor">?android:textcolorsecondary</item>
  <item name="textallcaps">true</item>
 </style>

从系统定义tablayout的默认样式可以看出,我们可以改变tablayout对应的系统样式的属性值来适配我们自己的需求.

tablayout的基本用法

tablayout独立使用使用时,可以xml布局中静态添加tab个数及其样式,也可以动态添加tab的个数及其样式,如:

 <android.support.design.widget.tablayout
  android:id="@+id/tablayout"
  android:background="@color/colorprimary"
  android:layout_width="match_parent"
  android:layout_height="wrap_content">
  <android.support.design.widget.tabitem
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:text="android"/>
  <android.support.design.widget.tabitem
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:icon="@mipmap/ic_launcher"/>
 </android.support.design.widget.tablayout>

这里写图片描述

或者:

 <android.support.design.widget.tablayout
  android:id="@+id/tablayout"
  android:background="@color/colorprimary"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"/>
    
private int[] images = new int[]{
     r.drawable.ic_account_balance_wallet_black,
     r.drawable.ic_android_black,
     r.drawable.ic_account_box_black};
 private string[] tabs = new string[]{"小说", "电影", "相声"};
 tablayout tablayout = (tablayout) findviewbyid(r.id.tablayout);
 tablayout.addtab(tablayout.newtab().seticon(images[0]).settext(tabs[0]),true);
 tablayout.addtab(tablayout.newtab().seticon(images[1]).settext(tabs[1]),false);
 tablayout.addtab(tablayout.newtab().seticon(images[2]).settext(tabs[2]),false);

这里写图片描述

tablayout在实际开发中最多的是与viewpager联合使用,实现tablayout与viewpager的联动:

<android.support.design.widget.tablayout
  android:id="@+id/tablayout"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:background="@color/colorprimary"
  app:tabgravity="fill"
  app:tabindicatorcolor="@android:color/holo_orange_dark"
  app:tabindicatorheight="2dp"
  app:tabmode="fixed"
  app:tabselectedtextcolor="@android:color/holo_orange_dark"
  app:tabtextappearance="@style/customtabtextappearancestyle"
  app:tabtextcolor="@android:color/white"
  app:theme="@style/widget.design.tablayout"/>
 <android.support.v4.view.viewpager
  android:id="@+id/view_pager"
  android:layout_width="match_parent"
  android:layout_height="match_parent"/>
 tablayout tablayout = (tablayout) findviewbyid(r.id.tablayout);
 viewpager viewpager = (viewpager) findviewbyid(r.id.view_pager);
 viewpager.setadapter(new tabpageradapter(getsupportfragmentmanager()));
 tablayout.setupwithviewpager(viewpager);

这里写图片描述

值得注意的是:

在tabpageradapter中需要实现getpagertitle()否则,tablayout的tab将不显示,先看tablayout#setupwithpager()源码,发现tab的添加是在populatefrompageradapter()中实现,实现源码如下,可以看出该方法调用了pageradpater#getpagertitle()为tab设置文本信息,如果我们自定义的adapter没有实现getpagertitle()将会导致tab不显示文本信息.

void populatefrompageradapter() {
  removealltabs();
  if (mpageradapter != null) {
   final int adaptercount = mpageradapter.getcount();
   for (int i = 0; i < adaptercount; i++) {
    addtab(newtab().settext(mpageradapter.getpagetitle(i)), false);
   }
   // make sure we reflect the currently set viewpager item
   if (mviewpager != null && adaptercount > 0) {
    final int curitem = mviewpager.getcurrentitem();
    if (curitem != getselectedtabposition() && curitem < gettabcount()) {
     selecttab(gettabat(curitem));
    }
   }
  }
 }

另外, 我们发现getpagertitle()方法的返回值charsequence而不是string,那么tab的文本信息的设置将变得更加灵活,比如设置一个spanablestring,将图片和文本设置tab的文本.       

@override
  public charsequence getpagetitle(int position) {
   drawable image = tablayoutactivity.this.getresources().getdrawable(images[position]);
   image.setbounds(0, 0, image.getintrinsicwidth()/2, image.getintrinsicheight()/2);
   imagespan imagespan = new imagespan(image, imagespan.align_bottom);
   spannablestring ss = new spannablestring(" "+tabs[position]);
   ss.setspan(imagespan, 0, 1, spannable.span_exclusive_exclusive);
   return ss;
  } 

但是tab缺没有显示任何信息,一片空白,从上面提到的tablayout的系统默认样式中我们发现: <item name="textallcaps">true</item>,这会阻止imagespan渲染出来,我们只需要将textallcaps改为false即可,如下定义,再次运行,成功显示

 <style name="customtabtextappearancestyle" parent="textappearance.design.tab">
  <item name="textallcaps">false</item>
 </style>

这里写图片描述

  修改indicator的长度:

从tablayout的源码可以看出indicator的绘制,是在其内部类slidingtabstrip中绘制,而slingtabstrip类继承linearlayout,源码如下:

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

在ondraw()中主要是就绘制一个rect,并且宽度是根据mindicatorleft和mindicatorright设置的,而mindicatorleft等的宽度来自slidingtabstrip的child,而child就相当于一个tab,这样我们就通过修改child的margin来设置mindicatorleft的值. 

public void setindicator(tablayout tabs, int leftdip, int rightdip) {
  class<?> tablayout = tabs.getclass();
  field tabstrip = null;
  try {
   tabstrip = tablayout.getdeclaredfield("mtabstrip");
  } catch (nosuchfieldexception e) {
   e.printstacktrace();
  }
  tabstrip.setaccessible(true);
  linearlayout lltab = null;
  try {
   lltab = (linearlayout) tabstrip.get(tabs);
  } catch (illegalaccessexception e) {
   e.printstacktrace();
  }
  int left = (int) typedvalue.applydimension(typedvalue.complex_unit_dip, leftdip, resources.getsystem().getdisplaymetrics());
  int right = (int) typedvalue.applydimension(typedvalue.complex_unit_dip, rightdip, resources.getsystem().getdisplaymetrics());
  for (int i = 0; i < lltab.getchildcount(); i++) {
   view child = lltab.getchildat(i);
   child.setpadding(0, 0, 0, 0);
   linearlayout.layoutparams params = new linearlayout.layoutparams(0, linearlayout.layoutparams.match_parent, 1);
   params.leftmargin = left;
   params.rightmargin = right;
   child.setlayoutparams(params);
   child.invalidate();
  }
 }

然后在代码中调用即可,但是要注意,必须要在tablayout渲染出来后调用,我们可以选择view.post()方法来实现:

 tablayout.post(new runnable() {
   @override
   public void run() {
    setindicator(tablayout, 20, 20);
   }
 });

最后得到效果图如下:

这里写图片描述

自定义tablayout的tabitem及tabitem的点击事件

在tablayout的api是没有提供tabitem点击事件的方法,如果我们想实现如下效果图,怎么办?

这里写图片描述

先自定义一个tabitem:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:gravity="center"
 android:orientation="horizontal">
 <textview
  android:id="@+id/txt_title"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:gravity="center"
  android:textsize="14sp" />
 <imageview
  android:id="@+id/img_title"
  android:src="@drawable/indicator"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginleft="5dp" />
</linearlayout>

在自定义的adapter中可以定义一个gettabview的方法:

 public view gettabview(int position){
  view view = layoutinflater.from(context).inflate(r.layout.tab_item, null);
  textview tv= (textview) view.findviewbyid(r.id.textview);
  tv.settext(tabtitles[position]);
  imageview img = (imageview) view.findviewbyid(r.id.imageview);
  img.setimageresource(imageresid[position]);
  return view;
 }

  重新设置点击事件:

viewpager.setadapter(pageradapter);
 tablayout.setupwithviewpager(viewpager);
 for (int i = 0; i < tablayout.gettabcount(); i++) {
  tablayout.tab tab = tablayout.gettabat(i);
  if (tab != null) {
   tab.setcustomview(pageradapter.gettabview(i));
   if (tab.getcustomview() != null) {
    view tabview = (view) tab.getcustomview().getparent();
    tabview.settag(i);
    tabview.setonclicklistener(mtabonclicklistener);
   }
  }
 }
 viewpager.setcurrentitem(1);

以上所述是小编给大家介绍的tablayout用法详解及自定义样式,希望对大家有所帮助

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网