ActionBarDrawerToggle stops working on fragment change - android

I have a HomeActivity which initiates the ActionBarDrawerToggle as follows:
private fun initDrawer() {
val toolbar = binding.fragmentHomeContainerView.findViewById<MaterialToolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
drawerToggle = ActionBarDrawerToggle(
this,
binding.drawer,
toolbar,
R.string.open_drawer,
R.string.close_drawer
)
binding.drawer.addDrawerListener(drawerToggle)
drawerToggle.syncState()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
binding.navigationView.setNavigationItemSelectedListener {
handleNavigationItemSelected(it)
true
}
}
The toolbar in question is inside a Fragment. Everything's normal and working until here, the toolbar is like Gmail's search with the hamburguer icon. But when I navigate to another fragment (that doesn't have this toolbar, but instead has an arrow back button), and then navigate back again to the first fragment (the one that has the toolbar) the icon doesn't work anymore. What's the best/correct solution for this? I've tried moving the initDrawer() function within the fragment but the application frozes when creating the ActionBarDrawerToggle I assume because of the activity passed to the ActionBarDrawerToggle
drawerToggle = ActionBarDrawerToggle(
activity = (requireActivity() as HomeActivity),
...
)
Moving the toolbar from the Fragment to the Activity isn't a solution neither, not because it doesn't fix the problem (which I'm not sure) but because I need the toolbar inside the fragment.
Minimal reproducible code:
MainActivity.kt:
class MainActivity : AppCompatActivity() {
private val binding: ActivityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
private lateinit var drawerToggle: ActionBarDrawerToggle
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
override fun onStart() {
super.onStart()
initDrawer()
}
private fun initDrawer() {
val toolbar = binding.fragmentContainerView.findViewById<MaterialToolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
drawerToggle = ActionBarDrawerToggle(
this,
binding.drawer,
toolbar,
R.string.app_name,
R.string.app_name
)
binding.drawer.addDrawerListener(drawerToggle)
drawerToggle.syncState()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/nav_home" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:clipToPadding="false"
android:visibility="visible" />
</androidx.drawerlayout.widget.DrawerLayout>
Fragment1.kt:
class Fragment1 : Fragment(R.layout.fragment_1) {
private val binding: Fragment1Binding by lazy {
Fragment1Binding.bind(requireView())
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.button.setOnClickListener {
navigateToFragment2()
}
}
private fun navigateToFragment2() {
val action = R.id.navigateToFragment2
Navigation.findNavController(requireView()).navigate(action)
}
}
fragment_1.xml:
<?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/entity_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragment1">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:background="#android:color/transparent"
android:elevation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:liftOnScroll="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="center"
android:layout_margin="6dp"
android:background="#drawable/rounded_toolbar"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
app:contentInsetStart="0dp"
app:contentInsetStartWithNavigation="0dp"
app:navigationIcon="#drawable/ic_baseline_menu_24"
app:titleTextColor="#android:color/white">
<EditText
android:id="#+id/entities_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints="Search for client"
android:background="#android:color/transparent"
android:hint="search"
android:inputType="textPersonName"
android:minHeight="48dp"
android:textColorHint="#color/black" />
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Navigate to fragment 2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/appBarLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
Fragment2.kt:
class Fragment2 : Fragment(R.layout.fragment_2) {
private val binding: Fragment2Binding by lazy {
Fragment2Binding.bind(requireView())
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setActionBarAction()
}
private fun setActionBarAction() {
val action = R.id.navigateToFragment1
binding.toolbar.setOnClickListener {
Navigation.findNavController(it).navigate(action)
}
}
}
fragment_2.xml:
<?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/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragment2">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginStart="4dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:background="#android:color/transparent"
android:elevation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:liftOnScroll="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/toolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|start"
android:clickable="true"
android:focusable="true"
android:minHeight="?attr/actionBarSize"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="#drawable/ic_baseline_chevron_left_32"
app:titleTextColor="#android:color/white">
</com.google.android.material.appbar.MaterialToolbar>
<com.google.android.material.textview.MaterialTextView
android:id="#+id/app_bar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="34sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Navigate back with the arrow button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
nav_home.xml:
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/nav_home"
app:startDestination="#id/fragment1">
<fragment
android:id="#+id/fragment1"
android:name="com.example.myapplication.Fragment1"
android:label="fragment_1"
tools:layout="#layout/fragment_1" >
<action
android:id="#+id/navigateToFragment2"
app:destination="#id/fragment2" />
</fragment>
<fragment
android:id="#+id/fragment2"
android:name="com.example.myapplication.Fragment2"
android:label="fragment_2"
tools:layout="#layout/fragment_2" >
<action
android:id="#+id/navigateToFragment1"
app:destination="#id/fragment1" />
</fragment>
</navigation>

Related

Android drawer layout header - cannot access it

In my past project from the beggining of the year I have set the content of my drawerHeader in the mainActivity code. I am rewriting it and now it seems impossible to access the header through binding in MainActivity.
I have a usual drawer layout in the activity -> navigation view -> drawer header.
I used to access it through simple binding.layoutDrawer.userDataHeader but it doesn't find userDataHeader no matter what I do. What am I doing wrong?
main activity layout
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="mainActivity"
type="com.kerubyte.engagecommerce.presentation.ui.activity.MainActivity" />
</data>
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/layout_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.ui.activity.MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/layout_activity_main_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.ui.activity.MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/layout_actionbar_root"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="#color/primaryColor"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/image_open_drawer_action"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="10dp"
android:onClick="#{() -> mainActivity.openDrawerMenu()}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_hamburger" />
<ImageView
android:id="#+id/image_open_profile_action"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginEnd="24dp"
android:onClick="#{() -> mainActivity.onProfileClick()}"
app:layout_constraintBottom_toBottomOf="#+id/image_open_cart_action"
app:layout_constraintEnd_toStartOf="#+id/image_open_cart_action"
app:layout_constraintTop_toTopOf="#+id/image_open_cart_action"
app:srcCompat="#drawable/ic_person" />
<ImageView
android:id="#+id/image_open_cart_action"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginEnd="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_cart" />
<TextView
android:id="#+id/text_user_cart_items_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="0"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="#+id/image_open_cart_action"
app:layout_constraintEnd_toEndOf="#+id/image_open_cart_action"
app:layout_constraintHorizontal_bias="0.55"
app:layout_constraintStart_toStartOf="#+id/image_open_cart_action"
app:layout_constraintTop_toTopOf="#+id/image_open_cart_action" />
</androidx.constraintlayout.widget.ConstraintLayout>
<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_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/layout_actionbar_root"
app:layout_constraintVertical_bias="1.0"
app:navGraph="#navigation/navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/layout_navigation_menu"
app:headerLayout="#layout/drawer_header"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:maxWidth="300dp"
app:menu="#menu/drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>
</layout>
drawer header layout
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/user_data_header"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.makeramen.roundedimageview.RoundedImageView
android:id="#+id/image_user_avatar"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginTop="16dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:riv_oval="true"/>
<View
android:id="#+id/view_avatar_support"
android:layout_width="1dp"
android:layout_height="1dp"
app:layout_constraintBottom_toBottomOf="#+id/image_user_avatar"
app:layout_constraintEnd_toEndOf="#+id/image_user_avatar"
app:layout_constraintStart_toStartOf="#+id/image_user_avatar"
app:layout_constraintTop_toTopOf="#+id/image_user_avatar" />
<TextView
android:id="#+id/text_user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
android:text="TextView"
app:layout_constraintBottom_toTopOf="#+id/text_user_email"
app:layout_constraintStart_toEndOf="#+id/image_user_avatar" />
<TextView
android:id="#+id/text_user_email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="#+id/image_user_avatar"
app:layout_constraintStart_toEndOf="#+id/image_user_avatar" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Main Activity
#AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val mainViewModel: ActivityMainViewModel by viewModels()
lateinit var binding: ActivityMainBinding
private lateinit var navigationView: NavigationView
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil
.setContentView(
this,
R.layout.activity_main
)
navigationView = binding.layoutNavigationMenu
navController = Navigation.findNavController(
this,
R.id.nav_host_fragment
)
NavigationUI.setupWithNavController(navigationView, navController)
setBindings()
setupObserver()
}
private fun updateDrawerHeader(user: User) {
binding.layoutDrawer.userDataHeader.text_first_name_value_header.text = user.firstName
binding.layoutDrawer.userDataHeader.text_last_name_value_header.text = user.lastName
binding.layoutDrawer.userDataHeader.text_email_value_header.text = user.email
}
}
And Im trying to update the header with
private fun updateDrawerHeader(user: User) {
binding.layoutDrawer.userDataHeader.text_first_name_value_header.text = user.firstName
binding.layoutDrawer.userDataHeader.text_last_name_value_header.text = user.lastName
binding.layoutDrawer.userDataHeader.text_email_value_header.text = user.email
}
userDataHeader I cannot find.

Hiding bottom navigation view on Android

I'm developing an Android app that follows the single activity pattern. In one of my fragments I have a RecyclerView and in the case where the user scrolls down I want to hide my BottomNavigationView.
I have already seen other posts about this matter but none of them seems to help my with my issue. So far I've tried making the bottom nav view and my host fragment childs of CoordinatorLayout as well as adding the app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior" property on my BottomNavigationView. I have also tried to implement this behaviour manually in code but that is not working either.
Here is my activity.xml which contains my BottomNavigationView and my host fragment.
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MainActivity">
<fragment
android:id="#+id/fragmentMaster"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="#id/bottomNav"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/nav_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/menu_bottom_nav">
</com.google.android.material.bottomnavigation.BottomNavigationView>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
And this is the fragment with the RecyclerView
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/topAppBar"
style="#style/Widget.MaterialComponents.Toolbar.Primary"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll"
app:title="#string/app_name" />
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:scrollbars="none"
app:layout_scrollFlags="scroll">
<com.google.android.material.chip.ChipGroup
android:id="#+id/filterChips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
app:singleLine="true">
<com.google.android.material.chip.Chip
android:id="#+id/breakfastChip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkable="true"
android:text="#string/breakfast" />
<com.google.android.material.chip.Chip
android:id="#+id/mealChip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkable="true"
android:text="#string/meal" />
<com.google.android.material.chip.Chip
android:id="#+id/dinnerChip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkable="true"
android:text="#string/dinner" />
<com.google.android.material.chip.Chip
android:id="#+id/veganChip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkable="true"
android:text="#string/vegan" />
<com.google.android.material.chip.Chip
android:id="#+id/vegetarianChip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkable="true"
android:text="#string/vegetarian" />
<com.google.android.material.chip.Chip
android:id="#+id/regularChip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkable="true"
android:text="#string/regular" />
</com.google.android.material.chip.ChipGroup>
</HorizontalScrollView>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recipeList"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:listitem="#layout/item_recipe_list">
</androidx.recyclerview.widget.RecyclerView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/newRecipeBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:contentDescription="#string/add_recipe"
android:src="#drawable/ic_baseline_add_24">
</com.google.android.material.floatingactionbutton.FloatingActionButton>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>
Edit: The issue was that the inner CoordinatorLayout was consuming the scroll event and so the AppBarLayout worked as expected, but the outer CoordinatorLayout that manages the BottomNavView never received the scroll notification. The solution is to overwrite the CoordinatorLayout implementation so that it propagates to the parent CoordinatorLayout.
Preview
Create kotlin class NavigationViewBehavior.kt
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.ViewCompat
import androidx.core.view.ViewCompat.NestedScrollType
import com.google.android.material.bottomnavigation.BottomNavigationView
class NavigationViewBehavior : CoordinatorLayout.Behavior<BottomNavigationView>() {
private var height = 0
override fun onLayoutChild(parent: CoordinatorLayout, child: BottomNavigationView, layoutDirection: Int): Boolean {
height = child.height
return super.onLayoutChild(parent, child, layoutDirection)
}
override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout,
child: BottomNavigationView, directTargetChild: View, target: View,
axes: Int, type: Int): Boolean {
return axes == ViewCompat.SCROLL_AXIS_VERTICAL
}
override fun onNestedScroll(coordinatorLayout: CoordinatorLayout, child: BottomNavigationView,
target: View, dxConsumed: Int, dyConsumed: Int,
dxUnconsumed: Int, dyUnconsumed: Int,
#NestedScrollType type: Int) {
if (dyConsumed > 0) {
slideDown(child)
} else if (dyConsumed < 0) {
slideUp(child)
}
}
private fun slideUp(child: BottomNavigationView) {
child.clearAnimation()
child.animate().translationY(0f).duration = 200
}
private fun slideDown(child: BottomNavigationView) {
child.clearAnimation()
child.animate().translationY(height.toFloat()).duration = 200
}
}
activity_main.xml
<?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/business_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hardwareAccelerated="true">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="#+id/coordinator_business_layout"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="#+id/frame_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="?actionBarSize"
android:orientation="vertical">
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/mobile_navigation"
tools:ignore="FragmentTagUsage" />
</FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
android:background="#color/colorWhite"
app:itemBackground="#drawable/border_bottom_ver"
app:itemIconTint="#drawable/tab_color"
app:itemTextColor="#drawable/tab_color"
app:menu="#menu/bottom_nav_menu" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
call in MainActivity.kt
val navController = Navigation.findNavController(this,
R.id.nav_host_fragment)
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration!!)
NavigationUI.setupWithNavController(navView!!, navController)
val layoutParams = navView!!.getLayoutParams() as CoordinatorLayout.LayoutParams
layoutParams.behavior = NavigationViewBehavior()
val params = frameLayout.layoutParams as ViewGroup.MarginLayoutParams
//hide bottom navigation no need while sun activities are being used
navController.addOnDestinationChangedListener { controller: NavController?,
destination: NavDestination, arguments: Bundle? ->
if (destination.id == R.id.navigation_fragments ) {
params.setMargins(0, 0, 0, 0)
frameLayout.layoutParams = params
navView!!.setVisibility(View.GONE)
} else {
params.setMargins(0, 0, 0, 160)
frameLayout.layoutParams = params
navView!!.setVisibility(View.VISIBLE)
}
}
home_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvServices"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:visibility="visible" />
<TextView
android:id="#+id/no_values_assigned_message"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:text="#string/no_values_assigned"
android:textSize="#dimen/fontSizeReg"
android:textStyle="bold"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
this is the setting my RecyclerView
private fun RecyclerSetting(view: View) {
no_value = view.findViewById(R.id.no_values_assigned_message)
rvItem = view.findViewById(R.id.rvServices)
rvItem!!.setHasFixedSize(true)
//Very IMP This Line
val manager = GridLayoutManager(activity, 2,
GridLayoutManager.VERTICAL,
false)
data
rvItem!!.setLayoutManager(manager)
}
while you scroll recycler view auto-hide and also you can hide bottom navigation from specific Fragment code included

