6

I want to hide bottomNavigationView in some fragments.

I have tried the below code, but it has a flicker effect. (bottomNavigationView hide before the nextFragment becomes visible.

    val navController = this.findNavController(R.id.nav_host_home)
    navController.addOnDestinationChangedListener { _, destination, _ ->
    when (destination.id) {
        R.id.searchArticlesFragment -> bnvMain.visibility = View.GONE
        R.id.articleFragment -> bnvMain.visibility = View.GONE
            else -> bnvMain.visibility = View.VISIBLE
        }
    }

I have also tried another code. But it resizes the fragment. And giving OutOfMemoryException in Destination Fragment.

    supportFragmentManager.registerFragmentLifecycleCallbacks(object :
        FragmentManager.FragmentLifecycleCallbacks() {
        override fun onFragmentViewCreated(
            fm: FragmentManager,
            f: Fragment,
            v: View,
            savedInstanceState: Bundle?
        ) {
            when (f) {
                is SearchArticlesFragment -> bnvMain.visibility = View.GONE
                is ArticleDetailsFragment -> bnvMain.visibility = View.GONE
                else -> bnvMain.visibility = View.VISIBLE
            }
        }
    }, true)

Please help me how can I hide the bottomNavigationView in the proper and best possible way? Is this the only way I can hide the bottomNavigationView? How youtube and Instagram achieve this behavior?

Shalu T D
  • 3,921
  • 2
  • 26
  • 37
Milan Thakor
  • 103
  • 3
  • 7

1 Answers1

11

If your code follows single activity design pattern then the following solution suites you.

  1. Create a method inside the parent activity to hide/show bottomNavigationView.
  2. Create a BaseFragment class(create your fragments by extending this BaseFragment Class)
  3. In the BaseFragment create a variable to hold the bottomNavigationViewVisibility (hide/show)
  4. In onActivityCreated method of the BaseFragment, get the activity reference and set the bottomNavigationViewVisibility by calling the method which we created in STEP1.
  5. In each fragment you create, just set the bottomNavigationViewVisibility variable.

Example: In parentAcitivty layout, file add bottomNavigationView

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/main_bottom_navigation_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?android:attr/windowBackground"
            app:labelVisibilityMode="labeled"
            app:menu="@menu/main_nav" />

Step 1: In parent activity, create a method to change the visibility.

 fun setBottomNavigationVisibility(visibility: Int) {
        // get the reference of the bottomNavigationView and set the visibility.
        activityMainBinding.mainBottomNavigationView.visibility = visibility
    }

Step 2 & 3 & 4:

    abstract class BaseFragment : Fragment() {
    
        protected open var bottomNavigationViewVisibility = View.VISIBLE
    
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            super.onActivityCreated(savedInstanceState)
            // get the reference of the parent activity and call the setBottomNavigationVisibility method.
            if (activity is MainActivity) {
               var  mainActivity = activity as MainActivity
                mainActivity.setBottomNavigationVisibility(bottomNavigationViewVisibility)
            }
        }
 override fun onResume() {
        super.onResume()
        if (activity is MainActivity) {
            mainActivity.setBottomNavigationVisibility(bottomNavigationViewVisibility)
        }
    }
    }

Step 5:

class SampleFragment1 : BaseFragment() {

    // set the visibility here, it takes care of setting the bottomNavigationView.
    override var navigationVisibility = View.VISIBLE
    
   // override var navigationVisibility = View.GONE

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_sampleFragment1, container, false)
    }
}
  • 1
    Thank you so much for the answer. This is really helpful, it works like charm!!. One thing I have to mention is I have changed `onActivityCreated()` method to `onStart()`, because when I navigate back to the previous fragment, `onStart()` is the method which is triggering(don't know why but official doc say `onCreateView()` will call). But I solved my problem. Again, Thank you:) – Milan Thakor Jun 24 '20 at 12:16
  • @MilanThakor, instead of adding it to onStart(), it can be added to onResume(). (Note: I have updated the post to reflect the same) onResume is called wherever you navigate back from other fragment. To your second question, onCreateView() is called only when the fragment is created, in your case when you navigate to the next fragment the current fragment instance is not destroyed completely instead it is placed in the backstack and when you hit back is resumes. – Manimaran Narasimman Jun 24 '20 at 18:40