This is how I'm implementing bottom navigation
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/main_botton_navigation"
android:background="#color/btn_bg"
app:menu="#menu/main_bottom_nav_menu"
app:labelVisibilityMode="labeled"
app:itemTextColor="#drawable/text_selector"
app:layout_constraintBottom_toBottomOf="parent" />
<fragment
android:id="#+id/fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
app:layout_constraintTop_toBottomOf="#id/main_appbar"
android:layout_height="617dp"
app:layout_constraintBottom_toTopOf="#id/main_botton_navigation"
app:defaultNavHost="true"
app:navGraph="#navigation/main_bottom_nav"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="57dp" />
and this is how I'm doing in activity
val navController = findNavController(R.id.fragment)
val appBarConfiguration =
AppBarConfiguration(setOf(R.id.allFiles, R.id.recentFiles, R.id.bookMark, R.id.tools))
setupActionBarWithNavController(navController, appBarConfiguration)
binding.mainBottonNavigation.setupWithNavController(navController)
but only last activity is changed while clicking on last item other's are not changing
Change your code like this and change fragment name according to yours.
// Setting Up ActionBar with Navigation Controller
// Pass the IDs of top-level destinations in AppBarConfiguration
var appBarConfiguration = AppBarConfiguration(
topLevelDestinationIds = setOf (
R.id.homeFragment,
R.id.searchFragment,
R.id.notificationsFragment,
R.id.profileFragment
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
For a detailed understanding of Navigation library please read this article
https://medium.com/android-news/beginners-guide-to-bottom-navigation-with-android-jetpack-5485d2b8bbb5
Related
This question already has answers here:
android navigation component up button, arrow displays but popTo not working
(2 answers)
Closed 1 year ago.
I have an AppCompatActivity with a FragmentContainerView and a BottomNavigationView.
When I navigate from a fragment_A to the fragment_B(which are not in the bottom menu) a back button appears, the problem is that the back button closes the app instead of going back to the previous fragment_A.
My activity 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:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:liftOnScroll="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/homeToolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways|snap" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment_activity_home"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#+id/nav_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/appBarLayout"
app:navGraph="#navigation/mobile_navigation" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom"
app:layout_behavior=".ui.behaviour.TestBehavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
And this is the kotlin code:
class HomeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHomeBinding
private val viewModel: HomeActivityViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityHomeBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.homeToolbar)
val navView: BottomNavigationView = binding.navView
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment_activity_home) as NavHostFragment
val navController = navHostFragment.navController
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_home,
R.id.navigation_fragment_a,
R.id.navigation_notifications
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
}
This is the action xml:
<action
android:id="#+id/navigate_to_fragment_b"
app:destination="#id/fragment_b"
app:enterAnim="#anim/slide_in_right"
app:exitAnim="#anim/slide_out_left"
app:popEnterAnim="#anim/slide_in_right"
app:popExitAnim="#anim/slide_out_left" />
This the code I use to obtain the navController reference:
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment_activity_home) as NavHostFragment
val navController = navHostFragment.navController
And this is the navigation function that i call from the fragment_A:
navController.navigate(R.id.navigate_to_fragment_b)
I tried to override the onBackPressed() in my activity but it's never gets called.
Update
I have confused the back button with the up button.
In my case back button returns to previous fragment but up button close the app.
So my problem is with the UP BUTTON.
UP button appears only when I navigate to the fragment_B, and referring to this I would say that there is something that does not work because it closes the app for me.
The Up button never exits your app
If a user is at the app's start destination, then the Up button does not appear, because the Up button never exits the app. The Back button, however, is shown and does exit the app.
Thanks to ianhanniballake for the solution in this answer
// Java
#Override
public boolean onSupportNavigateUp() {
return Navigation.findNavController(this, R.id.main_fragment).navigateUp()|| super.onSupportNavigateUp();
}
// Kotlin
override fun onSupportNavigateUp(): Boolean {
return Navigation.findNavController(this, R.id.main_fragment).navigateUp() || super.onSupportNavigateUp()
}
In my application, I want to show bottom tabs and when click on these tabs show one fragment.
For this I used BottomNavigationView and NavigationUI component for show fragments
My XML code:
<fragment
android:id="#+id/homePage_fragmentNavHost"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="#navigation/home_navigator"
app:defaultNavHost="true"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="#+id/homePage_bottomNavBar"
app:layout_constraintTop_toBottomOf="#+id/homePage_toolbar"/>
<!--Bottom menu-->
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/homePage_bottomNavBar"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:background="?android:attr/windowBackground"
app:menu="#menu/menu_home_navigation"
app:labelVisibilityMode="selected"
app:itemTextAppearanceActive="#style/BottomNavigationView.Active"
app:itemTextAppearanceInactive="#style/BottomNavigationView"
app:itemTextColor="#color/bottom_nav_bar_colors"
app:itemIconTint="#color/bottom_nav_bar_colors"/>
And I write below codes, for connect NavigationUi and BottomNavigationView :
private fun setupNavigation() {
val navController = Navigation.findNavController(this, R.id.homePage_fragmentNavHost)
NavigationUI.setupWithNavController(homePage_bottomNavBar, navController)
}
override fun onSupportNavigateUp() = Navigation.findNavController(this, R.id.homePage_fragmentNavHost).navigateUp()
But always show the item 0 for default tab.
I want write condition and check one value and with this value set default tab for this NavigationUi and BottomNavigationView.
How can I do it?
In the graph you can define the startDestination.
Something like:
val navHostFragment = supportFragmentManager.findFragmentById(R.id.homePage_fragmentNavHost) as NavHostFragment
val graphInflater = navHostFragment.navController.navInflater
val navGraph = graphInflater.inflate(R.navigation.home_navigator)
navGraph.startDestination = R.id.nav_xxxxx
navController.graph = navGraph
findViewById<BottomNavigationView>(R.id.homePage_bottomNavBar)
.setupWithNavController(navController)
I have successfully integrated the bottom navigation with the latest android architecture navigation components. The following is my complete code.
Navigation
<?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/mobile_navigation"
app:startDestination="#+id/navigation_home">
<fragment
android:id="#+id/navigation_home"
android:name="in.zedone.bottomsample.ui.home.HomeFragment"
android:label="#string/title_home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/navigation_saloons"
android:name="in.zedone.bottomsample.ui.saloons.SaloonsFragment"
android:label="#string/title_saloon"
tools:layout="#layout/fragment_saloons" />
<fragment
android:id="#+id/navigation_offers"
android:name="in.zedone.bottomsample.ui.offers.OffersFragment"
android:label="#string/title_offer"
tools:layout="#layout/fragment_offers" />
<fragment
android:id="#+id/navigation_account"
android:name="in.zedone.bottomsample.ui.account.AccountFragment"
android:label="#string/title_account"
tools:layout="#layout/fragment_account" />
</navigation>
BottomNavigationView
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:labelVisibilityMode="labeled"
app:itemTextAppearanceActive="#style/BottomNavigationView.Active"
app:itemTextAppearanceInactive="#style/BottomNavigationView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/bottom_nav_menu" />
MainActivity
BottomNavigationView navView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_saloons, R.id.navigation_offers,R.id.navigation_account)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
Now how can I add transition/animation on select each tab/fragment in bottom navigation?
Instead of using setupWithNavController function, follow this way.
First, create your NavOptions which include animation shown below.
val options = NavOptions.Builder()
.setLaunchSingleTop(true)
.setEnterAnim(R.anim.enter_from_bottom)
.setExitAnim(R.anim.exit_to_top)
.setPopEnterAnim(R.anim.enter_from_top)
.setPopExitAnim(R.anim.exit_to_bottom)
.setPopUpTo(navController.graph.startDestination, false)
.build()
Then use setOnNavigationItemSelectedListener to navigate with animation like that.
bottomNavigationView.setOnNavigationItemSelectedListener { item ->
when(item.itemId) {
R.id.fragmentFirst -> {
navController.navigate(R.id.fragmentFirst,null,options)
}
R.id.fragmentSecond -> {
navController.navigate(R.id.fragmentSecond,null,options)
}
R.id.fragmentThird -> {
navController.navigate(R.id.fragmentThird,null,options)
}
}
true
}
Finally, you should prevent same item selection case so you can add below code.
bottomNavigationView.setOnNavigationItemReselectedListener { item ->
return#setOnNavigationItemReselectedListener
I used bottomNavigation like that in my project to add animation for page transitions.
I hope it helped.
its work with BottomNavigationView's siblings fragment also(JetPack Navigation Components)
// FragmentA.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
exitTransition = MaterialFadeThrough()
}
// FragmentB.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialFadeThrough()
}
You can also do it with keeping setupWithNavController by overriding onCreateAnimation() in each Fragment and checking whether or not you're entering or exiting the Fragment with the enter parameter and then creating the appropriate Animation with AnimationUtils.loadAnimation(context, animationId).
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
return if (enter) {
AnimationUtils.loadAnimation(context, R.anim.fade_in)
} else {
AnimationUtils.loadAnimation(context, R.anim.fade_out)
}
}
EDIT as a response to iloo:
According to Material Design (https://material.io/components/bottom-navigation#behavior) you shouldn't be doing that in the first place, but I guess it's still achievable.
Since when using setupWithNavController all destinations are top level there will
ever be only one previousBackStackEntry whose destination points to the home
destination, therefore previousBackStackEntry is not much of a help in figuring out which Fragment are you coming from.
Other approach could be to have a public variable in the Activity, where you will store the
last destination you were in and set that variable in each Fragment upon resuming.
And you can check that variable in onAnimationCreate to know which Fragment you're coming from
and apply an appropriate animation.
I'm kinda new to the Android Navigation but this is what I think you can try if you like to change the default animation
put those file in your anim directory
nav_default_enter_anim.xml
nav_default_exit_anim.xml
nav_default_pop_enter_anim.xml
nav_default_pop_exit_anim.xml
and the default animation for the transactions will change to the animation you put in the above files.
I'm hiding a bottom navigation item when user is not authenticated (that item will show up once the user is authenticated, which in this case, is a Messages Fragment). That works well, but when that fragment is shown and selected, the previous navigation menu that I was in is still highlighted, even if I'm on that fragment. Also, once I chose another navigation item, Messages is still highlighted on the bottom navigation bar. Refer to the screenshots below:
When the Messages is not yet selected
When I select Message Fragment (I was from Home Fragment before that)
When I go back to any other Fragment aside from Messages (in this case, Home Fragment)
Here's my MainActivity (Notice that there's navView.menu.findItem(R.id.navigation_messages).isVisible, which is the main cause of this behavior in bottom navigation bar)
class MainActivity : AppCompatActivity() {
private var authState : Int = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_home, R.id.navigation_explore, R.id.navigation_messages, R.id.navigation_account
)
)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
when(authState) {
0 -> navView.menu.findItem(R.id.navigation_messages).isVisible = false
1 -> navView.menu.findItem(R.id.navigation_messages).isVisible = true
}
}
override fun onSupportNavigateUp(): Boolean {
return navigateUp(Navigation.findNavController(this, R.id.nav_host_fragment), AppBarConfiguration(setOf(
R.id.navigation_home, R.id.navigation_explore, R.id.navigation_messages, R.id.navigation_account
)))
}
}
Also, here's my activity_main.xml file:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:itemHorizontalTranslationEnabled="false"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/bottom_nav_menu" />
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
android:layout_marginBottom="56dp"
app:layout_constraintBottom_toTopOf="#+id/nav_view"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:navGraph="#navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
To note, I'm using Android Jetpack Navigation Architecture Components, which made other similar solutions like this, this, or this, not that viable on this case.
I have installed the latest canary version of Android Studio, and followed this (https://developer.android.com/topic/libraries/architecture/navigation/navigation-implementing) instruction to implement a simple two page navigation. Basically page1 has a button, and when it is clicked, the app shows page2.
It works, but there is one problem... It does not seem to do anything with the action bar automatically. Is it supposed to show up/back arrow and the "Label" attribute on the action bar automatically by the navigation library? Or am I supposed to do all the work manually as before? I want to show the back arrow and "Details" on action(tool) bar when page2 is showing.
On button click at page 1.
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{
button1.setOnClickListener {
val nav = NavHostFragment.findNavController(this);
nav.navigate(R.id.show_page2)
}
}
Main activity XML. By default it was the default Action Bar, I have replaced it with a ToolBar. There was no difference.
<?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.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
android:background="?attr/colorPrimary"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
android:layout_width="match_parent">
</androidx.appcompat.widget.Toolbar>
<fragment
android:id="#+id/my_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolbar"
app:navGraph="#navigation/nav_graph"/>
</androidx.constraintlayout.widget.ConstraintLayout>
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/page1">
<activity
android:id="#+id/mainActivity2"
android:name="com.android.navtest.MainActivity"
android:label="activity_main"
tools:layout="#layout/activity_main"/>
<fragment
android:id="#+id/page1"
android:name="com.android.navtest.BlankFragment2"
android:label="Home page"
tools:layout="#layout/page1">
<action
android:id="#+id/show_page2"
app:destination="#id/page2"
app:enterAnim="#anim/anim1"
app:popExitAnim="#anim/anim2"/>
</fragment>
<fragment
android:id="#+id/page2"
android:name="com.android.navtest.BlankFragment"
android:label="Details"
tools:layout="#layout/page2"/>
</navigation>
You can connect your ActionBar to a NavController using NavigationUI.setupActionBarWithNavController(). This is generally done in your Activity, right after you call setSupportActionBar():
supportActionBar = findViewById<Toolbar>(R.id.toolbar)
// Get the NavController for your NavHostFragment
val navController = findNavController(R.id.nav_host_fragment)
// Set up the ActionBar to stay in sync with the NavController
setupActionBarWithNavController(navController)
This approach is covered in the Navigation talk at Google I/O 2018.
If you want to have navigation back button hidden in more than one place (default is only for home fragment) you can add ids of fragments to AppBarConfiguration and pass this as second parameter of setupActionBarWithNavController, for example:
val appBarConfiguration = AppBarConfiguration(setOf(R.id.splashFragment, R.id.onboardingFragment, R.id.homeFragment))
setupActionBarWithNavController(findNavController(R.id.nav_host), appBarConfiguration)
This is what I have done.
onSupportNavigateUp is called when the user navigates up and it set again. by calling this setupActionBarWithNavController tell android to update the title of toolbar.
navigateUp Handles the Up button by delegating its behavior to the given NavController. This should generally be called from AppCompatActivity.onSupportNavigateUp().
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityGameConfigBinding =
DataBindingUtil.setContentView(this, R.layout.activity_game_config)
supportActionBar?.show()
val navController = Navigation.findNavController(this, R.id.myNavHostFragment)
NavigationUI.setupActionBarWithNavController(this, navController, null)
appBarConfiguration = AppBarConfiguration.Builder(navController.graph)
.build()
NavigationUI.setupWithNavController(binding.navView, navController)
}
override fun onSupportNavigateUp(): Boolean {
val navController = Navigation.findNavController(this, R.id.myNavHostFragment)
return NavigationUI.navigateUp(navController, appBarConfiguration)
}
my solution with binding - the code is in MainActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.main_activity)
navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.navController
setSupportActionBar(toolbar)//needs to be after binding
toolbar.setupWithNavController(navController,AppBarConfiguration(navController.graph))
}
as for the titles - first I removed labels (android:label) from the fragments in navigation graph (label overwrites title from what I've tested)
<fragment
android:id="#+id/productListFragment"
android:name="com.example.ProductListFragment"
android:label="TO_BE_REMOVED"
tools:layout="#layout/product_list_fragment">
<action
android:id="#+id/action_productListFragment_to_mainMenuFragment"
app:destination="#id/mainMenuFragment" />
</fragment>
each fragment sets the title and subtitle in onResume, here example from ProductListFragment
override fun onResume() {
super.onResume()
val actionBar = (activity as AppCompatActivity).supportActionBar
actionBar?.title = getString(R.string.product_list_title)
actionBar?.subtitle = getString(R.string.product_list_subtitle)
}