J'ai une application avec BottomNavigationView
et ViewPager
. Comment est-il possible de l'implémenter à l'aide du nouveau "composant d'architecture de navigation?"
Quelle est la meilleure pratique?
Merci beaucoup
L'implémentation par défaut de BottomNavigationView
avec Navigation Arch Component n'a pas fonctionné pour moi. Lorsque vous cliquez sur les onglets, cela commence par les graphiques de navigation.
J'ai besoin de 5 onglets au bas de l'écran et d'un backstack séparé pour chacun des onglets. Ce qui signifie que lorsque vous passez d'un onglet à l'autre, vous retrouvez toujours exactement le même état qu'avant votre départ (comme sur Instagram).
Mon approche est la suivante:
ViewPager
et BottomNavigationView
dans activity_main.xml
OnNavigationItemSelectedListener
sur BottomNavigationView
dans MainActivity.kt
NavHostFragment
à l'intérieur du xml du conteneur.Remarque: chacun des graphiques peut interagir.
Le point important ici est que nous plaçons Toolbar not en activité mais dans le conteneur. Ensuite, nous appelons setupWithNavController()
sur la barre d’outils elle-même sans le définir comme supportActionBar
. De cette façon, les titres de la barre d’outils seront automatiquement mis à jour et le bouton Back/Up sera géré automatiquement.
Résultats:
SafeArgs
et DeepLinking
fonctionnent comme prévu.BottomNavigationManager
et ViewPager
(c’est-à-dire que nous pouvons implémenter OnNavigationItemReselectedListener
et décider de faire défiler des listes dans l’onglet actuel en haut avant de faire sauter backstack).Code:
activity_main.xml
<LinearLayout 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"
Android:orientation="vertical"
tools:context=".MainActivity">
<androidx.viewpager.widget.ViewPager
Android:id="@+id/main_view_pager"
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="1" />
<com.google.Android.material.bottomnavigation.BottomNavigationView
Android:id="@+id/main_bottom_navigation_view"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:background="?android:attr/windowBackground"
app:menu="@menu/navigation" />
</LinearLayout>
MainActivity.kt
import kotlinx.Android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private lateinit var viewPagerAdapter: ViewPagerAdapter
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_tab_1 -> {
main_view_pager.currentItem = 0
return@OnNavigationItemSelectedListener true
}
R.id.navigation_tab_2 -> {
main_view_pager.currentItem = 1
return@OnNavigationItemSelectedListener true
}
}
false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewPagerAdapter = ViewPagerAdapter(supportFragmentManager)
main_view_pager.adapter = viewPagerAdapter
main_bottom_navigation_view.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
}
}
ViewPagerAdapter.kt
class ViewPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
override fun getItem(position: Int): Fragment {
return when (position) {
0 -> Tab1ContainerFragment()
else -> Tab2ContainerFragment()
}
}
override fun getCount(): Int {
return 2
}
}
fragment_tab_1_container.xml
<RelativeLayout 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=".Tab1ContainerFragment">
<androidx.appcompat.widget.Toolbar
Android:id="@+id/tab_1_toolbar"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
Android:background="@color/colorPrimary"
Android:theme="@style/ThemeOverlay.AppCompat.Dark" />
<fragment
Android:id="@+id/tab_1_nav_Host_fragment"
Android:name="androidx.navigation.fragment.NavHostFragment"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/navigation_graph_tab_1" />
</RelativeLayout>
Tab1ContainerFragment.kt
class Tab1ContainerFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_tab_1_container, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val toolbar = view.findViewById<Toolbar>(R.id.tab_1_toolbar)
val navHostFragment = childFragmentManager.findFragmentById(R.id.tab_1_nav_Host_fragment) as NavHostFragment? ?: return
val navController = navHostFragment.navController
val appBarConfig = AppBarConfiguration(navController.graph)
toolbar.setupWithNavController(navController, appBarConfig)
}
}
Nous pouvons créer autant de graphiques de navigation que vous le souhaitez:
Mais nous avons besoin d’un graphique séparé pour chaque onglet:
<navigation 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:id="@+id/navigation_graph_tab_1"
app:startDestination="@id/tab1StartFragment">
<fragment
Android:id="@+id/tab1StartFragment"
Android:name="com.marat.Android.bottomnavigationtutorial.Tab1StartFragment"
Android:label="fragment_tab_1_start"
tools:layout="@layout/fragment_tab_1_start">
<action
Android:id="@+id/action_tab_1_to_content"
app:destination="@id/navigation_graph_content" />
</fragment>
<include app:graph="@navigation/navigation_graph_content" />
</navigation>
Ici, commencer fragment de destination est tout fragment que vous souhaitez voir apparaître en tant que premier écran dans l'onglet.
J'ai implémenté Android Arch Navigations avec viewpager. jetez un coup d'oeil s'il vous plait. Toute amélioration est la bienvenue. Permet d'apprendre à se réunir.
https://github.com/Maqsood007/AndroidJetpack/tree/master/ArchNavViewPagerImpl
Nous pouvons implémenter facilement l’utilisation du composant de navigation inférieure et de NavigationGraph.
Vous devez créer le fragment correspondant pour chaque menu de navigation inférieur
nav_graph.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/nav_graph"
app:startDestination="@id/actionHome">
<fragment
Android:id="@+id/actionHome"
Android:name="com.sample.demo.fragments.Home"
Android:label="fragment_home"
tools:layout="@layout/fragment_home">
<action
Android:id="@+id/toExplore"
app:destination="@id/actionExplore" />
</fragment>
<fragment
Android:id="@+id/actionExplore"
Android:name="com.sample.demo.fragments.Explore"
Android:label="fragment_explore"
tools:layout="@layout/fragment_explore" />
<fragment
Android:id="@+id/actionBusiness"
Android:name="com.sample.demo.fragments.Business"
Android:label="fragment_business"
tools:layout="@layout/fragment_business" />
<fragment
Android:id="@+id/actionProfile"
Android:name="com.sample.demo.fragments.Profile"
Android:label="fragment_profile"
tools:layout="@layout/fragment_profile" />
</navigation>
Chaque identifiant de fragment de navigation et identifiant d'élément de menu de navigation inférieur doit être identique. Par exemple ici
<fragment
Android:id="@+id/actionBusiness"
Android:name="com.sample.demo.fragments.Business"
Android:label="fragment_business"
tools:layout="@layout/fragment_business" />
En bas, dans le menu de navigation navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item
Android:id="@+id/actionExplore"
Android:icon="@drawable/ic_search_24dp"
Android:title="@string/explore" />
<item
Android:id="@+id/actionBusiness"
Android:icon="@drawable/ic_business_24dp"
Android:title="@string/business" />
<item
Android:id="@+id/actionProfile"
Android:icon="@drawable/ic_profile_24dp"
Android:title="@string/profile" />
</menu>
Définissez le fichier nav_graph.xml sur le fragment palceholder dans activity_main.xml.
<?xml version="1.0" encoding="utf-8"?>
<Android.support.constraint.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:id="@+id/container"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@drawable/gradient_bg"
Android:focusable="true"
Android:focusableInTouchMode="true"
tools:context=".MainActivity"
tools:layout_editor_absoluteY="25dp">
<Android.support.design.widget.BottomNavigationView
Android:id="@+id/navigation"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_marginStart="0dp"
Android:layout_marginEnd="0dp"
Android:background="@color/semi_grey"
app:itemIconTint="@drawable/bottom_bar_nav_item"
app:itemTextColor="@drawable/bottom_bar_nav_item"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/navigation" />
<include
Android:id="@+id/appBarLayout"
layout="@layout/app_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<fragment
Android:id="@+id/mainNavigationFragment"
Android:name="androidx.navigation.fragment.NavHostFragment"
Android:layout_width="0dp"
Android:layout_height="0dp"
Android:paddingBottom="@dimen/activity_horizontal_margin"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@+id/navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
app:navGraph="@navigation/nav_graph" />
</Android.support.constraint.ConstraintLayout>
Mapper le graphique de navigation en fragment ici app: navGraph = "@ navigation/nav_graph"
Après cela, implémentez le graphique de navigation et le composant bottomNavigation dans MainActivity.Java.
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
NavController navController = Navigation.findNavController(this, R.id.mainNavigationFragment);
NavigationUI.setupWithNavController(navigation, navController);
À votre santé!!!