Je veux utiliser com.google.android.material.tabs.TabLayout
avec le nouveau composant Android ViewPager
mise en œuvre androidx.viewpager2.widget.ViewPager2
. Cependant, le setupWithViewPager(..)
méthode fournie par TabLayout
ne supporte que l'ancien ViewPager
mise en œuvre. Existe-t-il un moyen de lier un TabLayout
à un ViewPager2
facilement ?
Réponses
Trop de publicités?Vous devez utiliser ce TabLayoutMediator
qui imite tabLayout.setupWithViewPager()
et met en place le ViewPager2
avec Tablayout
. Sinon, vous devrez rédiger votre propre adaptateur qui combinera les deux parties.
Son code ressemblera à ceci en kotlin
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = tabTitles[position]
}.attach()
UPDATE
Vérifiez ceci Créer des vues glissantes avec des onglets en utilisant ViewPager2
Voici la réponse mise à jour Comment utiliser TabLayout avec ViewPager2 dans Android ?
Maintenant, nous n'avons pas besoin de créer une classe à partir de TabLayoutMediator
Utilisez ci-dessous dependencies
implementation 'com.google.android.material:material:1.1.0-alpha08'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta02'
CODE ÉCHANTILLON
Mise en page XMl
<?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>
Activité
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()
}
}
UPDATE
Si vous utilisez implementation 'com.google.android.material:material:1.1.0-alpha10'
puis utilisez le code ci-dessous
TabLayoutMediator(tabs, viewpage,
TabLayoutMediator.TabConfigurationStrategy { tab, position ->
when (position) {
0 -> { tab.text = "TAB ONE"}
1 -> { tab.text = "TAB TWO"}
}
}).attach()
SORTIE
Pas de bidouillages, pas d'extensions, pas de TabLayoutMediator.
Je suis sur implementation 'com.google.android.material:material:1.2.0-alpha02'
et faire ce qui suit sans ayant besoin du TabLayoutMediator. Au lieu de cela, je lie le TabLayout avec le ViewPager2 en utilisant la méthode décrite ci-dessous. ici . J'ai également ajouté un exemple fonctionnel sur github. ici . Je pense avoir réduit la solution à un exemple fonctionnel minimal. Je vais expliquer les points importants.
Ajout des éléments au modèle
Tout d'abord, nous devons ajouter le TabLayout et le ViewPager2 à la disposition. Je les ai placés à l'intérieur d'un LinearLayout et d'un CoordinatorLayout, mais vous pouvez faire ce que vous voulez, bien sûr.
<!-- 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>
Connexion d'un adaptateur au viewpager
L'adaptateur est donc chargé de fournir les bons fragments à l'activité. Vous devrez étendre FragmentStateAdapter ce que j'ai fait très simplement comme ci-dessous (c'est une classe privée car elle est déclarée dans mon MainActivity.java ici) :
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;
}
}
Je peux alors connecter mon propre adaptateur au ViewPager comme ci-dessous :
FragmentManager fm = getSupportFragmentManager();
ViewStateAdapter sa = new ViewStateAdapter(fm, getLifecycle());
final ViewPager2 pa = findViewById(R.id.pager);
pa.setAdapter(sa);
J'ai ajouté les fragments à mon viewpager. (Parce que j'ai codé en dur les fragments dans mon adaptateur, vous devriez utiliser une liste et quelque chose comme une méthode 'addFragment' ou quelque chose comme ça)
Le TabLayout
Ensuite, avec
TabLayout tabLayout = findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText("Bar"));
tabLayout.addTab(tabLayout.newTab().setText("Foo"));
J'ajoute deux onglets à mon TabLayout, affichant les titres mais ne me permettant pas encore de passer aux fragments.
Connexion de TabLayout à l'adaptateur
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) {
}
});
Cela devrait être assez simple. L'utilisateur clique sur un onglet, je récupère la position dans mon callback et je fixe simplement l'élément actuel de l'adaptateur à cette position.
Changement d'onglet lors du glissement de la souris
Enfin, nous couplons lorsque l'utilisateur passe le fragment pour définir l'élément correct de l'onglet comme sélectionné
pa.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
tabLayout.selectTab(tabLayout.getTabAt(position));
}
});
Initialiser le TabLayoutMediator
avec un objet de TabLayout
, ViewPager2
, autoRefresh
-- de type booléen, et un objet de type OnConfigurationChangeCallback
.
TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager2, true, new TabLayoutMediator.OnConfigureTabCallback() {
@Override
public void onConfigureTab(TabLayout.Tab tab, int position) {
// position of the current tab and that tab
}
});
Enfin, il suffit d'appeler attach()
à la TabLayoutMediator
objet pour relier le tablayout au viewpager :-
tabLayoutMediator.attach();
autoRefresh
- si elle est réglée sur true
-- ( Par défaut, elle est mise à true )
RECREATES
tous les onglets de latabLayout
sinotifyDataSetChanged
est appelé au viewpageradapter
.
Utilisez le contenu de TabLayoutMediator.java
Vous pouvez utiliser la fonction d'extension 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()
}
Et l'appeler :
tabLayout.setupWithViewPager(viewPager, listOf("Tab A", "Tab B"))
- Réponses précédentes
- Plus de réponses