Bootstrap

Android 实现首页Tab切换并且支持懒加载功能详解

1. 添加依赖

在 build.gradle 文件中添加以下依赖:

implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
implementation 'com.google.android.material:material:1.6.1'

2. 布局文件

在 res/layout/activity_main.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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabGravity="fill"
        app:tabMode="fixed" />

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager2"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

3. 创建 Fragment

创建多个 Fragment 用于展示不同的页面内容,以 HomeFragment 为例:

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

public class HomeFragment extends Fragment {

    private boolean isLoaded = false;

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

    @Override
    public void onResume() {
        super.onResume();
        if (!isLoaded && isVisible()) {
            loadData();
            isLoaded = true;
        }
    }

    private void loadData() {
        // 这里进行数据加载操作,例如网络请求等
    }
}

对应的 fragment_home.xml 布局文件:

<?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="vertical">

    <TextView
        android:text="Home Page"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="24sp" />
</LinearLayout>

4. 创建适配器

创建一个继承自 FragmentStateAdapter 的适配器类:

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 MyFragmentStateAdapter extends FragmentStateAdapter {

    private final List<Fragment> fragmentList = new ArrayList<>();

    public MyFragmentStateAdapter(@NonNull FragmentActivity fragmentActivity) {
        super(fragmentActivity);
    }

    public void addFragment(Fragment fragment) {
        fragmentList.add(fragment);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return fragmentList.get(position);
    }

    @Override
    public int getItemCount() {
        return fragmentList.size();
    }
}

5. 在 MainActivity 中设置 TabLayout 和 ViewPager2

import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import android.os.Bundle;
import android.graphics.drawable.Drawable;
import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {

    private TabLayout tabLayout;
    private ViewPager2 viewPager2;

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

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

        MyFragmentStateAdapter adapter = new MyFragmentStateAdapter(this);
        adapter.addFragment(new HomeFragment());
        adapter.addFragment(new DiscoverFragment());
        adapter.addFragment(new ProfileFragment());

        viewPager2.setAdapter(adapter);

        new TabLayoutMediator(tabLayout, viewPager2, (tab, position) -> {
            switch (position) {
                case 0:
                    tab.setText("Home");
                    Drawable homeIcon = ContextCompat.getDrawable(this, R.drawable.ic_home);
                    tab.setIcon(homeIcon);
                    break;
                case 1:
                    tab.setText("Discover");
                    Drawable discoverIcon = ContextCompat.getDrawable(this, R.drawable.ic_discover);
                    tab.setIcon(discoverIcon);
                    break;
                case 2:
                    tab.setText("Profile");
                    Drawable profileIcon = ContextCompat.getDrawable(this, R.drawable.ic_profile);
                    tab.setIcon(profileIcon);
                    break;
            }
        }).attach();
    }
}

运行该应用后,你会看到一个带有图片和文字的 TabLayout,同时可以通过点击 Tab 或者左右滑动屏幕来切换不同的页面,并且每个 Fragment 会在第一次可见时进行数据加载,实现了懒加载的功能。

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;