Navigation Arch Component and Fragments Recreation - android

I used BottomNavigationView along with NavHostFragment and I have only 2 tabs at the moment, down below the Navigation Graph I used
<?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/main_navigation"
app:startDestination="#id/fragment1">
<fragment
android:id="#+id/fragment1"
android:name="something.ListingFragment"
android:label="#string/hello" />
<fragment
android:id="#+id/fragment2"
android:name="something.ListingFragment2"
android:label="#string/Hi" />
</navigation>
And the BottomNavigation Menu is:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="#id/fragment1"
android:icon="#drawable/ic1"
android:title="#string/hello"
tools:showAsAction="ifRoom" />
<item
android:id="#id/fragment2"
android:icon="#drawable/ic2"
android:title="#string/hi"
tools:showAsAction="ifRoom" />
All setuped together using:
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_navigation_view)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.navigation_host_fragment) as NavHostFragment
NavigationUI.setupWithNavController(bottomNavigationView, navHostFragment.navController)
Question is, every time I switch between tabs it creates a new instance of the tab fragment I click on, is there a way to manage this to prevent the creation of new items if it already exists in the memory?

Related

Android bottom navigation not changing destination

I was trying to implement a simple bottom navigation view using android's navigation, but I think I'm missing a step.
Here's what I did:
At first I created four fragments. These fragments contain only a text view.
Then I created a navigation graph. The code is as follows:
<?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/main_nav_graph"
app:startDestination="#id/homeFragment">
<fragment
android:id="#+id/homeFragment"
android:name="com.baba_abdullah.Project.fragment.HomeFragment"
android:label="fragment_home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/addBooksFragment"
android:name="com.example.Project.fragment.AddBooksFragment"
android:label="fragment_add_books"
tools:layout="#layout/fragment_add_books" />
<fragment
android:id="#+id/chatFragment"
android:name="com.example.Project.fragment.ChatFragment"
android:label="fragment_chat"
tools:layout="#layout/fragment_chat" />
<fragment
android:id="#+id/profileFragment"
android:name="com.example.Project.fragment.ProfileFragment"
android:label="fragment_profile"
tools:layout="#layout/fragment_profile" />
</navigation>
Menu file:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/home_fragment"
android:icon="#drawable/ic_baseline_home_24"
android:title="#string/home_menu_title"/>
<item
android:id="#+id/add_book_fragment"
android:icon="#drawable/ic_baseline_add_circle_outline_24"
android:title="#string/add_book_menu_title"/>
<item
android:id="#+id/chat_fragment"
android:icon="#drawable/ic_baseline_chat_bubble_outline_24"
android:title="#string/chat_menu_title"/>
<item
android:id="#+id/profile_fragment"
android:icon="#drawable/ic_baseline_account_circle_24"
android:title="#string/profile_menu_title"/>
</menu>
Inside the layout file of MainActivity, I added a FragmentContainer that would serve as NavHostFragment and a BottomNavigationView in the following way:
<?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/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/main_fragment_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#+id/bottom_nav_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/main_nav_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_nav_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/main_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
And in the MainActivity, I added the following lines to tie them up together:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.main_fragment_container);
NavController navController = navHostFragment.getNavController();
BottomNavigationView bottomNav = findViewById(R.id.bottom_nav_bar);
NavigationUI.setupWithNavController(bottomNav, navController);
}
Now, when I click on other menu item, it doesn't get selected and the destination view isn't changed either.
You can check the screen recording of the bahaviour of the output app.
What am I missing here?
to connect bottom navigation id of fragments most be equal with menu id, here is how need to be your navigation graph
<?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/main_nav_graph"
app:startDestination="#id/home_fragment">
<fragment
android:id="#+id/home_fragment"
android:name="com.baba_abdullah.Project.fragment.HomeFragment"
android:label="fragment_home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/add_book_fragment"
android:name="com.example.Project.fragment.AddBooksFragment"
android:label="fragment_add_books"
tools:layout="#layout/fragment_add_books" />
<fragment
android:id="#+id/chat_fragment"
android:name="com.example.Project.fragment.ChatFragment"
android:label="fragment_chat"
tools:layout="#layout/fragment_chat" />
<fragment
android:id="#+id/profile_fragment"
android:name="com.example.Project.fragment.ProfileFragment"
android:label="fragment_profile"
tools:layout="#layout/fragment_profile" />
</navigation>
In Menu file replace menu items id with fragment id's. e.g
<item
android:id="#+id/homeFragment"
android:icon="#drawable/ic_baseline_home_24"
android:title="#string/home_menu_title"/>

