📌  相关文章
📜  如何在 Android 中实现动态 TabLayout?(1)

📅  最后修改于: 2023-12-03 15:08:33.162000             🧑  作者: Mango

如何在 Android 中实现动态 TabLayout?

在 Android 应用中,TabLayout 是非常常用的控件之一,它通常用于展示具有固定数量的选项卡,而这些选项卡通常是提前在 XML 布局文件中定义好的。但在某些情况下,我们需要动态地添加选项卡,这可能会比较困难,本文将介绍如何在 Android 中实现动态 TabLayout。

基本思路

我们可以通过 TabLayout.addTab(TabLayout.Tab) 方法添加 Tab,但是要动态添加 Tab,我们需要借助 ViewPager 来管理 Tab,同时使用 FragmentPagerAdapter 或 FragmentStatePagerAdapter 来填充 Tab 的内容。以下是实现步骤:

  1. 创建布局文件,包含一个 TabLayout 和一个 ViewPager:

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        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"
                app:tabMode="scrollable"
                app:tabGravity="fill" />
    
        </com.google.android.material.appbar.AppBarLayout>
    
        <androidx.viewpager.widget.ViewPager
            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>
    

    在布局文件中,我们定义了一个 CoordinatorLayout ,将 TabLayout 和 ViewPager 放在了其中。

  2. 创建一个 FragmentPagerAdapter 或 FragmentStatePagerAdapter 类:

    public class PagerAdapter extends FragmentPagerAdapter {
    
        private List<Fragment> mFragments = new ArrayList<>();
        private List<String> mTitles = new ArrayList<>();
    
        public PagerAdapter(FragmentManager fm) {
            super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
        }
    
        public void addFragment(Fragment fragment, String title) {
            mFragments.add(fragment);
            mTitles.add(title);
            notifyDataSetChanged();
        }
    
        @NonNull
        @Override
        public Fragment getItem(int position) {
            return mFragments.get(position);
        }
    
        @Override
        public int getCount() {
            return mFragments.size();
        }
    
        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
            return mTitles.get(position);
        }
    }
    

    在 PagerAdapter 中,我们维护了一个 Fragment 列表和一个标题列表,可以通过 addFragment() 方法添加 Fragment 和对应的标题。

  3. 在 Activity 中初始化 ViewPager 和 TabLayout,并为 ViewPager 设置适配器:

    ViewPager viewPager = findViewById(R.id.viewPager);
    TabLayout tabLayout = findViewById(R.id.tabLayout);
    
    PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
    viewPager.setAdapter(pagerAdapter);
    
    tabLayout.setupWithViewPager(viewPager);
    
  4. 添加 Tab,从而动态的生成选项卡:

    pagerAdapter.addFragment(new Fragment(), "Tab 1");
    pagerAdapter.addFragment(new Fragment(), "Tab 2");
    pagerAdapter.addFragment(new Fragment(), "Tab 3");
    

    通过 pagerAdapter.addFragment() 方法添加 Fragment 和标题,然后调用 notifyDataSetChanged() 更新 ViewPager。

支持纯文本和图标

有时候,我们可能需要在 Tab 中添加纯文本或图标,这可以通过 Tab 的 setCustomView() 方法实现。

  1. 定义一个布局文件作为 Tab 的自定义视图:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <ImageView
            android:id="@+id/tabIcon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="8dp" />
    
        <TextView
            android:id="@+id/tabText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@android:color/black"
            android:textSize="12sp"
            android:textStyle="bold" />
    
    </LinearLayout>
    

    在这个布局文件中,我们定义了一个 ImageView 和一个 TextView,用于显示 Tab 的图标和文本。

  2. 在 TabLayout 中添加 Tab:

    View tabView = LayoutInflater.from(this).inflate(R.layout.tab_layout, null);
    ImageView tabIcon = tabView.findViewById(R.id.tabIcon);
    TextView tabText = tabView.findViewById(R.id.tabText);
    
    tabIcon.setImageResource(R.drawable.ic_home);
    tabText.setText("Tab 1");
    
    TabLayout.Tab tab = tabLayout.newTab();
    tab.setCustomView(tabView);
    tabLayout.addTab(tab);
    

    在这个例子中,我们首先通过 LayoutInflater.from() 方法加载自定义视图的布局文件,然后使用 findViewById() 方法获取 ImageView 和 TextView 实例,并分别给它们设置图标和文本。最后,将自定义视图设置给 Tab 并添加到 TabLayout 中。

总结

通过 ViewPager 和 PagerAdapter,我们可以很方便地实现动态 TabLayout 的功能。

在实现时,我们需要注意以下几点:

  • 为了可以动态添加 Tab,需要使用 ViewPager 和 PagerAdapter;
  • 可以通过 Fragment 或自定义布局文件实现 Tab 内容的切换;
  • 实现纯文本或图片等自定义 Tab 内容,需要使用 Tab 的 setCustomView() 方法。

完整代码片段见 GitHub

参考资料
Code Block
public class PagerAdapter extends FragmentPagerAdapter {

   private List<Fragment> mFragments = new ArrayList<>();
   private List<String> mTitles = new ArrayList<>();

   public PagerAdapter(FragmentManager fm) {
       super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
   }

   public void addFragment(Fragment fragment, String title) {
       mFragments.add(fragment);
       mTitles.add(title);
       notifyDataSetChanged();
   }

   @NonNull
   @Override
   public Fragment getItem(int position) {
       return mFragments.get(position);
   }

   @Override
   public int getCount() {
       return mFragments.size();
   }

   @Nullable
   @Override
   public CharSequence getPageTitle(int position) {
       return mTitles.get(position);
   }
}