White screen in my activity_main while others not

Hi I am trying to launch an activity which has a navigation drawer and it is simply a Constraintlayout with 4 buttons. But it shows a white screen. My other activities appear perfectly. I don't really know why this happened. It happened before when I was trying to build a gridlayout but now it's just a plain constraintlayout and it still appears the same. If you have any idea, thank you so much!
Here is the XML of a normal layout that works perfectly:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
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/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:titleTextColor="#android:color/white"
android:background="?attr/colorPrimary">
</androidx.appcompat.widget.Toolbar>
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ProfileActivity">
<TextView
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Profile"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:clipToPadding="false"
app:menu="#menu/main_menu"
/>
</androidx.drawerlayout.widget.DrawerLayout>
Here is the XML of the layout that has launching problems :
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
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/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:titleTextColor="#android:color/white" />
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="150dp"
android:text="TextView"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/textView3"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="150dp"
android:text="TextView"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/textView5" />
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="150dp"
android:text="TextView"
android:textSize="30sp"
app:layout_constraintEnd_toStartOf="#+id/textView"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="150dp"
android:text="TextView"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/textView4"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:clipToPadding="false"
app:menu="#menu/main_menu"
/>
</androidx.drawerlayout.widget.DrawerLayout>
Here is MainActivity:
class MainActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.toolbar))
val drawer = findViewById<DrawerLayout>(R.id.drawer)
val drawerToggle = ActionBarDrawerToggle(this, drawer, R.string.open, R.string.close)
drawer.addDrawerListener(drawerToggle)
drawerToggle.syncState()
val navView= findViewById<NavigationView>(R.id.navigation_view)
navView.setNavigationItemSelectedListener{
when(it.itemId){
R.id.nav_profile -> {
var intent = Intent(this, ProfileActivity::class.java)
startActivity(intent)
}
R.id.nav_home -> {
var intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
R.id.nav_schedule -> {
var intent = Intent(this, ScheduleActivity::class.java)
startActivity(intent)
}
R.id.nav_settings -> {
var intent = Intent(this, SettingsActivity::class.java)
startActivity(intent)
}
R.id.nav_tutorial -> {
var intent = Intent(this, TutorialActivity::class.java)
startActivity(intent)
}
R.id.nav_about -> {
var intent = Intent(this, AboutActivity::class.java)
startActivity(intent)
}
R.id.nav_procrastination -> {
var intent = Intent(this, ProcrastinationActivity::class.java)
startActivity(intent)
}
R.id.nav_premium -> {
var intent = Intent(this, PremiumActivity::class.java)
startActivity(intent)
}
}
true
}
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
// override fun onNavigationItemSelected(menuItem: MenuItem): Boolean {
// val drawer = findViewById<DrawerLayout>(R.id.drawer)
// when (menuItem.itemId) {
// R.id.nav_profile -> {
// Intent(this,ProfileActivity::class.java)
// }
// }
// drawer.closeDrawer(GravityCompat.START)
// return true
// }
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val drawer = findViewById<DrawerLayout>(R.id.drawer)
val drawerToggle = ActionBarDrawerToggle(this, drawer, R.string.open, R.string.close)
if(drawerToggle.onOptionsItemSelected(item)){
return true
}
return super.onOptionsItemSelected(item)
}
override fun onBackPressed() {
val drawer = findViewById<DrawerLayout>(R.id.drawer)
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START)
} else {
super.onBackPressed()
}
}
}
I had just created by mistake a v21 layout file for my activity. This one didn't had any xml code inside. And as my phone is higher than API 21 therefore i always got a white screen. I just deleted the file and it worked out.

