How to hide BottomSheetDialogFragment after navigating to another fragment - android

i have Fragment that include ImgaeView(s) in it's XML and i'm navigating from these images to another fragments but the problem is that the bottomsheet stays open, how to make it collapse when i navigate to another fragment?
here is a picture of the bottomsheet
and here i navigated to another fragment but the bottomsheet still appears on the screen
here is the code for inside the fragment
class MoreFragment : BottomSheetDialogFragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_more, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
home_button.setOnClickListener{
val homeFragment = HomeFragment()
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.nav_host_fragment, homeFragment, "findThisFragment")
?.addToBackStack(null)
?.commit()
}
so my question is:
how to make it collapse down after i navigate to another fragment?

in Onclick listener before navigating to another fragment call dismiss() function

Just remove .addToBackStack(null) and call method dismiss()

Related

How to use Bottom Navigation within a Fragment rather than Main Activity

I'm trying to use Bottom Navigation in my app. Most explanations online are about using Bottom Navigation to navigate a fragment container from WITHIN the MainActivity. However, I am trying to use the Bottom Navigation from within a fragment and not an activity. Can anybody help me? This is the code I have thus far, the line in bold represents the problem saying:
"Too many arguments for public fun Fragment.findNavController(): NavController defined in androidx.navigation.fragment"
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentHomePageBinding.inflate(inflater, container, false)
val bottomNavigationView = binding.bottomNavigation
val navController = findNavController(**R.id.homeScreenFragment**)
bottomNavigationView.setupWithNavController(navController)
return binding.root
}
}

BottomSheetDialog dims background being used in ViewPager2

I have a fragment that I want to display as an embedded fragment in a ViewPager and as a Bottom Sheet. I followed this https://developer.android.com/reference/android/app/DialogFragment#DialogOrEmbed and created a DialogFragment
private val mViewModel: CardPricesViewModel by viewModels()
private val binding by viewBinding(FragmentCardDetailPricesBinding::inflate)
companion object {
// This is the same value as the navArg name so that the SavedStateHandle can acess from either
const val ARG_SKU_IDS = "skuIds"
fun newInstance(skus: List<Long>?) =
CardDetailPricesFragment().apply {
arguments = Bundle().apply {
putLongArray(ARG_SKU_IDS, skus?.toLongArray())
}
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
}
However, when it gets inflated in a ViewPager the background dims as though it is a BottomSheetDialogFragment
However, when I manually do it with
supportFragmentManager
.beginTransaction()
.replace(binding.cardPricesFragmentContainer.id, cardDetailPricesFragment)
.commit()
It works fine. I see that the FragmentStateAdapter uses FragmentViewHolders instead of the using transactions directly (?), so I am not sure how to resolve this issue. I see that onCreateDialog() is being called, so if I call dismiss() after onViewCreated(), it works properly, but I am not sure if this a workaround
After some digging, I found the DialogFragment.setShowsDialog(boolean) method that you can use to disable the dialog being created.

Single activity: fragment with AppBarLayout

I have a fragment with a RecyclerView in it. When clicking on an item, I'm navigating (with navigation component) to a detail fragment.
Inside the detail fragment, I want to implement the AppBarLayout. But I have already a Toolbar on activity level.
How can I achieve something like this? You can find the video here on Google design guidelines. Not sure if they are starting a new activity. Bottom navigation is also part of my activity and should be visible when navigating to detail fragment with AppBarLayout.
Inside the detail fragment, I want to implement the AppBarLayout. But I have already a Toolbar on activity level.
So, now the activity has a toolbar, and you want to set another toolBar in the DetailFragment. And as you're using navigation components, you are likely making the toolbar managed by the navController
Well, this requires you to move the activity level toolBar to be in the main fragment; that is hosted by navHostFragment.
The reason: because setting another toolbar from the fragment level will duplicate it as the activity level toolbar always persist. Check this answer for that.
And therefore you need to setup the toolBar in the fragments instead; and normally when you move from a fragment to another though the navigation components, no duplication will occur, and now you can have different toolbar as you'd like to.
Here is a schematic demo:
Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun setupActionBar(toolbar: Toolbar) {
setSupportActionBar(toolbar)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
val appBarConfiguration = AppBarConfiguration.Builder(
R.id.fragment, R.id.fragment_b
) .build()
NavigationUI.setupActionBarWithNavController(
this,
mNavController,
navController
)
}
}
FragmentA
class FragmentA : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_a, container, false)
(requireActivity() as MainActivity).setupActionBar(view.findViewById(R.id.fragment_toolbar))
return view
}
}
FragmentB: Similar to FragmentA, but has its own toolBar
class FragmentB : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_b, container, false)
(requireActivity() as MainActivity).setupActionBar(view.findViewById(R.id.fragment_toolbar))
return view
}
}

Jetpack Compose In Fragment doesn't recompose on popbackstack

I'm using the jetpack navigation component here, not the Compose Navigation Component since there are some areas in my app I cannot convert yet.
The issue I'm running into is:
Fragment A starts and contains a ComposeView in it's xml. Fragment A opens Fragment B. But, when you return to Fragment A, the ComposeView is empty and doesn't show anything.
Is this a bug? Is this known? Am I just doing something wrong? I looked into setting the view composition strategy and tried each option and none of them worked.
I found the answer. I had a BaseFragment:
abstract class BaseFragment : Fragment() {
private var hasInitializedRootView = false
private var rootView: View? = null
protected abstract val layoutId: Int
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return getPersistentView(inflater, container, savedInstanceState, layoutId)
}
private fun getPersistentView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?, layout: Int): View? {
if (rootView == null) {
// Inflate the layout for this fragment
rootView = inflater?.inflate(layout, container, false)
} else {
// Do not inflate the layout again.
// The returned View of onCreateView will be added into the fragment.
// However it is not allowed to be added twice even if the parent is same.
// So we must remove rootView from the existing parent view group
// (it will be added back).
(rootView?.parent as? ViewGroup)?.removeView(rootView)
}
return rootView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (!hasInitializedRootView) {
hasInitializedRootView = true
viewCreated(view, savedInstanceState)
}
}
abstract fun viewCreated(view: View, savedInstanceState: Bundle?)
}
What would happen is that onCreateView wouldn't be called as wanted and the composition wouldn't restart. Changing to using a normal Fragment fixed this perfectly.

Base Navigation Fragment for multiple Fragments

Is it possible to create a Navigation Fragment to contain my navigation back button click logic.
Multiple Fragment's that have a back button would then be able then inherit from the Navigation Fragment.
I'm new to Kotlin development. As you see below the SigninFragment inflates the view, I'm not sure how to get a reference to the view & back button in a parent Navigation Fragment
class SigninFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_signin, container, false)
// Navigation back button logic
var headerBackButton = view.findViewById<ImageButton>(R.id.headerBackButton)
headerBackButton.setOnClickListener {
val navController = NavHostFragment.findNavController(this#SignInFragment)
navController.navigateUp()
}
return view
}
}
I'm not sure if I got your problem right but could this be the trick?
open class NavigationFragment() : Fragment() {
fun asignNavigationBackClickListener(backButton: View) {
backButton.setOnClickListener {
val navController = NavHostFragment.findNavController(this#NavigationFragment)
navController.navigateUp()
}
}
}
class SigninFragment : NavigationFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_signin, container, false)
asignNavigationBackClickListener(view.findViewById(R.id.headerBackButton))
return view
}
}
I think you can use this code for going back to the previous activity:
headerBackButton.setOnClickListener {
finish()
}

Categories

Resources