Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách tạo Tab Layout trong ứng dụng Android

Hướng dẫn này trình bày cách tạo Tab Layout kết hợp với ViewPager trong Android sử dụng Material Design Components. Tab Layout cho phép chuyển đổi giữa các trang (Fragment) bằng cách nhấn vào tab hoặc vuốt ngang.

Các bước thực hiện

Bước 1: Tạo dự án mới

Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.

Bước 2: Thêm dependency (build.gradle Module:app)

dependencies {
    // Material Components (bao gồm TabLayout, ViewPager2)
    implementation 'com.google.android.material:material:1.9.0'

    // Fragment & ViewPager2 (AndroidX)
    implementation 'androidx.fragment:fragment:1.6.1'
    implementation 'androidx.viewpager2:viewpager2:1.0.0'
}
Lưu ý: Code gốc dùng android.support.design:design:28.0.0 (thư viện Support cũ, đã ngừng hỗ trợ). Phiên bản trên dùng AndroidX + Material Components hiện đại.

Bước 3: Layout chính (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            app:tabTextColor="?attr/colorOnSurface"
            app:tabSelectedTextColor="?attr/colorOnPrimary"
            app:tabIndicatorColor="?attr/colorOnPrimary"
            app:tabGravity="fill"
            app:tabMode="fixed" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Bước 4: MainActivity (src/MainActivity.java)

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;

public class MainActivity extends AppCompatActivity {
    TabLayout tabLayout;
    ViewPager2 viewPager;

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

        tabLayout = findViewById(R.id.tabLayout);
        viewPager = findViewById(R.id.viewPager);

        // Adapter cho ViewPager2
        MyAdapter adapter = new MyAdapter(this);
        viewPager.setAdapter(adapter);

        // TabLayoutMediator: Kết nối TabLayout với ViewPager2 (thay thế TabLayout.OnTabSelectedListener + ViewPager.addOnPageChangeListener)
        new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
            switch (position) {
                case 0: tab.setText("Bóng đá"); break;
                case 1: tab.setText("Cricket"); break;
                case 2: tab.setText("NBA"); break;
            }
        }).attach();
    }
}

Bước 5: Adapter cho ViewPager2 (MyAdapter.java)

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;

public class MyAdapter extends FragmentStateAdapter {
    private static final int TAB_COUNT = 3;

    public MyAdapter(FragmentActivity fa) {
        super(fa);
    }

    @Override
    public Fragment createFragment(int position) {
        switch (position) {
            case 0: return new FootballFragment();
            case 1: return new CricketFragment();
            case 2: return new NbaFragment();
            default: return new FootballFragment();
        }
    }

    @Override
    public int getItemCount() {
        return TAB_COUNT;
    }
}

Bước 6: Tạo 3 Fragment

Click chuột phải package → New → Fragment → Fragment (Blank)

a) FootballFragment.java

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

public class FootballFragment extends Fragment {
    public FootballFragment() {}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_football, container, false);
    }
}

fragment_football.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="⚽ Football Fragment"
        android:textSize="24sp"
        android:textStyle="bold" />

</FrameLayout>

b) CricketFragment.java / fragment_cricket.xml

// Java: CricketFragment.java - tương tự, return R.layout.fragment_cricket
// XML: fragment_cricket.xml - TextView "🏏 Cricket Fragment"

c) NbaFragment.java / fragment_nba.xml

// Java: NbaFragment.java - tương tự, return R.layout.fragment_nba
// XML: fragment_nba.xml - TextView "🏀 NBA Fragment"

Bước 7: Cấu hình AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="com.example.tablayoutdemo">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MaterialComponents.DayNight.NoActionBar">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Chạy ứng dụng

Kết nối thiết bị, nhấn Run. 3 tab hiển thị ở đầu. Vuốt ngang hoặc nhấn tab để chuyển Fragment.

Cách tạo Tab Layout trong ứng dụng Android Cách tạo Tab Layout trong ứng dụng Android Cách tạo Tab Layout trong ứng dụng Android

TabLayoutMediator vs Cách cũ

Cách cũ (ViewPager + TabLayout) Cách mới (ViewPager2 + TabLayoutMediator)
PagerAdapter / FragmentPagerAdapter FragmentStateAdapter (ViewPager2)
viewPager.addOnPageChangeListener Tự động sync qua Mediator
tabLayout.addOnTabSelectedListener Tự động sync qua Mediator
setOffscreenPageLimit thủ công Mặc định cache tốt hơn
Khó RTL, vertical Hỗ trợ RTL, vertical, diff util

Tùy chỉnh Tab Layout

1. Tab với Icon

new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
    tab.setText(titles[position]);
    tab.setIcon(icons[position]); // Drawable resource
}).attach();

2. Custom Tab View (Layout tùy chỉnh hoàn toàn)

tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabMode(TabLayout.MODE_FIXED);

// Inflate custom view cho từng tab
for (int i = 0; i < tabLayout.getTabCount(); i++) {
    TabLayout.Tab tab = tabLayout.getTabAt(i);
    if (tab != null) {
        View customView = LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
        TextView tv = customView.findViewById(R.id.tabText);
        ImageView iv = customView.findViewById(R.id.tabIcon);
        tv.setText(titles[i]);
        iv.setImageResource(icons[i]);
        tab.setCustomView(customView);
    }
}

3. Scrollable Tabs (nhiều tab)

app:tabMode="scrollable" // Thay vì fixed

Tóm tắt

  • Dùng ViewPager2 + TabLayoutMediator (Material Components 1.1+)
  • Adapter kế thừa FragmentStateAdapter
  • FragmentStateAdapter tự động hủy Fragment không hiển thị (tiết kiệm bộ nhớ)
  • TabLayout thuộc AppBarLayout để có hiệu ứng cuộn (collapsing toolbar)
  • Theme: Theme.MaterialComponents.DayNight.NoActionBar