Android控件——Tablayout使用浅析(一)

1. Tablelayout序言

在一个app中,Tabs 使不同视图和功能之间的切换变得简单。使用 tabs 将大量关联的数据或者选项划分成更易理解的分组,可以在不需要切换出当先上下文的情况下,有效的进行内容导航和内容组织。

Tablayout继承自HorizontalScrollView,用作页面切换指示器
这里给出一个相关Tablayout实现的效果图:
在这里插入图片描述
从效果图上可以看出,可以操作的属性有:设置tab属性,指示线的设置,tab的图标设置,超出屏幕滚动tab

2. 简单使用

Tablayout常用属性如下:

  • tabGravity fill,填满TabLayout;center,居中显示
  • tabMode fixed, 固定标签;scrollable,可滚动标签,个数较少的时候可 以使用fixed,如果标签超出了屏幕范围,设置为scrollable比较好
  • tabMaxWidth Tab的最大宽度
  • tabIndicatorColor 底部滑动的线条的颜色,默认是colorAccent
  • tabIndicatorHeight 底部滑动线条的高度
  • tabPadding* 标签页的padding
  • tabBackground 标签页的背景
  • tabTextAppearance 文本设置
  • tabSelectedTextColor 选中字体颜色

Tablayout常见方法如下:

  • 构造方法 不显示滚动条,创建标签条就是下面滚来滚去的那个东东,获取自定义属性值
  • addTab 手动添加Tab页
  • addOnTabSelectedListener/removeOnTabSelectedListenerclearOnTabSelectedListeners 添加/移除/清空Tab选择事件监听器
  • newTab 创建Tab页
  • getTabAt 通过index获取Tab
  • removeTab 通过tab实例移除tab
  • removeTabAt 移除特定位置的tab
  • removeAllTabs 清空tabs
  • setTabTextColors 设置tab的正常显示颜色和选中后颜色
  • setupWithViewPager 通过ViewPager初始化TabLayout
  • shouldDelayChildPressedState 判断是否需要delay视图的press状态,一般无法滚动的视图直接返回false,可以滚动的视图看情况返回true或者false
  • addView 添加TabItem,如果参数类型不是TabItem会报异常
  • generateLayoutParams 默认生成属性值,防止TabItem没有定义android:layout_*而报异常

TabItem属性

  • text:标签文字
  • icon:图标
  • layout:自定义布局

2.1 默认使用样式

  • activity_main.xml布局
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.tablayoutusecase.defaultuse.MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:background="@color/colorPrimaryDark">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="一般用法"
            android:textColor="#fff"
            android:textSize="16sp"/>

    </RelativeLayout>

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

</LinearLayout>
  • MainActivity修改:设置相关属性
public class MainActivity extends AppCompatActivity {
    private TabLayout tabLayout;
    private String[] titles = new String[]{"最新","热门","我的"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();
    }

    private void init() {

        tabLayout = (TabLayout) findViewById(R.id.tablayout);
        
		// 创建Tab页
        for(int i=0;i<titles.length;i++){
            tabLayout.addTab(tabLayout.newTab());
        }
		// 设置TabItem的标题
        for(int i=0;i<titles.length;i++){
            tabLayout.getTabAt(i).setText(titles[i]);
        }
    }

}

2.2 设置Tablayout属性:

简单效果图如下
在这里插入图片描述
用Tablayout属性写一个style,给需要的Tablayout引用:

<!-- 设置tablayout样式 -->
    <style name="MyTablayoutstyle" parent="Base.Widget.Design.TabLayout">
        <item name="tabBackground">@color/white</item>
        <item name="tabIndicatorColor">@color/green</item>
        <item name="tabIndicatorHeight">2dp</item>
        <item name="tabSelectedTextColor">@color/green</item>
        <item name="android:textSize">15sp</item>
        <item name="android:textColor">@color/text</item>
    </style>

Tablayout引用:


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

2.3 Tablayout 指示线设置

  • 不想显示指示线,可以给tabIndicatorHeight属性设置0dp,或者给tabSelectedTextColor属性设置透明,就不显示指示线了
    在这里插入图片描述
  • 修改指示线长度
    在布局中无法找到tabIndicatorWidth属性,进入到Tablayout类里面查找,查看其如何实现指示线。
    找到有SlidingTabStrip内部类:
