初学者入门:Android 实现 Tab 点击切换(TabLayout + ViewPager2)

在 Android 开发中,Tab 切换是常见的 UI 交互场景(如首页分类、我的页面选项卡等)。本文将以 TabLayout + ViewPager2 组合为例,带初学者一步步实现 Tab 点击切换功能,适配 Android Studio 2025minSdk 26,使用 Java 语言开发,流程清晰且易上手。

一、项目背景

配置项 具体信息
开发工具 Android Studio 2025
最小兼容版本 minSdk = 26(Android 8.0)
开发语言 Java
核心组件 TabLayout + ViewPager2
依赖版本 androidx.viewpager2:viewpager2:1.1.0

二、实现步骤(详细版)

1. 配置 ViewPager2 依赖

首先需要在项目中引入 ViewPager2 的官方依赖,用于承载 Tab 对应的内容页面。

操作步骤:

  1. 打开项目的 app/build.gradle.kts(或 build.gradle,根据项目结构选择);

  2. dependencies 闭包中添加 ViewPager2 依赖;

  3. 点击编辑器右上角的 Sync Now 按钮,下载并同步依赖。

kotlin

scss 复制代码
// app/build.gradle.kts
dependencies {
    // ViewPager2 核心依赖(用于内容页面切换)
    implementation("androidx.viewpager2:viewpager2:1.1.0")
    // Material Design 依赖(包含 TabLayout,若项目已引入可忽略)
    implementation("com.google.android.material:material:1.12.0")
}

⚠️ 注意:若项目未引入 Material Design 依赖,TabLayout 会报错,需补充上述 material 依赖。

2. 编写布局文件

需创建两个核心布局:

  • Activity 布局:包含 TabLayout(顶部选项卡)和 ViewPager2(内容容器);
  • Fragment 布局:每个 Tab 对应的内容页面(如 "平台数据""平台日志" 页面)。

2.1 Activity 主布局(activity_main.xml)

采用垂直 LinearLayout 布局,TabLayout 在上,ViewPager2 在下(占满剩余空间)。

xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/main_gradient" <!-- 可选:背景渐变,若无可删 -->
    tools:context=".MainActivity">

    <!-- 1. TabLayout:顶部选项卡 -->
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent" <!-- 原200dp改为match_parent,适配全屏 -->
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        app:tabSelectedTextColor="@color/blue" <!-- 选中Tab的文字颜色 -->
        app:tabTextColor="@color/black" <!-- 未选中Tab的文字颜色 -->
        app:tabIndicatorColor="@color/blue" <!-- 选中Tab的下划线颜色 -->
        app:tabIndicatorHeight="2dp" <!-- 下划线高度 -->
        app:tabMode="fixed" <!-- Tab固定排列(适合少量Tab) -->
        app:tabPaddingHorizontal="20dp" <!-- Tab左右内边距,避免拥挤 -->
        app:tabTextSize="16sp" /> <!-- 文字大小 -->

    <!-- 2. ViewPager2:内容容器(占满剩余空间) -->
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" /> <!-- 用weight占满剩余高度 -->

</LinearLayout>

2.2 Fragment 内容布局(2 个)

创建两个 Fragment 布局,分别对应 "平台数据" 和 "平台日志" 页面(结构类似,仅内容区分)。

(1)平台数据 Fragment 布局(fragment_platform_data.xml)

xml

ini 复制代码
<?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:background="@color/white">

    <TextView
        android:id="@+id/tv_platform_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="平台数据页面"
        android:textSize="18sp"
        android:textColor="@color/black" />

</LinearLayout>
(2)平台日志 Fragment 布局(fragment_platform_log.xml)

xml

ini 复制代码
<?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:background="@color/white">

    <TextView
        android:id="@+id/tv_platform_log"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="平台日志页面"
        android:textSize="18sp"
        android:textColor="@color/black" />

</LinearLayout>

2.3 补充颜色资源(colors.xml)

res/values/colors.xml 中定义用到的颜色(确保与布局中的颜色引用对应):

xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 基础颜色 -->
    <color name="black">#000000</color>
    <color name="blue">#37A6EB</color> <!-- Tab选中色/下划线色 -->
    <color name="white">#FFFFFF</color>
    <color name="gray">#545454</color>
    <color name="light_gray">#F5F5F5</color>

    <!-- 主题颜色(适配Material Design) -->
    <color name="colorPrimary">#37A6EB</color>
    <color name="colorPrimaryDark">#0277BD</color>
    <color name="colorAccent">#FF4081</color>
</resources>

3. 创建 Fragment 逻辑类

Fragment 是 ViewPager2 承载的内容单元,需创建两个 Fragment 类,分别关联上述布局。

3.1 平台数据 Fragment(PlatformDataFragment.java)

java

运行

scala 复制代码
package com.example.lionlite_user_app;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;

public class PlatformDataFragment extends Fragment {

    // 实例化方法(可选:用于传递参数,初学者可先保留)
    public static PlatformDataFragment newInstance() {
        return new PlatformDataFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // 关联Fragment布局
        View view = inflater.inflate(R.layout.fragment_platform_data, container, false);
        // 若需修改TextView内容,可在此处初始化(示例)
        // TextView tvData = view.findViewById(R.id.tv_platform_data);
        // tvData.setText("自定义平台数据内容");
        return view;
    }
}

3.2 平台日志 Fragment(PlatformLogFragment.java)

⚠️ 注意:原内容中此类代码复制错误(类名重复),以下为修正版:

java

运行

scala 复制代码
package com.example.lionlite_user_app;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;

public class PlatformLogFragment extends Fragment {

