I have only one activity in my project and that is MainActivity and I have implemented a collapsing toolbar layout on my MainActivity's layout:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="@style/Theme">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
ads:expandedTitleMarginBottom="24dp"
ads:expandedTitleMargin="16dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/app_bar_img"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop"
ads:srcCompat="@mipmap/logo"
ads:layout_collapseMode="parallax"
ads:layout_collapseParallaxMultiplier="@integer/material_motion_duration_long_2" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
ads:layout_collapseMode="pin"
ads:popupTheme="@style/Widget.AppCompat.PopupMenu.Overflow" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>
and I wanted the toolbar to be visible only when a few specific fragments are active on the screen and to achieve that functionality, I've implemented the logic like this:
BaseActivity.kt:
open class BaseActivity : AppCompatActivity()
MainActivity.kt:
package com.pavan.teja.example
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import androidx.core.text.HtmlCompat
import androidx.databinding.DataBindingUtil
import androidx.navigation.NavController
import androidx.navigation.NavDestination
import androidx.navigation.fragment.findNavController
import com.google.android.material.appbar.AppBarLayout
import com.pavan.teja.example.BaseApplicationStuff.BaseActivity
import com.pavan.teja.example.Utils.Utilities
import com.pavan.teja.example.databinding.ActivityMainBinding
import kotlinx.android.synthetic.main.activity_main.view.*
import timber.log.Timber
class MainActivity : BaseActivity(), AppBarLayout.OnOffsetChangedListener, NavController.OnDestinationChangedListener {
private lateinit var utilities: Utilities
private lateinit var activityMainBinding: ActivityMainBinding
private var navController: NavController? = null
private lateinit var appToolbar: androidx.appcompat.widget.Toolbar
private lateinit var appBarLayout: AppBarLayout
private lateinit var menu: Menu
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
utilities = Utilities()
//Apply security by blocking screenshots
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
//Setting up AppBar
appToolbar = activityMainBinding.toolbar
//setting AppBar Layout
appBarLayout = activityMainBinding.appBar
appBarLayout.addOnOffsetChangedListener(this)
setSupportActionBar(appToolbar)
//Fragment Navigation setup
val navHostFragment =
supportFragmentManager.findFragmentById(activityMainBinding.container.id)
navController = navHostFragment?.findNavController()
navController?.addOnDestinationChangedListener(this)
}
override fun onOffsetChanged(appBarLayout: AppBarLayout?, verticalOffset: Int) {
var isShow = false
var scrollRange = -1
if (scrollRange == -1) {
scrollRange = appBarLayout?.totalScrollRange!!
}
if (scrollRange + verticalOffset == 0) {
isShow = true
// showOption(R.id.action_info)
} else if (isShow) {
isShow = false
// hideOption(R.id.action_info)
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.memu, menu)
if (menu != null) {
this.menu = menu
}
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
}
return super.onOptionsItemSelected(item)
}
private fun hideOption(id: Int) {
val item: MenuItem = menu.findItem(id)
item.isVisible = false
}
private fun showOption(id: Int) {
val item: MenuItem = menu.findItem(id)
item.isVisible = true
}
override fun onSupportNavigateUp(): Boolean {
return navController!!.navigateUp()
}
override fun onDestinationChanged(controller: NavController,
destination: NavDestination,
arguments: Bundle?
) {
when (navController?.currentDestination?.label) {
"SplashScreenFragment" -> {
activityMainBinding.appBar.visibility = View.GONE
// supportActionBar?.hide()
activityMainBinding.container.fitsSystemWindows = true
utilities.hideSystemUI(window, activityMainBinding.root)
}
"InitiationCheckFragment" -> {
activityMainBinding.appBar.visibility = View.GONE
// supportActionBar?.hide()
activityMainBinding.container.fitsSystemWindows = true
utilities.hideSystemUI(window, activityMainBinding.root)
}
"NotInitiatedFragment" -> {
activityMainBinding.appBar.visibility = View.GONE
// supportActionBar?.hide()
activityMainBinding.container.fitsSystemWindows = true
utilities.hideSystemUI(window, activityMainBinding.root)
}
else -> {
// activityMainBinding.container.fitsSystemWindows = false
supportActionBar?.show()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
supportActionBar?.title = getString(R.string.app_bar_title)
// val title = getString(R.string.app_bar_title)
// appToolbar.toolbar.title = title
// appToolbar.showOverflowMenu()
// supportActionBar?.title =
// HtmlCompat.fromHtml("<big>${title}</big>", HtmlCompat.FROM_HTML_MODE_LEGACY)
// activityMainBinding.container.fitsSystemWindows = false
utilities.showSystemUI(window, activityMainBinding.root)
}
}
Timber.d("current active fragment ${navController?.currentDestination?.label}")
}
}
Here's the Utilities class code:
class Utilities {
fun hideSystemUI(window: Window, mainContainer: View) {
WindowCompat.setDecorFitsSystemWindows(window, false)
WindowInsetsControllerCompat(window, mainContainer).let { controller ->
controller.hide(WindowInsetsCompat.Type.systemBars())
controller.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
}
fun showSystemUI(window: Window, mainContainer: View) {
WindowCompat.setDecorFitsSystemWindows(window, true)
WindowInsetsControllerCompat(
window,
mainContainer
).show(WindowInsetsCompat.Type.systemBars())
}
themes.xml:
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.MyCustomAppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">#f21505</item>
<item name="colorPrimaryVariant">#ed594e</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">#f25c05</item>
<item name="colorSecondaryVariant">#f58b4e</item>
<!-- <item name="colorOnSecondary">@color/black</item>-->
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
night/themes.xml:
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.MyCustomAppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">#f21505</item>
<item name="colorPrimaryVariant">#ed594e</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">#f25c05</item>
<item name="colorSecondaryVariant">#f58b4e</item>
<!-- <item name="colorOnSecondary">@color/black</item>-->
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
The app doesn't crash but it doesn't show the app bar when the fragments where I wanted the appbar to be visible.
Now that the toolbar layout is on MainActivity, I haven't implemented anything on the fragments regarding the toolbar. I'm changing the fragments using navController.
Can anyone please help me resolve this problem and make the appbar visible on top of the fragments?
Thank you.