How to replace ChildFragmentManager with Navigation Graph in Android

I'm working on nested fragment scenario where I'm using a fragment with BottomNavigationView and inside that main fragment I need to load new fragments and these new fragments should replace more fragments within main fragment what contains BottomNavigationView. I'm able to load main fragment using NavigationGraph but not child fragments.
I'm loading main fragment as
<navigation ------- >
<fragment
android:id="#+id/mainTabFragment"
android:name="com.package.MainTabFragment"
android:label="#string/app_name"
tools:layout="#layout/fragment_main_tab"/>
</navigation>
And for Child fragments I'm using fragment manager as:
private fun loadFragment(fragment: Fragment): Boolean {
//switching fragment
childFragmentManager
.beginTransaction()
.replace(R.id.container, fragment)
.commit()
return true
}
MainFragmentGraph:
<?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/nav_landing_graph">
<!-- region added graphs -->
<include app:graph="#navigation/nav_landing_graph" />
<include app:graph="#navigation/nav_graph_main_tab" />
<!-- endregion -->
<fragment
android:id="#+id/mainTabFragment"
android:name="com.package.ui.mainTab.bottomView.MainTabFragment"
tools:layout="#layout/fragment_main_tab">
<action
android:id="#+id/action_landingFrag_to_bottomViewFrag"
app:destination="#id/nav_graph_main_tab" />
</fragment>
</navigation>
nav_graph_main_tab.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_main_tab"
app:startDestination="#id/mainTabFragment">
<fragment
android:id="#+id/mainTabFragment"
android:name="com.package.ui.mainTab.bottomView.MainTabFragment"
android:label="#string/my_health_space"
tools:layout="#layout/fragment_main_tab">
<action
android:id="#+id/action_bottomViewFrag_to_mainFrag"
app:destination="#id/nav_menu_graph" />
</fragment>
<include app:graph="#navigation/nav_menu_graph" />
</navigation>
It would be great if someone can help me to replace it with NavGraphComponent. Thanks.

Navigated fragment shows behind the previous fragment in Navigation architecture component jetpack