    // 实例化方法
    public static PlatformLogFragment newInstance() {
        return new PlatformLogFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // 关联Fragment布局(注意是fragment_platform_log)
        View view = inflater.inflate(R.layout.fragment_platform_log, container, false);
        return view;
    }
}

4. 编写 ViewPager2 适配器(TabPagerAdapter.java)

适配器用于将 Fragment 与 ViewPager2 绑定,负责创建 Fragment、返回 Tab 数量和标题。

java

运行

java 复制代码
package com.example.lionlite_user_app;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import java.util.ArrayList;
import java.util.List;

public class TabPagerAdapter extends FragmentStateAdapter {

    // 1. 存储 Tab 标题和对应的 Fragment
    private final List<String> tabTitles = new ArrayList<>();
    private final List<Fragment> tabFragments = new ArrayList<>();

    // 2. 构造方法(接收宿主Activity)
    public TabPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
        super(fragmentActivity);
        // 初始化 Tab 数据(标题 + Fragment 对应)
        initTabData();
    }

    // 3. 初始化 Tab 标题和 Fragment
    private void initTabData() {
        tabTitles.add("平台数据");
        tabFragments.add(PlatformDataFragment.newInstance());

        tabTitles.add("平台日志");
        tabFragments.add(PlatformLogFragment.newInstance());
    }

    // 4. 创建对应位置的 Fragment(核心方法)
    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return tabFragments.get(position);
    }

    // 5. 返回 Tab 总数(ViewPager2 页数)
    @Override
    public int getItemCount() {
        return tabFragments.size();
    }

    // 6. 提供 Tab 标题(给 TabLayout 调用)
    public String getTabTitle(int position) {
        return tabTitles.get(position);
    }
}

5. 关联 TabLayout 与 ViewPager2(MainActivity.java)

在 MainActivity 中完成 TabLayout 和 ViewPager2 的绑定,实现 "点击 Tab 切换页面""滑动页面切换 Tab" 的联动效果。

java

运行

scala 复制代码
package com.example.lionlite_user_app;

import android.os.Bundle;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 启用EdgeToEdge(沉浸式状态栏,可选)
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);

        // 处理状态栏内边距(避免内容被状态栏遮挡)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        // 1. 初始化控件
        TabLayout tabLayout = findViewById(R.id.tab_layout);
        ViewPager2 viewPager = findViewById(R.id.view_pager);

        // 2. 给 ViewPager2 设置适配器
        TabPagerAdapter adapter = new TabPagerAdapter(this);
        viewPager.setAdapter(adapter);

        // 3. 关联 TabLayout 和 ViewPager2(核心:实现联动)
        new TabLayoutMediator(
                tabLayout,          // 要关联的 TabLayout
                viewPager,          // 要关联的 ViewPager2
                (tab, position) -> { // 回调:给每个 Tab 设置标题
                    tab.setText(adapter.getTabTitle(position));
                }
        ).attach(); // ⚠️ 必须调用 attach(),否则绑定失败
    }
}

三、常见问题排查(初学者必看)

  1. TabLayout 找不到类?
    → 检查是否引入 Material Design 依赖(见步骤 1 的 material 依赖)。
  2. Fragment 布局不显示?
    → 确认 Fragment 中 inflate 的布局文件名正确(如 fragment_platform_log 而非 fragment_platform_data)。
  3. Tab 点击无反应?
    → 检查是否调用 TabLayoutMediatorattach() 方法(步骤 5 的关键代码)。
  4. ViewPager2 滑动卡顿?
    → 避免在 Fragment 的 onCreateView 中做耗时操作(如网络请求),可延迟初始化。

四、扩展优化(进阶方向)

  1. 修改 Tab 样式 :如添加图标(tab.setIcon(R.drawable.ic_data))、修改选中背景色;
  2. 添加切换动画 :通过 viewPager.setPageTransformer() 自定义页面切换动画;
  3. 支持更多 Tab :将 app:tabMode="fixed" 改为 app:tabMode="scrollable",实现可滚动的 Tab;
  4. 保存 Fragment 状态 :在 ViewPager2 中设置 viewPager.setOffscreenPageLimit(2)(缓存 2 个页面,避免切换时重建)。

五、总结

本文通过 5 个核心步骤 实现了 Tab 切换功能,核心逻辑是:
TabLayout(用户交互)TabLayoutMediator(联动桥梁)ViewPager2(内容容器)TabPagerAdapter(数据适配)Fragment(内容单元)

相关推荐
superlls2 分钟前
(Redis)缓存三大问题及布隆过滤器详解
java·后端·spring
阿里嘎多哈基米33 分钟前
二、JVM 入门——(三)栈
java·开发语言·jvm·线程·
lovebugs40 分钟前
🚀 Kubernetes核心命令详解:Java开发者必备指南
java·后端·kubernetes
CYRUS_STUDIO44 分钟前
手把手教你改造 AAR:解包、注入逻辑、重打包,一条龙玩转第三方 SDK!
android·逆向
快乐肚皮1 小时前
IntelliJ IDEA Debug 模式功能指南
java·ide·intellij-idea·debug
_風箏1 小时前
SpringBoot【ElasticSearch集成 02】Java HTTP Rest client for ElasticSearch Jest 客户端集成
java·后端·elasticsearch
野犬寒鸦1 小时前
力扣hot100:字母异位词分组和最长连续序列(49,128)
java·数据结构·后端·算法·哈希算法
浮游本尊1 小时前
Java学习第14天 - 微服务架构与Spring Cloud
java
CYRUS_STUDIO1 小时前
Android 源码如何导入 Android Studio?踩坑与解决方案详解
android·android studio·源码阅读
燃尽余火1 小时前
Knife4j 文档展示异常的小坑
java·开发语言·spring