No drawer view found with gravity LEFT - Android - android

My menu was opening from left to right, but I want it to be opened from right to left. I have arranged the code to be opened from right to left, but now the code does not work I get the following error.
java.lang.IllegalArgumentException: No drawer view found with gravity LEFT
I get an error on this line : return NavigationUI.navigateUp(navController, mAppBarConfiguration)
MAİN CLASS
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
NavigationView navigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_sss, R.id.nav_gelisim,
R.id.nav_destek,R.id.nav_hakkımızda,R.id.nav_instagram)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
}
XML
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layoutDirection="rtl"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:itemTextColor="#color/white"
app:itemTextAppearance="#style/NavDrawerTextStyle"
android:layout_gravity="right"
android:theme="#style/NavigationView"
android:background="#color/NavItem"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main2"
app:menu="#menu/activity_main_drawer"/>
</androidx.drawerlayout.widget.DrawerLayout>

You need to handle navigation click on Toolbar like below:
ViewCompat.setLayoutDirection(toolbar, ViewCompat.LAYOUT_DIRECTION_RTL);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (drawer.isDrawerOpen(GravityCompat.END))
drawer.closeDrawer(GravityCompat.END);
else
drawer.openDrawer(GravityCompat.END);
}
});
Also don't forgot to close drawer whenever needed like below:
drawer.closeDrawer(GravityCompat.END)

You could possible find your answer here in this previous post:
Android DrawerLayout - No drawer view found with gravity

You have to set layout Direction in Your Root Drawer Layout
android:layoutDirection="rtl"

If you set the layout direction of the root drawer as follows:
android:layoutDirection="rtl"
All elements will change direction. To solve this, place all elements within a LinearLayout and set LinearLayout direction to ltr.
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
**android:layoutDirection="rtl"**
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
**android:layoutDirection="ltr"**>
<!--place your layout here-->
</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"
android:layoutDirection="rtl"
app:menu="#menu/drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>
If you are using the navigation component use the below code in your activity class.
override fun onCreate(savedInstanceState: Bundle?) {
//...
val navHostFragment = supportFragmentManager.findFragmentById(
R.id.my_nav_host_fragment
) as NavHostFragment
navController = navHostFragment.navController
binding.navigationView.setupWithNavController(navController)
//...
}
override fun onSupportNavigateUp(): Boolean {
return NavigationUI.navigateUp(navController, binding.drawerLayout)
}
override fun onBackPressed() {
if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
binding.drawerLayout.closeDrawer(GravityCompat.START)
} else {
super.onBackPressed()
}
}

It seems like the DrawerLayout need to be in the start direction every time,
if you want it to open from the left you need to do the following:
make your DrawerLayout android:layoutDirection="ltr"
remove tools:openDrawer from your DrawerLayout XML
put your NaviagtionView android:layout_gravity="start"
if you want your content to be RTL don't forget to do this in your contentView container android:layoutDirection="rtl"
and it will work like a charm!

Related

Navigation Drawer Activity's menu items are not clickable

I am trying to create a new activity with drawer layout. To do this, I used Android Studio's default code generator: File -> New -> Activity -> Navigation Drawer Activity. It created a bunch of files with fragments, drawer, and (jetpack) navigation support and their corresponding resources such as navigation file and layout files. I tried to run the new activity and it installed successfully. The problem is, my navigation drawer is not working. The menu items in my drawer do not trigger any change in host navigation fragment.
I've been stuck for a day already and have tried many solutions already and still, my menu items won't let me navigate to another destination.
Here is my resulting MainActivity.java:
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
private ActivityMainBinding binding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.appBarMain.toolbar);
DrawerLayout drawer = binding.drawerLayout;
NavigationView navigationView = binding.navView;
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
.setOpenableLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
return NavigationUI.onNavDestinationSelected(
item,
Navigation.findNavController(this, R.id.nav_host_fragment_content_main)) ||
super.onOptionsItemSelected(item);
}
}
The overridden onOptionsItemSelected() function is from Android's codelab.
Here is my navigation file:
<?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/mobile_navigation"
app:startDestination="#+id/nav_home">
<fragment
android:id="#+id/nav_home"
android:name="com.bicolexpress.delivery.ui.main.ui.home.HomeFragment"
android:label="#string/menu_home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/nav_gallery"
android:name="com.bicolexpress.delivery.ui.main.ui.gallery.GalleryFragment"
android:label="#string/menu_gallery"
tools:layout="#layout/fragment_gallery" />
<fragment
android:id="#+id/nav_slideshow"
android:name="com.bicolexpress.delivery.ui.main.ui.slideshow.SlideshowFragment"
android:label="#string/menu_slideshow"
tools:layout="#layout/fragment_slideshow" />
</navigation>
Based on the codelab link above:
If NavigationUI finds a menu item with the same ID as a destination on
the current graph, it configures the menu item to navigate to that
destination.
This is true for the generated menu items and destination IDs. But still, does not work. Can anyone point me to what I missed? I desperately need your help.
Android Studio Version: Electric Eel | 2022.1.1
So I tried to copy the layout from codelab. And guess what, the click listeners worked!
I noticed that in codelab's layout, the NavigationView was added into the DrawerLayout as the last child. So I modified my activity_main.xml to:
<?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_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
android:id="#+id/app_bar_main"
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<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"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>

