icode icode
首页
  • Android学习

    • 📁基础内容
    • 📺AndroidCore
    • 🎨Android-UI
    • 🏖️Components
    • 📊Fragment
    • 🔗网络操作
    • 🔏异步机制
    • 📦数据存储
    • 🗃️Gradle
  • 学习笔记

    • 『框架』笔记
    • 『Kotlin』笔记
    • 《Vue》笔记
    • 《Git》学习笔记
    • 『Bug踩坑记录』
  • ListView
  • RecyclerView
  • ViewPager
  • Java笔记

    • 🟠JavaSE
    • 🟢JavaWeb
    • 🔴JavaEE
    • ⚪JavaTopic
    • 🍳设计模式
  • 计算机基础

    • 📌计算机网络
    • 🔍数据结构
    • 📦数据库
    • 💻OS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
  • 关于

    • 📫关于我
  • 收藏

    • 网站
    • 资源
    • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

iqqcode

保持对技术的探索实践与热爱
首页
  • Android学习

    • 📁基础内容
    • 📺AndroidCore
    • 🎨Android-UI
    • 🏖️Components
    • 📊Fragment
    • 🔗网络操作
    • 🔏异步机制
    • 📦数据存储
    • 🗃️Gradle
  • 学习笔记

    • 『框架』笔记
    • 『Kotlin』笔记
    • 《Vue》笔记
    • 《Git》学习笔记
    • 『Bug踩坑记录』
  • ListView
  • RecyclerView
  • ViewPager
  • Java笔记

    • 🟠JavaSE
    • 🟢JavaWeb
    • 🔴JavaEE
    • ⚪JavaTopic
    • 🍳设计模式
  • 计算机基础

    • 📌计算机网络
    • 🔍数据结构
    • 📦数据库
    • 💻OS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
  • 关于

    • 📫关于我
  • 收藏

    • 网站
    • 资源
    • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • ListView

  • RecyclerView

  • ViewPager

    • ViewPager基础
    • 用ViewPager偏移看到下一页部分内容
    • 结合TabLayout使用
      • 前言
        • 各种使用场景:
    • ViewPager注意事项
    • androidclipChildren属性
  • Component
  • ViewPager
iqqcode
2021-06-02
目录

结合TabLayout使用

# 前言

Tablayout继承自HorizontalScrollView,用作页面切换指示器,因使用简便功能强大而广泛使用在App中。

但有的产品经理偏偏是个磨人的小妖精,真的猜不透啊,今天要这种效果,明天就指着另一款App说做成跟这个一样。对付这种产品经理我们有骨气的程序员该怎么办?怎么办?当然是屈服啊,不然去跳楼让他因内疚改需求? 所以,就在各种复杂的情况下打磨,渐渐地就变得圆润。这里,有Tablayout的各种使用场景,拿去指着产品经理说:你要哪个给你哪个。

github代码直通车 (opens new window)

先上效果图:分别为设置tab属性、去掉指示线、设置指示线长度、设置图标tab、超出屏幕滚动tab

img

使用场景

# 常用属性:
app:tabIndicatorColor :指示线的颜色
app:tabIndicatorHeight :指示线的高度
app:tabSelectedTextColor : tab选中时的字体颜色
app:tabMode="scrollable" : 默认是fixed,固定的;scrollable:可滚动的
1
2
3
4

# 各种使用场景:

# 1.默认使用样式,结合Viewpager使用:

效果图:

img

giphy.gif

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"/>


    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

MainActivity使用:根据title长度,设置文字title,设置fragment,设置viewpager联动,使用的是Tablayout默认属性。

import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.example.tablayoutusecase.R;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    private TabLayout tabLayout;
    private ViewPager viewPager;
    private FmPagerAdapter pagerAdapter;
    private ArrayList<Fragment> fragments = new ArrayList<>();
    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);
        viewPager = (ViewPager) findViewById(R.id.viewpager);

        for(int i=0;i<titles.length;i++){
            fragments.add(new TabFragment());
            tabLayout.addTab(tabLayout.newTab());
        }

        tabLayout.setupWithViewPager(viewPager,false);
        pagerAdapter = new FmPagerAdapter(fragments,getSupportFragmentManager());
        viewPager.setAdapter(pagerAdapter);

        for(int i=0;i<titles.length;i++){
            tabLayout.getTabAt(i).setText(titles[i]);
        }
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 2.设置Tablayout属性:

效果图:

img

image.png

用Tablayout属性写一个style,给需要的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>
1
2
3
4
5
6
7
8

Tablayout引用:

    <android.support.design.widget.TabLayout
        android:id="@+id/tab1"
        style="@style/MyTablayoutstyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
1
2
3
4
5
# 3.Tablayout去掉指示线:

img

image.png

这种很easy,给tabIndicatorHeight属性设置0dp,或者给tabSelectedTextColor属性设置透明,就不显示指示线了。

# 4.修改指示线长度:

img

image.png

