📅  最后修改于: 2023-12-03 15:08:33.162000             🧑  作者: Mango
在 Android 应用中,TabLayout 是非常常用的控件之一,它通常用于展示具有固定数量的选项卡,而这些选项卡通常是提前在 XML 布局文件中定义好的。但在某些情况下,我们需要动态地添加选项卡,这可能会比较困难,本文将介绍如何在 Android 中实现动态 TabLayout。
我们可以通过 TabLayout.addTab(TabLayout.Tab)
方法添加 Tab,但是要动态添加 Tab,我们需要借助 ViewPager 来管理 Tab,同时使用 FragmentPagerAdapter 或 FragmentStatePagerAdapter 来填充 Tab 的内容。以下是实现步骤:
创建布局文件,包含一个 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 放在了其中。
创建一个 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 和对应的标题。
在 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);
添加 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()
方法实现。
定义一个布局文件作为 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 的图标和文本。
在 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 的功能。
在实现时,我们需要注意以下几点:
setCustomView()
方法。完整代码片段见 GitHub。
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);
}
}