Reputation: 67
I would like to use a fullscreen fragment in my button navigation based layout. The issue is that the content is not filling up the hidden navigation space. My goal is to make it fill the whole screen without navigation or status bar.
Activity xml:
<com.flipboard.bottomsheet.BottomSheetLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/bottomsheet"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu" />
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/nav_view"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:navGraph="@navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.flipboard.bottomsheet.BottomSheetLayout>
Fragment code: (From Android Studio's Fullscreen Fragment template)
class FullscreenFragment : Fragment() {
private val hideHandler = Handler()
@Suppress("InlinedApi")
private val hidePart2Runnable = Runnable {
// Delayed removal of status and navigation bar
// Note that some of these constants are new as of API 16 (Jelly Bean)
// and API 19 (KitKat). It is safe to use them, as they are inlined
// at compile-time and do nothing on earlier devices.
val flags =
View.SYSTEM_UI_FLAG_LOW_PROFILE or
View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
activity?.window?.decorView?.systemUiVisibility = flags
(activity as? AppCompatActivity)?.supportActionBar?.hide()
}
private val showPart2Runnable = Runnable {
// Delayed display of UI elements
fullscreenContentControls?.visibility = View.VISIBLE
}
private var visible: Boolean = false
private val hideRunnable = Runnable { hide() }
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
private val delayHideTouchListener = View.OnTouchListener { _, _ ->
if (AUTO_HIDE) {
delayedHide(AUTO_HIDE_DELAY_MILLIS)
}
false
}
private var dummyButton: Button? = null
private var fullscreenContent: View? = null
private var fullscreenContentControls: View? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_fullscreen, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
visible = true
dummyButton = view.findViewById(R.id.dummy_button)
fullscreenContent = view.findViewById(R.id.fullscreen_content)
fullscreenContentControls = view.findViewById(R.id.fullscreen_content_controls)
// Set up the user interaction to manually show or hide the system UI.
fullscreenContent?.setOnClickListener { toggle() }
// Upon interacting with UI controls, delay any scheduled hide()
// operations to prevent the jarring behavior of controls going away
// while interacting with the UI.
dummyButton?.setOnTouchListener(delayHideTouchListener)
}
override fun onResume() {
super.onResume()
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
delayedHide(100)
}
override fun onPause() {
super.onPause()
activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
// Clear the systemUiVisibility flag
activity?.window?.decorView?.systemUiVisibility = 0
show()
}
override fun onDestroy() {
super.onDestroy()
dummyButton = null
fullscreenContent = null
fullscreenContentControls = null
}
private fun toggle() {
if (visible) {
hide()
} else {
show()
}
}
private fun hide() {
// Hide UI first
fullscreenContentControls?.visibility = View.GONE
visible = false
// Schedule a runnable to remove the status and navigation bar after a delay
hideHandler.removeCallbacks(showPart2Runnable)
hideHandler.postDelayed(hidePart2Runnable, UI_ANIMATION_DELAY.toLong())
}
@Suppress("InlinedApi")
private fun show() {
// Show the system bar
fullscreenContent?.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
visible = true
// Schedule a runnable to display UI elements after a delay
hideHandler.removeCallbacks(hidePart2Runnable)
hideHandler.postDelayed(showPart2Runnable, UI_ANIMATION_DELAY.toLong())
(activity as? AppCompatActivity)?.supportActionBar?.show()
}
/**
* Schedules a call to hide() in [delayMillis], canceling any
* previously scheduled calls.
*/
private fun delayedHide(delayMillis: Int) {
hideHandler.removeCallbacks(hideRunnable)
hideHandler.postDelayed(hideRunnable, delayMillis.toLong())
}
companion object {
/**
* Whether or not the system UI should be auto-hidden after
* [AUTO_HIDE_DELAY_MILLIS] milliseconds.
*/
private const val AUTO_HIDE = true
/**
* If [AUTO_HIDE] is set, the number of milliseconds to wait after
* user interaction before hiding the system UI.
*/
private const val AUTO_HIDE_DELAY_MILLIS = 3000
/**
* Some older devices needs a small delay between UI widget updates
* and a change of the status and navigation bar.
*/
private const val UI_ANIMATION_DELAY = 300
}
}
Upvotes: 3
Views: 5347
Reputation: 101
according this BottomNavigationView issue post:
https://github.com/material-components/material-components-android/issues/499#issuecomment-519618931
bottomNavigationView.setOnApplyWindowInsetsListener(null);
the code sample above might solve this problem.
Upvotes: 5
Reputation: 67
I solved this issue using this code:
@Suppress("InlinedApi")
private val hidePart2Runnable = Runnable {
val flags =
(View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
activity?.window?.decorView?.systemUiVisibility = flags
(activity as? AppCompatActivity)?.apply {
supportActionBar?.hide()
nav_view?.isVisible = false
}
}
And on show:
// Show the system bar
player_view?.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
// Schedule a runnable to display UI elements after a delay
hideHandler.removeCallbacks(hidePart2Runnable)
(activity as? AppCompatActivity)?.apply {
supportActionBar?.show()
nav_view?.isVisible = true
}
Upvotes: -1
Reputation: 435
you can not hide the status bar and if you hide your bottom navigation how will the user navigate to other fragments?
if you just want to hide the toolbar use this style in the activity containing the bottom navigation
<style name="full_screen" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimaryDark">@color/colorPrimary</item>
</style>
Upvotes: -2