I only added a PreferenceScreen to Android Studio's Basic Views Activity template, and I don't know why the AppBarLayout flashes when a preference is clicked
This is not the behavior of any other clickable element with the AppBarLayout. Upon inspection of snapshots, it seems this is because there is an elevation change when the preference is clicked. While scrolled down, the elevation goes to 0.0 when a preference is clicked, and then rapidly changes when selected again.
activity_main.xml with the app bar and includes content_main.xml:
<androidx.coordinatorlayout.widget.CoordinatorLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_main" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="@dimen/fab_margin"
android:layout_marginBottom="16dp"
app:srcCompat="@android:drawable/ic_dialog_email"
android:contentDescription="@string/fab_description" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
content_main.xml:
<androidx.constraintlayout.widget.ConstraintLayout 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"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<fragment
android:id="@+id/nav_host_fragment_content_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
SettingsFragment class:
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
}
}
preferences.xml:
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<SwitchPreferenceCompat
android:key="switch_preference_1"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_2"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_3"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_4"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_5"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_6"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_7"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_8"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_9"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_10"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_11"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_12"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_13"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_14"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
<SwitchPreferenceCompat
android:key="switch_preference_15"
android:title="Switch Preference"
android:summary="An example that uses a switch" />
</PreferenceScreen>
And finally, my MainActivity class:
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityMainBinding
private var isMenuVisible = true // Default value true to show the menu initially
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.toolbar)
val navController = findNavController(R.id.nav_host_fragment_content_main)
appBarConfiguration = AppBarConfiguration(navController.graph)
setupActionBarWithNavController(navController, appBarConfiguration)
navController.addOnDestinationChangedListener { _, destination, _ ->
// Determine if the menu should be visible based on the current destination
val shouldMenuBeVisible = destination.id != R.id.SettingsFragment
if (shouldMenuBeVisible != isMenuVisible) {
// Only update the menu if the visibility has changed
isMenuVisible = shouldMenuBeVisible
invalidateOptionsMenu() // Trigger a call to onPrepareOptionsMenu
}
}
binding.fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
if (isMenuVisible) {
menuInflater.inflate(R.menu.menu_main, menu)
}
return true
}
// For dynamically adjusting the contents of the options menu based on the current state or
// configuration of the application (whether the current version of the application is taking
// advantage of this function or not).
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
super.onPrepareOptionsMenu(menu)
// Clear the existing menu to ensure it reflects the current state
menu.clear()
// Conditionally inflate the menu based on the current state
if (isMenuVisible) {
menuInflater.inflate(R.menu.menu_main, menu)
}
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_settings -> {
findNavController(R.id.nav_host_fragment_content_main)
.navigate(R.id.action_global_settingsFragment)
true
}
else -> super.onOptionsItemSelected(item)
}
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment_content_main)
return navController.navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
}
