如何在Android中将TabLayout与ViewPager2一起使用

Ugu*_*rim 18 android android-tablayout androidx android-viewpager2

我想将com.google.android.material.tabs.TabLayout组件与Android的新ViewPager实现一起使用androidx.viewpager2.widget.ViewPager2。但是,setupWithViewPager(..)提供的方法TabLayout仅支持旧的ViewPager实现。有没有一种方法可以轻松地将a绑定TabLayoutViewPager2组件?

Pot*_*ole 30

没有黑客,没有扩展,没有 TabLayoutMediator

我在implementation 'com.google.android.material:material:1.2.0-alpha02'不需要TabLayoutMediator 的情况下执行以下操作。相反,我使用此处描述的方法将 TabLayout 与 ViewPager2 链接。我还在 github此处添加了一个工作示例。我想我已经将解决​​方案最小化为一个最小的工作示例。我将解释重要的部分。

将元素添加到模板

首先,我们需要将 TabLayout 和 ViewPager2 添加到布局中。我已经将它们放置在 LinearLayout 和 CoordinatorLayout 中,当然你可以做任何你喜欢的事情。

<!-- activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:orientation="vertical"
            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"/>
            <androidx.viewpager2.widget.ViewPager2
                android:id="@+id/pager"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>

        </LinearLayout>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)

将适配器连接到 viewpager

所以适配器负责为活动提供正确的片段。您必须扩展FragmentStateAdapter,我已经完成了如下非常简单的操作(它是一个私有类,因为它是在我的 MainActivity.java 中声明的):

    private class ViewStateAdapter extends FragmentStateAdapter {

        public ViewStateAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
            super(fragmentManager, lifecycle);
        }

        @NonNull
        @Override
        public Fragment createFragment(int position) {
            // Hardcoded in this order, you'll want to use lists and make sure the titles match
            if (position == 0) {
                return new BarFragment();
            }
            return new FooFragment();
        }

        @Override
        public int getItemCount() {
            // Hardcoded, use lists
            return 2;
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后我可以将我自己的适配器连接到 ViewPager,如下所示:

FragmentManager fm = getSupportFragmentManager();
ViewStateAdapter sa = new ViewStateAdapter(fm, getLifecycle());
final ViewPager2 pa = findViewById(R.id.pager);
pa.setAdapter(sa);
Run Code Online (Sandbox Code Playgroud)

我已将片段添加到我的 viewpager 中。(因为我在我的适配器中对 Fragments 进行了硬编码,你应该使用一个列表和类似“addFragment”方法之类的东西)

选项卡布局

然后用

TabLayout tabLayout = findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText("Bar"));
tabLayout.addTab(tabLayout.newTab().setText("Foo"));
Run Code Online (Sandbox Code Playgroud)

我在 TabLayout 中添加了两个选项卡,显示了标题但还没有让我切换到片段。

将 TabLayout 连接到适配器

tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                pa.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
Run Code Online (Sandbox Code Playgroud)

这应该很简单。用户单击选项卡,我在回调中获取位置,然后将适配器的当前项目设置为该位置。

滑动时更改 Tab

最后,当用户滑动片段以将正确的选项卡项设置为选中时,我们再次耦合

pa.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
    @Override
    public void onPageSelected(int position) {
        tabLayout.selectTab(tabLayout.getTabAt(position));
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 很好的解决方案!按预期工作。 (2认同)

Nik*_*ski 21

您必须使用 TabLayoutMediator来模拟tabLayout.setupWithViewPager()和设置ViewPager2with Tablayout。否则,您将必须编写自己的适配器,以结合双方。

它的代码在Kotlin中看起来像这样

TabLayoutMediator(tabLayout, viewPager) { tab, position ->
            tab.text = tabTitles[position]
        }.attach()
Run Code Online (Sandbox Code Playgroud)

  • 使用此** TabLayoutMediator **的代码如下:`TabLayoutMediator(tabLayout,viewPager2){tab,position-&gt; viewPager2.setCurrentItem(tab.position,true)if(position == 1)tab.setText(“ Test2” )if(position == 0)tab.setText(“ Test1”)} .attach()` (8认同)
  • `viewPager.setCurrentItem(tab.position, true)` 是不必要的,它会导致选择第二个选项卡并始终滑动页面! (4认同)
  • 阅读此书的任何人都应仔细检查其应用程序的材料库版本。TapLayoutMediator存在于实现com.google.android.material:material:1.1.0-alpha08中,但是android studio默认为导入了版本1.0.0,而我没有此版本。 (2认同)
  • 如何在 TabLayout (如轮播)上设置点,而不是选项卡中的数字? (2认同)

San*_*Sur 11

初始化TabLayoutMediator用的目的对象TabLayoutViewPager2autoRefresh布尔型,和的目的- OnConfigurationChangeCallback

TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager2, true, new TabLayoutMediator.OnConfigureTabCallback() {
     @Override
     public void onConfigureTab(@NotNull TabLayout.Tab tab, int position) {
          // position of the current tab and that tab  
     }
});
Run Code Online (Sandbox Code Playgroud)

最后,只需调用attach()TabLayoutMediator对象即可将TabLayout链接到viewpager:-

 tabLayoutMediator.attach();
Run Code Online (Sandbox Code Playgroud)

autoRefresh-如果设置为-键true(默认情况下设置为true)

RECREATEStabLayout如果if的所有选项卡notifyDataSetChanged被调用到viewpager adapter

使用TabLayoutMediator.java的内容