Change Floating Action Button Image Programmatically in DrawerLayout

Just as the title suggest, I am trying to change the floating image button's icon/image programmatically when the user open specifics fragment from DrawerLayout. This is what I've alredy tried : First, this is the onCreate() method for the DrawerLayout class.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu_drawer);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), TransaksiKeranjang.class);
startActivity(intent);
}
});
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_transaksi, R.id.nav_pesanan, R.id.nav_sejarah, R.id.nav_inventory,
R.id.nav_akun, R.id.nav_cabang, R.id.nav_laporan, R.id.nav_logout)
.setDrawerLayout(drawer)
.build();
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
//Change fab icon when branch fragment open
navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
#Override
public void onDestinationChanged(#NonNull NavController controller, #NonNull NavDestination destination, #Nullable Bundle arguments) {
if (destination.getId() == R.id.nav_cabang) {
fab.setImageDrawable(ContextCompat.getDrawable(getParent(), R.drawable.icon_add));
}
}
});
navigationView.getMenu().findItem(R.id.nav_logout).setOnMenuItemClickListener(menuItem -> {
Intent intent = new Intent(MenuDrawer.this, Login.class);
startActivity(intent);
return true;
});
}
And then this is the xml where floating action button exist :
<?xml version="1.0" encoding="utf-8"?>
<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:background="#drawable/background_fragment"
tools:context=".MenuDrawer">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/Theme.HuwenakApp.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/huwenak_brown"
app:popupTheme="#style/Theme.HuwenakApp.PopupOverlay" />
</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_margin="#dimen/fab_margin"
android:src="#drawable/icon_cart" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
The problem is when I try to change the fab image I always get a nullPointerException error in this line :
fab.setImageDrawable(ContextCompat.getDrawable(getParent(), R.drawable.icon_add));
Which is weird because the onClickListener is working fine and not giving me this error.
You have to add the context
fab.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.icon_add))
You see in documentation getDrawable need context and if you pass the parent then you get the below error
Attempt to invoke virtual method 'android.graphics.drawable.Drawable android.content.Context.getDrawable(int)' on a null object reference
getDrawable(#NonNull Context context, #DrawableRes int id)

Android navigation onNavigationItemSelected not called

I have this DrawerLayout
<?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/stock_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/stock_app_bar"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_stock_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/stock_nav_header"
app:menu="#menu/stock_activity_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
and then in the activity I have the following onCreate function:
class StockMainActivity: AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_stock_main)
val toolbar: Toolbar = findViewById(R.id.stock_toolbar)
setSupportActionBar(toolbar)
val drawerLayout: DrawerLayout = findViewById(R.id.stock_drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_stock_view)
navView.bringToFront()
navView.setNavigationItemSelectedListener { item ->
if (item.itemId == R.id.nav_stock_home) {
finish()
}
true
}
val navController = findNavController(R.id.nav_stock_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(setOf(
R.id.nav_stock_home,
R.id.stock_navigation_fragment
), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_stock_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
But the navigation selected item listener is never called. It eventually navigates to the destination, but the listener is never called. I have checked similar posts, some suggesting to bring to the front the Navigation View, but to no avail. Please help ...
Ok, I have found the solution. I have put:
navView.bringToFront()
navView.setNavigationItemSelectedListener { item ->
if (item.itemId == R.id.nav_stock_home) {
finish()
}
true
}
At the end of onCreate... and it works now.

(Navigation component) How to display back arrow on the activity when back to the home fragment?

I have to fragments discount fragment and edit service fragment displayed on Edit Service activity.
the back arrow displayed on discount fragment when i back to edit service fragment the arrow disappear i want to display it to navigate the previous activity from edit service activity.
activity layout
.........................................................
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar_hesham"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:title="#string/edit_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:layout_constraintTop_toTopOf="parent" />
<fragment
android:id="#+id/nav_host_edit_service"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#+id/toolbar_hesham"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="#navigation/edit_service_nav" />
</androidx.constraintlayout.widget.ConstraintLayout>
<include layout="#layout/confirm_request_bottom_sheet"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
activity code
.............................................................
public class EditServicesActivity extends BaseActivity<MainViewModel> {
public Toolbar toolbar;
public NavController navController;
#Override
protected void initActivityComponent() {
component = ProServeTechApp.getComponent(this)
.plus(new ActivityModule(this));
component.inject(this);
}
#Override
protected int getLayout() {
return R.layout.activity_edit_services;
}
#Override
protected Class<MainViewModel> getViewModelClass() {
return MainViewModel.class;
}
#Override
protected void initActivity() {
viewModel.getRequestDetails(getIntent().getExtras().getString("requestId"), String.valueOf(0));
viewModel.getIssues(getIntent().getStringExtra("requestId"));
toolbar = findViewById(R.id.toolbar_hesham);
setSupportActionBar(toolbar);
navController = Navigation.findNavController(this, R.id.nav_host_edit_service);
NavigationUI.setupWithNavController(toolbar, navController );
}
}
navigation
........................................
<?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/edit_service_nav"
app:startDestination="#id/edi_service_fragment">
<fragment
android:id="#+id/edi_service_fragment"
android:name="com.unicomg.proservetech.ui.requestdetails.edit.service.fragments.EditServiceFragment"
android:label="#string/edit_service"
tools:layout="#layout/edit_service_fragment">
<action
android:id="#+id/action_edi_service_fragment_to_discount_fragment"
app:destination="#id/discount_fragment"
app:enterAnim="#anim/slide_up"
app:exitAnim="#anim/slide_bottom"
app:popEnterAnim="#anim/slide_up"
app:popExitAnim="#anim/slide_bottom" />
</fragment>
<fragment
android:id="#+id/discount_fragment"
android:name="com.unicomg.proservetech.ui.requestdetails.edit.service.fragments.DiscountFragment"
android:label="#string/add_discount"
tools:layout="#layout/discount_fragment">
</fragment>
</navigation>
As per the setupWithNavController(Toolbar, NavController) documentation:
The start destination of your navigation graph is considered the only top level destination. On all other destinations, the Toolbar will show the Up button.
If you want to also show the Up button on your start destination (i.e., to go to the previous activity), you'd want to use the version that takes an AppBarConfiguration.
As per the Update UI components documentation on AppBarConfiguration, AppBarConfiguration allows you to set exactly what destinations you want as top level destinations. To get the Up button to show on every destination, you'd use an empty set of top level destinations:
AppBarConfiguration appBarConfiguration =
new AppBarConfiguration.Builder().build();
Note that since you're using setSUpportActionBar(), you should follow the Action Bar documentation and use the setupActionBarWithNavController() method rather than the Toolbar version. You must also override onSupportNavigateUp() to handle the up button.
Therefore your complete code would look like:
public class EditServicesActivity extends BaseActivity<MainViewModel> {
public Toolbar toolbar;
public AppBarConfiguation appBarConfiguation;
public NavController navController;
#Override
protected void initActivityComponent() {
component = ProServeTechApp.getComponent(this)
.plus(new ActivityModule(this));
component.inject(this);
}
#Override
protected int getLayout() {
return R.layout.activity_edit_services;
}
#Override
protected Class<MainViewModel> getViewModelClass() {
return MainViewModel.class;
}
#Override
protected void initActivity() {
viewModel.getRequestDetails(getIntent().getExtras().getString("requestId"), String.valueOf(0));
viewModel.getIssues(getIntent().getStringExtra("requestId"));
toolbar = findViewById(R.id.toolbar_hesham);
setSupportActionBar(toolbar);
navController = Navigation.findNavController(this, R.id.nav_host_edit_service);
appBarConfiguration = new AppBarConfiguration.Builder().build();
NavigationUI.setupActionBarWithNavController(this, navController,
appBarConfiguration);
}
#Override
public boolean onSupportNavigateUp() {
return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp();
}
}

BottomAppBar with BottomNavigationDrawer connected to NavigationController

Hi I'm trying to use new arch components in my project. Short description what I want to achieve:
When user is on MainFragment I want to display navigation icon (Hamburger) on BottomAppBar. User is able to click navigation icon and display BottomNavigationDrawer
When user select some menu item, or click something on MainFragment he is moved to another fragment, let say DebtDetailsFragment. Then Hamburger should be replaced with 'Back arrow' by NavigationController
Below I pasted my MainActivity code. When I comment line with navigation controller, the Hamburger icon is visible and BottomNavigationDrawer is able to display.
But when I uncomment this line, the Hamburger disappear because NavigationController knows nothing about NavigationView used in BottomNavigationDrawer. I don't use DrawerLayout, so controller thinks Hamburger is not needed.
Method setupWithNavController can control Hamburger icon and back arrow, but I have to provide DrawerLayout as parameter which I don't use.
Documentation for this method:
The Toolbar will also display the Up button when you are on a non-root destination and the drawer icon when on the root destination, automatically animating between them. This method will call [DrawerLayout.navigateUp] when the navigation icon is clicked.
So the question is, how to display Hamburger icon when NavigationController is connected with BottomAppBar but without DrawerLayout? I will handle hamburger click myself in onOptionsItemSelected method.
class MainActivity : BaseActivity() {
#Inject
lateinit var viewModelProvider: ViewModelProvider.Factory
private val viewModel: MainActivityViewModel by lazy {
ViewModelProviders.of(this, viewModelProvider).get(MainActivityViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(bottomAppBar)
val navController = findNavController(R.id.main_nav_host_fragment)
//bottomAppBar.setupWithNavController(navController)
onDestroyDisposables += viewModel.uiStateObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(::render, Timber::e)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.bottomappbar_menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
android.R.id.home -> {
val bottomNavDrawerFragment = BottomNavigationDrawerFragment()
bottomNavDrawerFragment.show(supportFragmentManager, bottomNavDrawerFragment.tag)
}
}
return super.onOptionsItemSelected(item)
}
override fun onSupportNavigateUp(): Boolean {
return findNavController(R.id.main_nav_host_fragment).navigateUp()
}
}
Without setted Navigation controller:
BottomNavigationDrawer
With setted NavigationController - Hamburger invisible.
The BottomAppBar should never display an Up button as per the anatomy of the BottomAppBar - it should only ever display the drawer icon. As seen in the behavior documentation, the Up button should be displayed in a top Toolbar.
Therefore, you should never be calling bottomAppBar.setupWithNavController(navController), but instead calling setupWithNavController(navController) using whatever top Toolbar you have.
To set up your BottomAppBar, you should instead set your own drawer icon and handle clicks on the drawer icon yourself.
The DrawerArrowDrawable class is available to give you a correct drawer icon:
val icon = DrawerArrowDrawable(bottomAppBar.context)
bottomAppBar.navigationIcon = icon
I implemented the BottomAppBar with Jetpack navigation drawer component as following way in my app.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomAppBar bottomAppBar = findViewById(R.id.bottomAppBar);
setSupportActionBar(bottomAppBar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
NavigationView navigationView = findViewById(R.id.nav_view);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupWithNavController(navigationView, navController);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
return NavigationUI.navigateUp(navController, drawer)
|| super.onSupportNavigateUp();
}
}
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_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<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"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
app_bar_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<include layout="#layout/content_main" />
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bottomAppBar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_gravity="bottom"
app:fabCradleVerticalOffset="16dp"
app:navigationIcon="#drawable/ic_baseline_menu_24"
app:navigationContentDescription="#string/nav_header_desc"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
style="#style/Widget.MaterialComponents.BottomAppBar.Colored"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_menu_send"
app:layout_anchor="#id/bottomAppBar"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
The result will be like this

Categories

Resources