Skip to content

Commit 7c249c2

Browse files
add bottom navigation to app with blank fragments
1 parent a60f590 commit 7c249c2

7 files changed

Lines changed: 206 additions & 1 deletion

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,72 @@
11
package com.smarttoolfactory.propertyfindar
22

3+
import android.os.Bundle
4+
import android.view.View
35
import com.smarttoolfactory.core.ui.fragment.DynamicNavigationFragment
46
import com.smarttoolfactory.propertyfindar.databinding.FragmentMainBinding
7+
import com.smarttoolfactory.propertyfindar.ui.BottomNavigationFragmentStateAdapter
58

69
class MainFragment : DynamicNavigationFragment<FragmentMainBinding>() {
710

811
override fun getLayoutRes(): Int = R.layout.fragment_main
12+
13+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
14+
super.onViewCreated(view, savedInstanceState)
15+
16+
val binding = dataBinding!!
17+
18+
val viewPager2 = binding.viewPager
19+
val bottomNavigationView = binding.bottomNav
20+
21+
// Cancel ViewPager swipe
22+
viewPager2.isUserInputEnabled = false
23+
24+
// Set viewpager adapter
25+
viewPager2.adapter =
26+
BottomNavigationFragmentStateAdapter(childFragmentManager, viewLifecycleOwner.lifecycle)
27+
28+
// Listen bottom navigation tabs change
29+
bottomNavigationView.setOnNavigationItemSelectedListener {
30+
31+
when (it.itemId) {
32+
33+
R.id.nav_graph_dfm_home_start -> {
34+
viewPager2.setCurrentItem(0, false)
35+
return@setOnNavigationItemSelectedListener true
36+
}
37+
38+
R.id.nav_graph_dfm_favorites_start -> {
39+
viewPager2.setCurrentItem(1, false)
40+
return@setOnNavigationItemSelectedListener true
41+
}
42+
43+
R.id.nav_graph_dfm_notification_start -> {
44+
viewPager2.setCurrentItem(2, false)
45+
return@setOnNavigationItemSelectedListener true
46+
}
47+
48+
else -> {
49+
viewPager2.setCurrentItem(3, false)
50+
return@setOnNavigationItemSelectedListener true
51+
}
52+
}
53+
}
54+
false
55+
}
56+
57+
override fun onDestroyView() {
58+
59+
val viewPager2 = dataBinding?.viewPager
60+
61+
/*
62+
Without setting ViewPager2 Adapter it causes memory leak
63+
64+
https://stackoverflow.com/questions/62851425/viewpager2-inside-a-fragment-leaks-after-replacing-the-fragment-its-in-by-navig
65+
*/
66+
viewPager2?.let {
67+
it.adapter = null
68+
}
69+
70+
super.onDestroyView()
71+
}
972
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.smarttoolfactory.propertyfindar.ui
2+
3+
import androidx.fragment.app.Fragment
4+
import androidx.fragment.app.FragmentContainerView
5+
import androidx.fragment.app.FragmentManager
6+
import androidx.lifecycle.Lifecycle
7+
import com.smarttoolfactory.core.ui.adapter.NavigableFragmentStateAdapter
8+
import com.smarttoolfactory.core.ui.fragment.navhost.NavHostContainerFragment
9+
import com.smarttoolfactory.propertyfindar.R
10+
11+
/**
12+
* FragmentStateAdapter to contain ViewPager2 fragments inside another fragment which uses
13+
* wrapper layouts that contain [FragmentContainerView]
14+
*
15+
* * 🔥 Create FragmentStateAdapter with viewLifeCycleOwner instead of Fragment to make sure
16+
* that it lives between [Fragment.onCreateView] and [Fragment.onDestroyView] while [View] is alive
17+
*
18+
* * https://stackoverflow.com/questions/61779776/leak-canary-detects-memory-leaks-for-tablayout-with-viewpager2
19+
*/
20+
class BottomNavigationFragmentStateAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
21+
NavigableFragmentStateAdapter(fragmentManager, lifecycle) {
22+
23+
override fun getItemCount(): Int = 4
24+
25+
override fun createFragment(position: Int): Fragment {
26+
return when (position) {
27+
0 -> NavHostContainerFragment.createNavHostContainerFragment(
28+
R.layout.fragment_navhost_home,
29+
R.id.nested_nav_host_fragment_home
30+
)
31+
32+
// Vertical NavHost Post Fragment Container
33+
1 -> NavHostContainerFragment.createNavHostContainerFragment(
34+
R.layout.fragment_navhost_favorites,
35+
R.id.nested_nav_host_fragment_favorites
36+
)
37+
38+
// Horizontal NavHost Post Fragment Container
39+
2 -> NavHostContainerFragment.createNavHostContainerFragment(
40+
R.layout.fragment_navhost_notification,
41+
R.id.nested_nav_host_fragment_notification
42+
)
43+
44+
else -> NavHostContainerFragment.createNavHostContainerFragment(
45+
R.layout.fragment_navhost_account,
46+
R.id.nested_nav_host_fragment_account
47+
)
48+
}
49+
}
50+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<layout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto">
4+
5+
<androidx.constraintlayout.widget.ConstraintLayout
6+
android:layout_width="match_parent"
7+
android:layout_height="match_parent">
8+
9+
<androidx.fragment.app.FragmentContainerView
10+
android:id="@+id/nested_nav_host_fragment_account"
11+
android:name="androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment"
12+
android:layout_width="0dp"
13+
android:layout_height="0dp"
14+
app:defaultNavHost="true"
15+
app:layout_constraintBottom_toBottomOf="parent"
16+
app:layout_constraintLeft_toLeftOf="parent"
17+
app:layout_constraintRight_toRightOf="parent"
18+
app:layout_constraintTop_toTopOf="parent"
19+
app:navGraph="@navigation/nav_graph_dfm_account_start" />
20+
21+
</androidx.constraintlayout.widget.ConstraintLayout>
22+
23+
</layout>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<layout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto">
4+
5+
<androidx.constraintlayout.widget.ConstraintLayout
6+
android:layout_width="match_parent"
7+
android:layout_height="match_parent">
8+
9+
<androidx.fragment.app.FragmentContainerView
10+
android:id="@+id/nested_nav_host_fragment_favorites"
11+
android:name="androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment"
12+
android:layout_width="0dp"
13+
android:layout_height="0dp"
14+
app:defaultNavHost="true"
15+
app:layout_constraintBottom_toBottomOf="parent"
16+
app:layout_constraintLeft_toLeftOf="parent"
17+
app:layout_constraintRight_toRightOf="parent"
18+
app:layout_constraintTop_toTopOf="parent"
19+
app:navGraph="@navigation/nav_graph_dfm_favorites_start" />
20+
21+
</androidx.constraintlayout.widget.ConstraintLayout>
22+
23+
</layout>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<layout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto">
4+
5+
<androidx.constraintlayout.widget.ConstraintLayout
6+
android:layout_width="match_parent"
7+
android:layout_height="match_parent">
8+
9+
<androidx.fragment.app.FragmentContainerView
10+
android:id="@+id/nested_nav_host_fragment_home"
11+
android:name="androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment"
12+
android:layout_width="0dp"
13+
android:layout_height="0dp"
14+
app:defaultNavHost="true"
15+
app:layout_constraintBottom_toBottomOf="parent"
16+
app:layout_constraintLeft_toLeftOf="parent"
17+
app:layout_constraintRight_toRightOf="parent"
18+
app:layout_constraintTop_toTopOf="parent"
19+
app:navGraph="@navigation/nav_graph_dfm_home_start" />
20+
21+
</androidx.constraintlayout.widget.ConstraintLayout>
22+
23+
</layout>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<layout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto">
4+
5+
<androidx.constraintlayout.widget.ConstraintLayout
6+
android:layout_width="match_parent"
7+
android:layout_height="match_parent">
8+
9+
<androidx.fragment.app.FragmentContainerView
10+
android:id="@+id/nested_nav_host_fragment_notification"
11+
android:name="androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment"
12+
android:layout_width="0dp"
13+
android:layout_height="0dp"
14+
app:defaultNavHost="true"
15+
app:layout_constraintBottom_toBottomOf="parent"
16+
app:layout_constraintLeft_toLeftOf="parent"
17+
app:layout_constraintRight_toRightOf="parent"
18+
app:layout_constraintTop_toTopOf="parent"
19+
app:navGraph="@navigation/nav_graph_dfm_notification_start" />
20+
21+
</androidx.constraintlayout.widget.ConstraintLayout>
22+
23+
</layout>

app/src/main/res/menu/menu_bottom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
android:title="Home" />
88

99
<item
10-
android:id="@+id/nav_graph_dfm_favorite_start"
10+
android:id="@+id/nav_graph_dfm_favorites_start"
1111
android:icon="@drawable/ic_baseline_favorite_24"
1212
android:title="Dashboard" />
1313

0 commit comments

Comments
 (0)