Nil*_*hod 8

UPDATE

check this Create swipe views with tabs using ViewPager2

Here is the Updated answer How to use TabLayout with ViewPager2 in Android

Now we no need to create a class from TabLayoutMediator

Use below dependencies

implementation 'com.google.android.material:material:1.1.0-alpha08'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta02'
Run Code Online (Sandbox Code Playgroud)

SAMPLE CODE

XMl layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
        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: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"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:layout_scrollFlags="scroll|enterAlways"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

        <com.google.android.material.tabs.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewpager"
            app:layout_anchor="@id/tabs"
            app:layout_anchorGravity="bottom"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
    />


</androidx.coordinatorlayout.widget.CoordinatorLayout>
Run Code Online (Sandbox Code Playgroud)

Activity

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import com.google.android.material.tabs.TabLayoutMediator

import com.google.android.material.tabs.TabLayout


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

//        setSupportActionBar(toolbar)
        viewpager.adapter = AppViewPagerAdapter(supportFragmentManager, lifecycle)

        TabLayoutMediator(tabs, viewpager, object : TabLayoutMediator.OnConfigureTabCallback {
            override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
                // Styling each tab here
                tab.text = "Tab $position"
            }
        }).attach()


    }
}
Run Code Online (Sandbox Code Playgroud)

UPDATE

If your using implementation 'com.google.android.material:material:1.1.0-alpha10' then use below code

        TabLayoutMediator(tabs, viewpage,
        TabLayoutMediator.TabConfigurationStrategy { tab, position ->
            when (position) {
                0 -> { tab.text = "TAB ONE"}
                1 -> { tab.text = "TAB TWO"}
            }
        }).attach()
Run Code Online (Sandbox Code Playgroud)

OUTPUT

在此处输入图片说明

  • 任何阅读本文的人都应该仔细检查其应用程序的材料库版本。这个版本对我有用,但是android studio默认导入了1.0.0版本,但没有这个版本 (3认同)
  • @ Seyid-KananBagirov,它存在于实现'com.google.android.material:material:1.1.0-alpha08'中(请注意版本1.1.0-alpha08而非1.0.0) (3认同)
  • 在1.1.0-alpha10中,他们将“ TabLayoutMediator.OnConfigureTabCallback”重命名为“ TabLayoutMediator.TabConfigurationStrategy” (2认同)

sey*_*gin 8

您可以使用 Kotlin 扩展功能:

fun TabLayout.setupWithViewPager(viewPager: ViewPager2, labels: List<String>) {

    if (labels.size != viewPager.adapter?.itemCount)
        throw Exception("The size of list and the tab count should be equal!")

    TabLayoutMediator(this, viewPager,
        TabLayoutMediator.TabConfigurationStrategy { tab, position ->
            tab.text = labels[position]
        }).attach()
}
Run Code Online (Sandbox Code Playgroud)

并称之为:

 tabLayout.setupWithViewPager(viewPager, listOf("Tab A", "Tab B"))
Run Code Online (Sandbox Code Playgroud)


Mig*_*más 5

如果您使用 JAVA 编码。您可以将以下适配器用于 viewPager2:

public class ViewPagerAdapter extends FragmentStateAdapter {
  private static final int CARD_ITEM_SIZE = 10;
  public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
    super(fragmentActivity);
  }
  @NonNull @Override public Fragment createFragment(int position) {
    return CardFragment.newInstance(position);
  }
  @Override public int getItemCount() {
    return CARD_ITEM_SIZE;
  }
}
Run Code Online (Sandbox Code Playgroud)

在 mainActivity 上,您需要包含以下内容:

@Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    viewPager = findViewById(R.id.view_pager);
    tabLayout = findViewById(R.id.tabs);
    viewPager.setAdapter(new ViewPagerAdapter(this));
    new TabLayoutMediator(tabLayout, viewPager,
        new TabLayoutMediator.TabConfigurationStrategy() {
          @Override public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
            tab.setText("Tab " + (position + 1));
          }
        }).attach();
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这很简单:

java代码:

tabLayout=findViewById(R.id.tabLayout);
    viewPager=findViewById(R.id.viewPager);
    viewPager.setAdapter(new ViewPagerAdapter(this));

    new TabLayoutMediator(tabLayout, viewPager, new TabLayoutMediator.TabConfigurationStrategy() {
        @Override
        public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
            if (position==0){
                tab.setText(R.string.photos);
                tab.view.setBackground(getResources().getDrawable(R.drawable.ic_rectangle_1345));
            }
            else {
                tab.setText(R.string.videos);
            }
        }
    }).attach();

    tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            tab.view.setBackground(getResources().getDrawable(R.drawable.ic_rectangle_1345));
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
            tab.view.setBackgroundColor(Color.TRANSPARENT);
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });
Run Code Online (Sandbox Code Playgroud)

适配器:

public class ViewPagerAdapter extends FragmentStateAdapter {
public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
    super(fragmentActivity);
}

@NonNull
@Override
public Fragment createFragment(int position) {
    if (position==0) {
        return new PhotosFragment();
    }
    else {
        return new VideosFragment();
    }
}

@Override
public int getItemCount() {
    return 2;
}}
Run Code Online (Sandbox Code Playgroud)

XML:

<com.google.android.material.tabs.TabLayout
    android:id="@+id/tabLayout"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:background="@color/tool_bar_bg"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/collection_bar" />

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/tabLayout" />
Run Code Online (Sandbox Code Playgroud)