How to Make Static Navigation Android Tablet? like this design

Hi I'm having trouble on making layout like this design because the navigation bar is difficult to make it become functional.
this is the design
I have created the class like this:
class MainActivity : AppCompatActivity() {
lateinit var navigationView: NavigationView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
navigationView = findViewById(R.id.navigation)
navigationView.setNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
}
private val mOnNavigationItemSelectedListener =
BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_user -> {
val fragment = UserFragment()
addFragment(fragment)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_scaner -> {
val fragment = ScannerFragment()
addFragment(fragment)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_laporan -> {
val fragment = LaporanFragment()
addFragment(fragment)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_notif ->{
val fragment = NotificationFragment()
addFragment(fragment)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_chat -> {
val fragment = LaporanFragment()
addFragment(fragment)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_profile -> {
val fragment = LaporanFragment()
addFragment(fragment)
return#OnNavigationItemSelectedListener true
}
}
false
}
private fun addFragment(fragment: Fragment) = supportFragmentManager
.beginTransaction()
.setCustomAnimations(R.anim.design_bottom_sheet_slide_in, R.anim.design_bottom_sheet_slide_out)
.replace(R.id.content, fragment, fragment.javaClass.simpleName)
.commit()
}
and this is my layout.xml :
<?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:layout_width="match_parent"
android:paddingBottom="20dp"
android:background="#FAFAFC"
android:paddingRight="20dp"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/linearnama"
android:layout_marginStart="20dp"
android:padding="25dp"
android:layout_marginTop="21dp"
android:background="#drawable/bg_white_rounded"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.cardview.widget.CardView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_margin="5dp"
android:id="#+id/foto_profil_operator"
android:elevation="10dp"
app:cardCornerRadius="18dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="51dp"
android:layout_height="51dp"
android:scaleType="centerCrop"
android:src="#drawable/lisa" />
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/poppins"
android:layout_marginStart="15dp"
android:layout_weight="0.2"
android:gravity="left"
android:layout_gravity="center"
android:textColor="#color/colorPrimary"
android:textSize="16sp"
android:text="Nama Operator" />
<ImageView
android:layout_width="200dp"
android:layout_height="match_parent"
android:foregroundGravity="right"
android:layout_gravity="end"
android:layout_weight="0"
android:src="#drawable/logo" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/linearnama"
app:layout_constraintVertical_bias="0.497">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraint_menu"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
android:layout_marginRight="20dp"
android:layout_weight="0.1"
android:background="#drawable/bg_white_rounded"
android:padding="20dp">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MENU"
android:fontFamily="#font/poppins"
android:textColor="#color/black"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:background="#color/white"
app:itemIconTint="#color/black"
app:itemTextColor="#color/black"
app:layout_constraintBottom_toTopOf="#+id/pp2k"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView"
app:menu="#menu/navigation">
</com.google.android.material.navigation.NavigationView>
<TextView
android:id="#+id/pp2k"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="navigation"
android:textColor="#color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<FrameLayout
android:id="#+id/frameLayout"
android:layout_weight="0.5"
android:layout_marginTop="20dp"
android:background="#drawable/bg_white_rounded"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" >
</FrameLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I have tried several navigation listener such as navigationView.setNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
But it won't work. Maybe someone know how I can solve my problem? Thanks in advance

how to set navigation menu dynamically?

In android, I want to set nav menu dynamically according to user.
some user has 3 menus and another usr has only one menu and so on....
how can I set navigation menu dynamically? the setting of the nav menu is written in xml file. I want to set the nav menu in class file and use show and hide the menu
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var navController: NavController
private lateinit var drawerLayout: DrawerLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupNavigationDrawer()
setSupportActionBar(toolbar)
navController = Navigation.findNavController(this,
R.id.nav_fragment
)
appBarConfiguration = AppBarConfiguration
.Builder(R.id.homeFragment, R.id.secondFragment)
.setDrawerLayout(drawerLayout)
.build()
nav_fragment.navGraphViewModels<>()
setupActionBarWithNavController(navController, appBarConfiguration)
navigation_view.setupWithNavController(navController)
}
override fun onSupportNavigateUp(): Boolean {
return findNavController(R.id.nav_fragment).navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
private fun setupNavigationDrawer() {
drawerLayout = (findViewById<DrawerLayout>(R.id.drawer_layout))
.apply {
setStatusBarBackground(R.color.colorPrimaryDark)
}
}
}
<androidx.drawerlayout.widget.DrawerLayout
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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="#style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay"/>
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:id="#+id/nav_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph"/>
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/nav_header"
app:menu="#menu/nav_menu"/>
</androidx.drawerlayout.widget.DrawerLayout>
Make a custom navigation view like below and change Visibility of view according to your condition.
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true" >
<LinearLayout
android:background="#FFFFFF"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/layout_home"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="#dimen/dimen_48dp">
<ImageView
android:id="#+id/nav_home"
app:srcCompat="#drawable/ic_home"
android:layout_width="#dimen/setting_icon"
android:layout_height="#dimen/setting_icon"
android:layout_marginLeft="#dimen/padding_double"
android:layout_marginRight="#dimen/padding_normal"
android:layout_centerVertical="true"
android:clickable="false"
android:focusable="false"
android:tint="#color/color_f85200"
android:layout_gravity="center_vertical"/>
<TextView
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/nav_home"
android:text="#string/title_activity_home"
android:textSize="16sp"
android:clickable="false"
android:focusable="false"
android:fontFamily="#font/sarabun_medium"
android:layout_marginLeft="#dimen/padding_double"
android:layout_gravity="center_vertical"
android:textColor="#color/DrawerTextColor"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
</LinearLayout>
</com.google.android.material.navigation.NavigationView>

Categories

Resources