<?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/restaurantListFragment">
<fragment
android:id="#+id/scanQRFragment"
android:name="com.example.dine.ui.view.home.scan_qr.ScanQRFragment"
android:label="fragment_scan_q_r"
tools:layout="#layout/fragment_scan_q_r" />
<fragment
android:id="#+id/restaurantListFragment"
android:name="com.example.dine.ui.view.home.restaurants.RestaurantListFragment"
android:label="fragment_restaurant_list"
tools:layout="#layout/fragment_restaurant_list" >
<action
android:id="#+id/action_restaurantListFragment_to_restaruntDetailFragment"
app:destination="#id/restaruntDetailFragment"
app:popUpTo="#id/restaurantListFragment" />
</fragment>
<fragment
android:id="#+id/myPlateFragment"
android:name="com.example.dine.ui.view.home.my_plate.MyPlateFragment"
android:label="fragment_my_plate"
tools:layout="#layout/fragment_my_plate" />
<fragment
android:id="#+id/accountFragment"
android:name="com.example.dine.ui.view.home.account.AccountFragment"
android:label="fragment_account"
tools:layout="#layout/fragment_account" />
<fragment
android:id="#+id/restaruntDetailFragment"
android:name="com.example.dine.ui.view.restaurant_detail.RestaruntDetailFragment"
android:label="RestaruntDetailFragment"
tools:layout="#layout/fragment_restarunt_detail" />
</navigation>
Here is the navigation graph file I have used for this navigation fragments.
private fun onItemSelected() {
findNavController().navigate(R.id.action_restaurantListFragment_to_restaruntDetailFragment)
}
I called the `onItemSelected() method on a action, any help would be great. thanks
While Navigating from Restaurant list to RestaurantDetail fragment It comes like this. I have been suffering from this issue so long

how to change the title of Title Bar on the left up corner of the screen with code

I create a android project with Bottom Navigation Activity template, then I get three default fragment,
in the method: onCreateView of DashboardFragment ,i added getActivity().setTitle("Important");
but the titile (on the left up corner of the screen) is still "Dashboard",it didn't change to "Important" why?
I want to change the title with code ,I want to change it when running the app,not just config it in the mobile_navigation.xml
thanks.
here is mobile_navigation.xml
here is mobile_navigation.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/mobile_navigation"
app:startDestination="#+id/navigation_home">
<fragment
android:id="#+id/navigation_home"
android:name="com.example.testfragmentjump.ui.home.HomeFragment"
android:label="#string/title_home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/navigation_dashboard"
android:name="com.example.testfragmentjump.ui.dashboard.DashboardFragment"
android:label="#string/title_dashboard"
tools:layout="#layout/fragment_dashboard" />
<fragment
android:id="#+id/navigation_notifications"
android:name="com.example.testfragmentjump.ui.notifications.NotificationsFragment"
android:laabel="#string/title_notifications"
tools:layout="#layout/fragment_notifications" />
</navigation>
First you have to remove the title of Dashboard Fragment to check where it is in XML or Code class,then by code your able to change the title as per your selection of fragment!

Wrong animation when using navigation architecture component

I am building an app that uses BottomNavigationView and Navigation Architecture Component (https://github.com/fkshiba/POCNavigation).
I have one graph.xml for each tab and the transition between tabs is done by the Activity without Navigation AC due to the multiple backstack issue. I have an action with a transition animation on home_graph.xml from Home2 to Home3.
The problem is, once I run this transition and pop back to Home2 then navigate to another tab. It runs the pop animation again for the Home2 fragment when I transition from another tab even though there wasn't any animation specified for it.
Does anyone know a solution for this issue?
I see your code on GitHub and i assume that you are using android navigation wrongly. First you don't need to create different graphs(in your case four) for
different fragments. Just create one graph and add all fragments in it that you have to use within your bottom navigation and for others transactions.
And secondly you don't need to perform fragment transactions manually (in your activity code) you can but not necessary.
Your updated code:
only one graph:
<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/home_graph"
app:startDestination="#id/home2Fragment">
<fragment
android:id="#+id/home2Fragment"
android:name="com.felipeshiba.pocnavigation.Home2Fragment"
android:label="fragment_home2"
tools:layout="#layout/fragment_home2" >
<action
android:id="#+id/action_home2Fragment_to_home3Fragment"
app:destination="#id/home3Fragment"
app:enterAnim="#anim/nav_default_enter_anim"
app:exitAnim="#anim/nav_default_exit_anim"
app:popEnterAnim="#anim/nav_default_pop_enter_anim"
app:popExitAnim="#anim/nav_default_pop_exit_anim"/>
</fragment>
<fragment
android:id="#+id/home3Fragment"
android:name="com.felipeshiba.pocnavigation.Home3Fragment"
android:label="fragment_home3"
tools:layout="#layout/fragment_home3" >
<deepLink
android:id="#+id/deepLink"
app:uri="ifood://home/" />
</fragment>
<fragment
android:id="#+id/orders2Fragment"
android:name="com.felipeshiba.pocnavigation.Orders2Fragment"
android:label="fragment_orders2"
tools:layout="#layout/fragment_orders2" />
<fragment
android:id="#+id/profile2Fragment"
android:name="com.felipeshiba.pocnavigation.Profile2Fragment"
android:label="fragment_profile2"
tools:layout="#layout/fragment_profile2" />
<fragment
android:id="#+id/search2Fragment"
android:name="com.felipeshiba.pocnavigation.Search2Fragment"
android:label="fragment_search2"
tools:layout="#layout/fragment_search2" /></navigation>
Your updated activity code:
class NavigationActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_navigation)
val host: NavHostFragment = supportFragmentManager
.findFragmentById(R.id.navigation_container) as NavHostFragment? ?: return
val navController = host.navController
bottom_navigation.setupWithNavController(navController)
}}
Now you can just call your botton navigation items(fragments) within your menu by replacing menu item id with fragments id like below:
updated menu.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/home2Fragment"
android:icon="?android:attr/actionModeCopyDrawable"
android:title="Home" />
<item
android:id="#+id/search2Fragment"
android:icon="#android:drawable/ic_menu_search"
android:title="Search" />
<item
android:id="#+id/orders2Fragment"
android:icon="?android:attr/actionModePasteDrawable"
android:title="Orders" />
<item
android:id="#+id/profile2Fragment"
android:icon="?android:attr/actionModeCutDrawable"
android:title="Profile" /></menu>
Your activity.xml:
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".NavigationActivity">
<fragment
android:id="#+id/navigation_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone"
app:defaultNavHost="true"
app:navGraph="#navigation/home_graph"
app:layout_constraintBottom_toTopOf="#id/bottom_navigation"
app:layout_constraintTop_toTopOf="parent" />
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:menu="#menu/bottom_navigation"></android.support.constraint.ConstraintLayout>
For other updated(working) code like manifest check here
NavigationUI will always pop to start destination before going to other tab in BottomNavigationView, it's just how the nav lib works. Set custom OnNavigationItemSelectedListener and navigate yourself, and pass your animations through NavOptions.

Categories

Resources