private final SlidingTabStrip mTabStrip;
 private class SlidingTabStrip extends LinearLayout {
        private int mSelectedIndicatorHeight;
        private final Paint mSelectedIndicatorPaint;

        int mSelectedPosition = -1;
        float mSelectionOffset;

        private int mLayoutDirection = -1;

        private int mIndicatorLeft = -1;
        private int mIndicatorRight = -1;

        private ValueAnimator mIndicatorAnimator;

        SlidingTabStrip(Context context) {
            super(context);
            setWillNotDraw(false);
            mSelectedIndicatorPaint = new Paint();
        }

        void setSelectedIndicatorColor(int color) {
            if (mSelectedIndicatorPaint.getColor() != color) {
                mSelectedIndicatorPaint.setColor(color);
                ViewCompat.postInvalidateOnAnimation(this);
            }
        }
        ... ...

可知该类就是设置指示线的,继承于Linearlayout。通过反射获得Tablayout的mTabStrip,循环获取到子View,设置leftMargin,rightMargin就可以压缩tab的宽度。

public class IndicatorLineUtil {
    /**
     * 调节tablayout指示线宽度
     * @param tabs
     * @param leftDip
     * @param rightDip
     */
    public static 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调用此方法:注意:margin数值不能设置过大,不然tab宽度压缩为0整个tablayout就不显示了。

tab3.post(new Runnable() {
            @Override
            public void run() {
                IndicatorLineUtil.setIndicator(tab3, 40, 40);
            }
        });

在这里插入图片描述

2.4 设置默认图标

Tablayout自带了setIcon()方法设置图标资源,不过效果别扭,脸被拉长。可以自己造一个。

tabLayout.getTabAt(i).setText(titles[i]).setIcon(pics[i]);

自己设置图标资源

  • 创建图标和文字布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="48dp"
    android:gravity="center">

    <ImageView
        android:id="@+id/imageview"
        android:layout_gravity="center"
        android:layout_width="24dp"
        android:layout_height="24dp" />

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textSize="14sp"
        android:layout_marginLeft="8dp"/>
</LinearLayout>
  • 设置资源方法:
	/**
     * 设置自定义位置图标
     */
    private void setCustomIcon() {

        tabLayout2 = (TabLayout) findViewById(R.id.tablayout2);
        for(int i=0;i<titles.length;i++){
            tabLayout2.addTab(tabLayout2.newTab());
        }

        for(int i=0;i<titles.length;i++){
            tabLayout2.getTabAt(i).setCustomView(makeTabView(i));
        }
    }


	/**
     * 引入布局设置图标和标题
     * @param position
     * @return
     */
    private View makeTabView(int position){
        View tabView = LayoutInflater.from(this).inflate(R.layout.tab_text_icon,null);
        TextView textView = tabView.findViewById(R.id.textview);
        ImageView imageView = tabView.findViewById(R.id.imageview);
        textView.setText(titles[position]);
        imageView.setImageResource(pics[position]);

        return tabView;
    }

2.5 tab超出屏幕时

当tab数量较多,超出屏幕,如今日头条的分类一样。可以用app:tabMode="scrollable"属性,让Tablayout变得可滚动,可超出屏幕
在这里插入图片描述
在布局中引入:

<android.support.design.widget.TabLayout
        android:id="@+id/tablayout3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabSelectedTextColor="@color/green"
        android:layout_marginTop="20dp"
        app:tabMode="scrollable"
        android:background="@color/white"/>

2.6 使用TabItem

在创建Tab时,可以直接在xml布局中设置TabItem来创建Tab

<android.support.design.widget.TabLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="蓝色"
            android:icon="@color/colorPrimary"/>
        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="红色"
            android:icon="@color/colorAccent"/>
    </android.support.design.widget.TabLayout>

如果多默认的TabItem不满,还可以自定义TabItem的布局

<android.support.design.widget.TabItem
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout="@layout/custom_indicator3"
            android:icon="@drawable/three"
            android:text="体育"/>

custom_indicator3.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content">

    <TextView
        android:id="@android:id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        />
    <ImageView
        android:id="@android:id/icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        />
</LinearLayout>

3. Tablayout进阶

3.1 Tab选中监听

Tab切换时,我们需要切换页面的内容,需要为它设置一个监听器Tablayout.OnTabSelectedListener

mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                Log.i(TAG,"onTabSelected:"+tab.getText());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

然后就可以在onTabSelected做对应的逻辑处理了

猜你喜欢

转载自blog.csdn.net/weixin_43499030/article/details/90179867