Reputation: 61
I implemented the bottom navigation bar using Navigation Component
, it works fine when changing fragments using the bottom navigation bar. But when I navigate from within a fragment, it jumps and creates a white space - gif
How can I fix this?
Here is the XML for activity_main
<?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_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
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/nav_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav_bar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/bottom_menu"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Edit :
This problem was caused because I tried to show and hide the top toolbar.
I used the following code to show/hide toolbar in the OnCreateView()
function of the fragments
code : (activity as AppCompatActivity).supportActionBar?.show()
and (activity as AppCompatActivity).supportActionBar?.hide()
How can I fix the above problem without losing the hide/show toolbar functionality?
Upvotes: 2
Views: 766
Reputation: 21
This might be a bit late, but perhaps helps someone else.
So, to solve this, you have to do 3 things:
1: Add the action bar as an overlay over your layout system:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
...
<item name="windowActionBarOverlay">true</item>
</style>
This ensures that hiding the BottomNavigationView doesn't jump, flicker, or create any unwanted white space. Obviously, this will overlap your layout, so you could set a marginTop of the preferred action bar height. So, so far no more white space and jumps on the bottom, but this leads to another problem, there will be a permanent whitespace when the action bar is hidden. Combatting this leads to the next point
2: Add an auxiliary view instead of a top margin of height exactly as of the action bar's:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="@+id/toolbar_placeholder"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height" />
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar_placeholder" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_nav_height"
android:layout_alignParentBottom="true"
app:itemBackground="@drawable/bg_bottom_nav_item"
app:itemIconTint="@drawable/nav_item_color_state"
app:itemTextColor="@drawable/nav_item_color_state"
app:labelVisibilityMode="labeled" />
</RelativeLayout>
We will show/hide this auxiliary view at the top of the layout, named toolbar_placeholder
3: Actually hide and show the toolbar placeholder:
myRecyclerView.addOnScrollListener(object: RecyclerView.OnScrollListener() {
val mainActivity = requireActivity() as MainActivity
var scrollDown = false
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (scrollDown) {
// set toolbar_placeholder visibility to View.GONE
// hide the action bar
// hide the bottom navigation bar (preferably with animation)
} else {
// set toolbar_placeholder visibility to View.VISIBLE
// show the action bar
// show the bottom navigation bar (preferably with animation)
}
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
if (dy > 50) {
scrollDown = true
} else if (dy < -5) {
scrollDown = false
}
}
})
PS: (you can try setting a marginTop anc changing the LayoutParams alltogether programatically instead of hiding and showing the toolbar placeholder View, but I chose the latter one)
Cheers!
Upvotes: 2