怎么办呢,在布局里怎么打也打不出来这个所谓的”tabIndicatorWidth“属性,那就点进去Tablayout类里面找,看它是怎么实现指示线的。

找到有如下属性,即有SlidingTabStrip内部类:

    private final SlidingTabStrip mTabStrip;
1

img

image.png

通过阅读发现该类就是设置指示线的,继承于Linearylayout。那么我们可以通过反射获取Tablayout的mTabStrip,循环获取到子view,设置leftMargin,rightMargin就可以压缩tab的宽度了。

一不做二不休,IndicatorLineUtil实现类:

import android.content.res.Resources;
import android.support.design.widget.TabLayout;
import android.util.TypedValue;
import android.view.View;
import android.widget.LinearLayout;
import java.lang.reflect.Field;

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


    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

tablayout调用此方法:注意:margin数值不能设置过大,不然tab宽度压缩为0整个tablayout就不显示了。

        tab3.post(new Runnable() {
            @Override
            public void run() {
                IndicatorLineUtil.setIndicator(tab3, 40, 40);
            }
        });
1
2
3
4
5
6
# 5.设置默认图标:

img

image.png

still easy,Tablayout自带了setIcon()方法设置图标资源,不过这中效果很别扭,脸被拉长了。不服,就自己造一个啊,造就造! tabLayout.getTabAt(i).setText(titles[i]).setIcon(pics[i]);

# 6.自己造tab样式:

img

image.png

创建图标和文字布局:

<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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

这里是图标居左,那我要改为图标上下左右呢?都自定义view了,你上天都行。

    /**
     * 设置自定义位置图标
     */
    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;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 7.tab数量太多,超出屏幕,就像今日头条的分类一样,那就挤在一起了啊。不怕,我们有app:tabMode="scrollable" 属性,让Tablayout变得可滚动,可超出屏幕。

img

image.png

布局引入:

    <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"/>
1
2
3
4
5
6
7
8
# 最后大合唱完整Activity:
import android.support.design.widget.TabLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.tablayoutusecase.R;

public class SetStyleActivity extends AppCompatActivity {
    private TabLayout tab1,tab2,tab3;
    private TabLayout tabLayout,tabLayout2,tabLayout3;
    private String[] titles = new String[]{"最新","热门","我的"};
    private String[] longTitles = new String[]{"推荐","热点","北京","视频","社会","图片","娱乐","科技","汽车"};
    private int[] pics = new int[]{R.mipmap.subtitle_left_roll_h,R.mipmap.subtitle_middle_roll_h,R.mipmap.subtitle_right_roll_h};

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

        setTab1();
        setTab2();
        setTab3();
        setDefaultIcon();
        setCustomIcon();
        setScroll();
    }

    private void setTab1(){
        tab1 = (TabLayout) findViewById(R.id.tab1);
        for(int i=0;i<titles.length;i++){
            tab1.addTab(tab1.newTab());
            tab1.getTabAt(i).setText(titles[i]);
        }
    }

    private void setTab2(){
        tab2 = (TabLayout) findViewById(R.id.tab2);
        for(int i=0;i<titles.length;i++){
            tab2.addTab(tab2.newTab());
            tab2.getTabAt(i).setText(titles[i]);
        }
    }

    private void setTab3(){
        tab3 = (TabLayout) findViewById(R.id.tab3);
        for(int i=0;i<titles.length;i++){
            tab3.addTab(tab3.newTab());
            tab3.getTabAt(i).setText(titles[i]);
        }

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

    /**
     * 设置默认图标
     */
    private void setDefaultIcon() {

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

        for(int i=0;i<titles.length;i++){
            tabLayout.getTabAt(i).setText(titles[i]).setIcon(pics[i]);
        }
    }

    /**
     * 设置自定义位置图标
     */
    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));
        }
    }

    private void setScroll(){
        tabLayout3 = (TabLayout) findViewById(R.id.tablayout3);
        for(int i=0;i<longTitles.length;i++){
            tabLayout3.addTab(tabLayout3.newTab());
        }

        for(int i=0;i<longTitles.length;i++){
            tabLayout3.getTabAt(i).setText(longTitles[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;
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

另外,我用过这个XTablayout (opens new window) 效果也还不错,可以自定义分割线,指示线长度,字体加粗等功能。

我明明是个程序员,却怎么要老是做图,蓝瘦香菇。 好了,Tablayout各种使用场景就讲解完了,代码在顶端。觉得有用的话关注我一起学习吧。

  • 作者:奔跑吧李博
  • 链接:https://www.jianshu.com/p/fde38f367019
编辑 (opens new window)
上次更新: 2021/06/02, 10:01:48
用ViewPager偏移看到下一页部分内容
ViewPager注意事项

← 用ViewPager偏移看到下一页部分内容 ViewPager注意事项→

最近更新
01
匿名内部类
10-08
02
函数式接口
10-08
03
ARouter-Kotlin踩坑
10-05
更多文章>
Theme by Vdoing | Copyright © 2021-2023 iqqcode | MIT License | 备案号-京ICP备2021028793号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×