Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0c6feae

Browse files
add bottomNavigation with ViewPager and NavHostContainerFragment
1 parent 1c212a4 commit 0c6feae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+840
-37
lines changed

‎app/src/main/java/com/smarttoolfactory/postdynamichilt/MainActivity.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@ package com.smarttoolfactory.postdynamichilt
22

33
import android.os.Bundle
44
import androidx.appcompat.app.AppCompatActivity
5-
import com.smarttoolfactory.domain.usecase.GetPostListUseCaseFlow
5+
import androidx.databinding.DataBindingUtil
6+
import com.smarttoolfactory.postdynamichilt.databinding.ActivityMainBinding
67
import dagger.hilt.android.AndroidEntryPoint
7-
import javax.inject.Inject
88

99
@AndroidEntryPoint
1010
class MainActivity : AppCompatActivity() {
1111

12-
@Inject
13-
lateinit var getPostListUseCaseFlow: GetPostListUseCaseFlow
14-
1512
override fun onCreate(savedInstanceState: Bundle?) {
1613
super.onCreate(savedInstanceState)
17-
setContentView(R.layout.activity_main)
14+
val dataBinding: ActivityMainBinding =
15+
DataBindingUtil.setContentView(this, R.layout.activity_main)
1816
}
1917
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.smarttoolfactory.postdynamichilt.account
2+
3+
import com.smarttoolfactory.core.ui.fragment.DynamicNavigationFragment
4+
import com.smarttoolfactory.postdynamichilt.R
5+
import com.smarttoolfactory.postdynamichilt.databinding.FragmentAccountBinding
6+
7+
class AccountFragment : DynamicNavigationFragment<FragmentAccountBinding>() {
8+
9+
override fun getLayoutRes(): Int = R.layout.fragment_account
10+
11+
override fun bindViews() {
12+
println("")
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.smarttoolfactory.postdynamichilt.account
2+
3+
import com.smarttoolfactory.core.ui.fragment.DynamicNavigationFragment
4+
import com.smarttoolfactory.postdynamichilt.R
5+
import com.smarttoolfactory.postdynamichilt.databinding.FragmentDashboardBinding
6+
7+
class DashboardFragment : DynamicNavigationFragment<FragmentDashboardBinding>() {
8+
9+
override fun getLayoutRes(): Int = R.layout.fragment_dashboard
10+
11+
override fun bindViews() {
12+
println("")
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.smarttoolfactory.postdynamichilt.account
2+
3+
import com.smarttoolfactory.core.ui.fragment.DynamicNavigationFragment
4+
import com.smarttoolfactory.postdynamichilt.R
5+
import com.smarttoolfactory.postdynamichilt.databinding.FragmentHomeBinding
6+
7+
class HomeFragment : DynamicNavigationFragment<FragmentHomeBinding>() {
8+
9+
override fun getLayoutRes(): Int = R.layout.fragment_home
10+
11+
override fun bindViews() {
12+
println("")
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.smarttoolfactory.postdynamichilt.account
2+
3+
import com.smarttoolfactory.core.ui.fragment.DynamicNavigationFragment
4+
import com.smarttoolfactory.postdynamichilt.R
5+
import com.smarttoolfactory.postdynamichilt.databinding.FragmentNotificationBinding
6+
7+
class NotificationFragment : DynamicNavigationFragment<FragmentNotificationBinding>() {
8+
9+
override fun getLayoutRes(): Int = R.layout.fragment_notification
10+
11+
override fun bindViews() {
12+
println("")
13+
}
14+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.smarttoolfactory.postdynamichilt.main
2+
3+
import android.os.Bundle
4+
import android.view.View
5+
import androidx.navigation.fragment.findNavController
6+
import com.smarttoolfactory.core.ui.fragment.BaseDataBindingFragment
7+
import com.smarttoolfactory.postdynamichilt.R
8+
import com.smarttoolfactory.postdynamichilt.databinding.FragmentMainBinding
9+
import com.smarttoolfactory.postdynamichilt.ui.BottomNavigationStateAdapter
10+
11+
class MainFragment : BaseDataBindingFragment<FragmentMainBinding>() {
12+
13+
override fun getLayoutRes(): Int = R.layout.fragment_main
14+
15+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
16+
super.onViewCreated(view, savedInstanceState)
17+
18+
println("🔥 MainFragmentWithViewPager navController: ${findNavController()}")
19+
20+
val binding = dataBinding!!
21+
22+
val viewPager2 = binding.viewPager
23+
val bottomNavigationView = binding.bottomNav
24+
25+
// Cancel ViewPager swipe
26+
viewPager2.isUserInputEnabled = false
27+
28+
// Set viewpager adapter
29+
viewPager2.adapter =
30+
BottomNavigationStateAdapter(childFragmentManager, viewLifecycleOwner.lifecycle)
31+
32+
// Listen bottom navigation tabs change
33+
bottomNavigationView.setOnNavigationItemSelectedListener {
34+
35+
when (it.itemId) {
36+
37+
R.id.nav_graph_home -> {
38+
viewPager2.setCurrentItem(0, false)
39+
return@setOnNavigationItemSelectedListener true
40+
}
41+
42+
R.id.nav_graph_dashboard -> {
43+
viewPager2.setCurrentItem(1, false)
44+
return@setOnNavigationItemSelectedListener true
45+
}
46+
47+
R.id.nav_graph_notification -> {
48+
viewPager2.setCurrentItem(2, false)
49+
return@setOnNavigationItemSelectedListener true
50+
}
51+
52+
else -> {
53+
viewPager2.setCurrentItem(3, false)
54+
return@setOnNavigationItemSelectedListener true
55+
}
56+
}
57+
}
58+
false
59+
}
60+
61+
override fun bindViews() {
62+
println("")
63+
}
64+
65+
override fun onDestroyView() {
66+
67+
val viewPager2 = dataBinding?.viewPager
68+
69+
/*
70+
Without setting ViewPager2 Adapter it causes memory leak
71+
72+
https://stackoverflow.com/questions/62851425/viewpager2-inside-a-fragment-leaks-after-replacing-the-fragment-its-in-by-navig
73+
*/
74+
viewPager2?.let {
75+
it.adapter = null
76+
}
77+
78+
super.onDestroyView()
79+
}
80+
}

‎app/src/main/java/com/smarttoolfactory/postdynamichilt/postlist/PostListFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import androidx.core.os.bundleOf
66
import androidx.fragment.app.viewModels
77
import androidx.navigation.fragment.findNavController
88
import androidx.recyclerview.widget.LinearLayoutManager
9-
import com.smarttoolfactory.core.ui.base.DynamicNavigationFragment
9+
import com.smarttoolfactory.core.ui.fragment.DynamicNavigationFragment
1010
import com.smarttoolfactory.postdynamichilt.R
1111
import com.smarttoolfactory.postdynamichilt.databinding.FragmentPostListBinding
1212
import dagger.hilt.android.AndroidEntryPoint
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.smarttoolfactory.postdynamichilt.ui
2+
3+
import androidx.fragment.app.Fragment
4+
import androidx.fragment.app.FragmentManager
5+
import androidx.fragment.app.commitNow
6+
import androidx.lifecycle.Lifecycle
7+
import androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment
8+
import androidx.navigation.fragment.NavHostFragment
9+
import androidx.viewpager2.adapter.FragmentStateAdapter
10+
import androidx.viewpager2.adapter.FragmentStateAdapter.FragmentTransactionCallback.OnPostEventListener
11+
import com.google.android.material.bottomnavigation.BottomNavigationView
12+
import com.smarttoolfactory.core.ui.fragment.navhost.NavHostContainerFragment
13+
import com.smarttoolfactory.postdynamichilt.R
14+
15+
/**
16+
* ViewPager2 Adapter for changing tabs of BottomNavigationView
17+
*
18+
* * This adapter is used because [BottomNavigationView] with back navigation does not support
19+
* [DynamicNavHostFragment] since [NavHostFragment.create] returns [NavHostFragment]
20+
* instead of type T:[NavHostFragment]`
21+
*/
22+
class BottomNavigationStateAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
23+
FragmentStateAdapter(fragmentManager, lifecycle) {
24+
25+
init {
26+
27+
// Add a FragmentTransactionCallback to handle changing
28+
// the primary navigation fragment
29+
registerFragmentTransactionCallback(object : FragmentTransactionCallback() {
30+
31+
override fun onFragmentMaxLifecyclePreUpdated(
32+
fragment: Fragment,
33+
maxLifecycleState: Lifecycle.State
34+
) = if (maxLifecycleState == Lifecycle.State.RESUMED) {
35+
36+
// This fragment is becoming the active Fragment - set it to
37+
// the primary navigation fragment in the OnPostEventListener
38+
OnPostEventListener {
39+
fragment.parentFragmentManager.commitNow {
40+
setPrimaryNavigationFragment(fragment)
41+
}
42+
}
43+
} else {
44+
super.onFragmentMaxLifecyclePreUpdated(fragment, maxLifecycleState)
45+
}
46+
})
47+
}
48+
49+
override fun getItemCount(): Int = 4
50+
51+
override fun createFragment(position: Int): Fragment {
52+
53+
return when (position) {
54+
// ViewPager Fragment NavHost Container
55+
0 -> NavHostContainerFragment.newInstance(
56+
R.layout.fragment_navhost_home,
57+
R.id.nested_nav_host_fragment_home
58+
)
59+
60+
// Dashboard Fragment NavHost Container
61+
1 -> NavHostContainerFragment.newInstance(
62+
R.layout.fragment_navhost_dashboard,
63+
R.id.nested_nav_host_fragment_dashboard
64+
)
65+
66+
// Notification Fragment NavHost Container
67+
2 -> NavHostContainerFragment.newInstance(
68+
R.layout.fragment_navhost_notification,
69+
R.id.nested_nav_host_fragment_notification
70+
)
71+
72+
// Account Fragment NavHost Container
73+
else -> NavHostContainerFragment.newInstance(
74+
R.layout.fragment_navhost_account,
75+
R.id.nested_nav_host_fragment_account
76+
)
77+
}
78+
}
79+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24"
6+
android:tint="?attr/colorControlNormal">
7+
<path
8+
android:fillColor="@android:color/white"
9+
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
10+
</vector>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24"
6+
android:tint="?attr/colorControlNormal">
7+
<path
8+
android:fillColor="@android:color/white"
9+
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
10+
</vector>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /