I am trying to apply a lesson I have seen about the Navigation Drawer Activity with Fragments and MVVM "the new Components", in this simple app I have three Fragments I try to navigate between them using
navController.addOnDestinationChangedListener
and show a toast message, but it seems that the code does not work and I do not know the reason
here's the my code
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
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();
}
});
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// 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)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
#Override
public void onDestinationChanged(#NonNull NavController controller, #NonNull NavDestination destination, #Nullable Bundle arguments) {
int menuId = destination.getId();
switch (menuId){
case R.id.nav_gallery:
fab.hide();
Toast.makeText(getApplicationContext(),"Gallery",Toast.LENGTH_LONG).show();
fragmentTransaction.replace(R.id.homeFragment,new GalleryFragment());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
NavGraph navGraph = new NavGraph()
// controller.getGraph().clear();
// controller.navigate(R.id.nav_gallery);
break;
case R.id.nav_slideshow:
fab.hide();
Toast.makeText(getApplicationContext(),"Slideshow",Toast.LENGTH_LONG).show();
break;
}
}
});
}
#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);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| 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">
<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" />
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.drawerlayout.widget.DrawerLayout>
content.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:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_main">
<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:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
mobile_navigation.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/mobile_navigation"
app:startDestination="#+id/nav_home">
<fragment
android:id="#+id/nav_home"
android:name="com.test.dummyappv3.ui.home.HomeFragment"
android:label="#string/menu_home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/nav_gallery"
android:name="com.test.dummyappv3.ui.gallery.GalleryFragment"
android:label="#string/menu_gallery"
tools:layout="#layout/fragment_gallery" />
<fragment
android:id="#+id/nav_slideshow"
android:name="com.test.dummyappv3.ui.slideshow.SlideshowFragment"
android:label="#string/menu_slideshow"
tools:layout="#layout/fragment_slideshow" />
</navigation>
while I searching for the solution I found this answer, and I tried to using the controller like this
controller.getGraph().clear();
controller.navigate(R.id.nav_gallery);
instead to using the fragment transaction but it's also not working
Ok you need to understand 2 Things.
The NavigationController does not have anything in common with the FragmentManager, except that it can swap Fragments too.
Applying your lesson, you need to either decide to use the FragmentManager OR the NavigationController.
Using both at the same time will not only confuse yourself, but also could crash the app itself.
The problem here
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Move this include from here to the top of NavigationView
<?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>
then everything will be okay
Related
I am trying to use the NavigationUI and toolbar's menu to navigate across fragments.
I follow the guide in Google as below:
https://developer.android.com/guide/navigation/navigation-ui?hl=en#support_app_bar_variations
However, I cannot use the toolbar's menu to navigate from fragment A to fragment B
My Fragment has its own toolbar and menu as below XML
<com.google.android.material.appbar.AppBarLayout 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="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<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"
android:theme="?attr/actionBarTheme"
app:menu="#menu/menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>
My toolbar menu is
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/fragmentA"
android:title="#string/fragmentA" />
<item
android:id="#+id/fragmentB"
android:title="#string/fragmentB" />
</menu>
The NAV Host is in my main activity with a nav graph as below:
<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/user"
app:startDestination="#id/userList">
<fragment
android:id="#+id/fragmentA"/>
<fragment
android:id="#+id/fragmentB"/>
</navigation>
In my fragment, I have below code to setup the NavigationUI navigation
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
NavController navController = Navigation.findNavController(view);
AppBarConfiguration appBarConfiguration =
new AppBarConfiguration.Builder(navController.getGraph()).build();
Toolbar toolbar = view.findViewById(R.id.toolbar);
NavigationUI.setupWithNavController(
toolbar, navController, appBarConfiguration);
}
Whenever I run this app everythning works fine. But nothing happens when I click to drawer options. When I debug, I realized that the method onNavigationItemSelected not even called by system. But When I make my fragment transaction commit in onCreate method, Everything works fine.
here is activiy.java
ublic class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{
DrawerLayout drawerLayout;
ActionBarDrawerToggle toggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id._toolbar);
setSupportActionBar(toolbar);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
drawerLayout = findViewById(R.id.drawerlayout);
toggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.nav_opened, R.string.nav_closed);
drawerLayout.addDrawerListener(toggle);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
displayView(R.id.nav_home);
}
#Override
protected void onPostCreate(#Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
toggle.syncState();
}
#Override
public void onConfigurationChanged(#NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
toggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if(toggle.onOptionsItemSelected(item))
return true;
return super.onOptionsItemSelected(item);
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
displayView(item.getItemId());
return true;
}
#Override
public void onBackPressed() {
if(drawerLayout.isDrawerOpen(GravityCompat.START))
drawerLayout.closeDrawer(GravityCompat.START);
else
super.onBackPressed();
}
public void displayView(int viewId) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (viewId) {
case R.id.nav_home:
//fragment = new HomeFragment();
break;
case R.id.nav_search:
fragment = new SearchFragment();
break;
case R.id.nav_list:
//fragment = new EatenListFragment();
break;
case R.id.nav_graph:
fragment = new SevenDayGraphFragment();
break;
case R.id.nav_settings:
//fragment = new SettingsFragment();
break;
}
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
}
// set the toolbar title
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(title);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawerlayout);
drawer.closeDrawer(GravityCompat.START);
}
}
And here xml file of activity
<?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/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start"
tools:context=".MainActivity">
<include layout="#layout/appbar"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/nav_header"
app:menu="#menu/activity_main_drawer">
</com.google.android.material.navigation.NavigationView>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" android:id="#+id/content_frame"/>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragment_container_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.drawerlayout.widget.DrawerLayout>
For Navigation Drawer
MainActivity.java
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
#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);
// 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)
.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) {
// 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);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
}
In Layout
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">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/Theme.NavigationDrawerApp.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/Theme.NavigationDrawerApp.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"
app:srcCompat="#android:drawable/ic_dialog_email" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
content_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:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_main">
<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:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
nav_header_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="#dimen/nav_header_height"
android:background="#drawable/side_nav_bar"
android:gravity="bottom"
android:orientation="vertical"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
android:theme="#style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/nav_header_desc"
android:paddingTop="#dimen/nav_header_vertical_spacing"
app:srcCompat="#mipmap/ic_launcher_round" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/nav_header_vertical_spacing"
android:text="#string/nav_header_title"
android:textAppearance="#style/TextAppearance.AppCompat.Body1" />
</LinearLayout>
In Menu
activity_main_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#drawable/ic_menu_camera"
android:title="#string/menu_home" />
<item
android:id="#+id/nav_gallery"
android:icon="#drawable/ic_menu_gallery"
android:title="#string/menu_gallery" />
<item
android:id="#+id/nav_slideshow"
android:icon="#drawable/ic_menu_slideshow"
android:title="#string/menu_slideshow" />
</group>
</menu>
Solved it by meyself. Inside activity_main.xml file I put NavigationView block under FrameLayout and FragmentContainerView blocks. On the web most of people says that put it under LinearLayout but since I don't have a linearlayout inside xml, I thought it wouldn't make sense for me.
Iam Implementing navigation drawer in my application but its menu not working on click. I dont know whats wrong but on click event is not doing anything or toasting a message.Click anything from drawer menu dont do anything.Firstly other button were also not working but adding them in a seprate layout solved the issue.but drawer menu are still not working
Here is my xml :
<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:fitsSystemWindows="true">
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/drawer_menu" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="#layout/app_bar_main" />
</LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>
Here in java Iam using it :
public class AuthorMainScreen extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
DrawerLayout drawerLayout;
NavigationView navigationView;
private ActionBarDrawerToggle actionBarDrawerToggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_author_navigation);
viewDeclaration();
drawerLayout.addDrawerListener(actionBarDrawerToggle);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (actionBarDrawerToggle.onOptionsItemSelected(item))
return true;
return super.onOptionsItemSelected(item);
}
private void viewDeclaration() {
newSurveyBtn = findViewById(R.id.new_surveys_button);
surveyWithRef = findViewById(R.id.get_survey_button);
surveyResult = findViewById(R.id.analyze_survey);
drawerLayout = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.navigation_view);
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.menu_share:
System.out.println("ss" + "coming");
Toast.makeText(getApplicationContext(), "Share", Toast.LENGTH_SHORT).show();
break;
case R.id.menu_survey_count:
Toast.makeText(getApplicationContext(), "Surveys", Toast.LENGTH_SHORT).show();
break;
case R.id.menu_logout:
Toast.makeText(getApplicationContext(), "logout", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
Solution for this is in the XML file bring navigation view below the include tag and it will work
Change this
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/drawer_menu" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="#layout/app_bar_main" />
</LinearLayout>
To this
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="#layout/app_bar_main" />
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/drawer_menu" />
You don't initialize actionBarDrawerToggle. You have to do it.
When you are using AndroidX try to use the methods related to it.
Add the host fragment when you want to implement the fragments in that particular activity:
xml:
<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:fitsSystemWindows="true">
<fragment
android:id="#+id/host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/navigation_graph"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="0dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="#layout/app_bar_main" />
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/drawer_menu" />
Now use the navigation graph where you need to implement the fragments you are about to use in the activity :
navigation_graph.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/navigation_graph"
app:startDestination="#id/profile">
<fragment
android:id="#+id/profile"
android:name="com.example.jetpacknavigationexample.Fragments.ProfileFragment"
android:label="#string/profile"
tools:layout="#layout/fragment_profile" />
<fragment
android:id="#+id/features"
android:name="com.example.jetpacknavigationexample.Fragments.FeaturesFragment"
android:label="#string/features"
tools:layout="#layout/fragment_features" />
<fragment
android:id="#+id/signout"
android:name="com.example.jetpacknavigationexample.Fragments.ProfileFragment"
android:label="#string/signout"
tools:layout="#layout/fragment_signout" />
</navigation>
In your java class add the implement the Navigation component code :
public class AuthorMainScreen extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
DrawerLayout drawerLayout;
NavigationView navigationView;
private ActionBarDrawerToggle actionBarDrawerToggle;
//Add this
NavController mNavController;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_author_navigation);
//add this
mNavController = Navigation.findNavController(this,R.id.host_fragment);
NavigationUI.setupActionBarWithNavController(this, mNavController, drawerLayout);
NavigationUI.setupWithNavController(navigationView,mNavController);
mNavigationView.setNavigationItemSelectedListener(this);
viewDeclaration();
drawerLayout.addDrawerListener(actionBarDrawerToggle);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (actionBarDrawerToggle.onOptionsItemSelected(item))
return true;
return super.onOptionsItemSelected(item);
}
private void viewDeclaration() {
newSurveyBtn = findViewById(R.id.new_surveys_button);
surveyWithRef = findViewById(R.id.get_survey_button);
surveyResult = findViewById(R.id.analyze_survey);
drawerLayout = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.navigation_view);
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.menu_share:
System.out.println("ss" + "coming");
Toast.makeText(getApplicationContext(), "Share",
Toast.LENGTH_SHORT).show();
break;
case R.id.menu_survey_count:
Toast.makeText(getApplicationContext(), "Surveys",
Toast.LENGTH_SHORT).show();
break;
case R.id.menu_logout:
Toast.makeText(getApplicationContext(), "logout",
Toast.LENGTH_SHORT).show();
break;
}
return true;
}
You can test your app now. let me know after you implement this.
I'm trying to use navigation drawer and bottom bar nav in my app.therefore i have created navigation activity first.then i tried to add bottom bar nav to that same activity. I want to develop like this app:
without BottomNavigationView in Activity.xml,app is working.but when i add BottomNavigationView inside Activity.xml app crashed.nothing showing in logcat.
how can i use both bottombar nav and navigation drawer in same activity,please give me an simple example? thx
I am using Navigation Architecture Component following version:
def nav_version = "2.0.0"
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
And below is a simple code to use BottomNavigation and Navigation Drawer
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private static final String TAG = "debinf MainActivity";
//public static final String FRAGMENT_KEY = "fragment";
private BottomNavigationView bottomNavigationView;
private NavigationView navigationView;
private DrawerLayout drawerLayout;
private NavController navController;
private AppBarConfiguration appBarConfiguration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "onCreate: ");
bottomNavigationView = (BottomNavigationView) findViewById(R.id.main_bottomnav);
navigationView = (NavigationView) findViewById(R.id.main_sidebar);
drawerLayout = (DrawerLayout) findViewById(R.id.main_drawer);
setupNavigation();
}
private void setupNavigation() {
Log.i(TAG, "setupNavigation: ");
navController = Navigation.findNavController(this, R.id.main_fragment);
appBarConfiguration =
new AppBarConfiguration.Builder(navController.getGraph()) //Pass the ids of fragments from nav_graph which you dont want to show back button in toolbar
.setDrawerLayout(drawerLayout)
.build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); //Setup toolbar with back button and drawer icon according to appBarConfiguration
NavigationUI.setupWithNavController(navigationView, navController);
NavigationUI.setupWithNavController(bottomNavigationView, navController);
/*
** Listener for bottomNavigation must be called after been setupWithNavController
** This command will override NavigationUI.setupWithNavController(bottomNavigationView, navController)
** and the automatic transaction between fragments is lost
* */
//bottomNavigationView.setOnNavigationItemSelectedListener(this);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
Log.i(TAG, "onBackPressed: ");
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
Log.i(TAG, "onBackPressed: DRAWER IS OPEN - CLOSING IT");
drawerLayout.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onSupportNavigateUp() {
Log.i(TAG, "onSupportNavigateUp: ");
// replace navigation up button with nav drawer button when on start destination
return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp();
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
Log.i(TAG, "onNavigationItemSelected: SIDE BAR");
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START);
}
// https://stackoverflow.com/questions/55990820/how-to-use-navigation-drawer-and-bottom-navigation-simultaneously-navigation-a
// https://stackoverflow.com/questions/58345696/how-to-use-android-navigation-component-bottomnavigationview-navigationview
// https://stackoverflow.com/questions/55667686/how-to-coordinate-a-navigation-drawer-with-a-buttom-navigation-view
// https://ux.stackexchange.com/questions/125627/is-it-okay-to-use-both-nav-drawer-and-bottom-nav-in-home-screen-of-an-android-ap?newreg=da5d1cea03db496982a00b256647728d
if (menuItem.getItemId() == R.id.main_menusidehome) {
Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
startActivity(intent);
Log.i(TAG, "onNavigationItemSelected: conta");
}
if (menuItem.getItemId() == R.id.main_menusideshop) {
Log.i(TAG, "onNavigationItemSelected: compra");
}
if (menuItem.getItemId() == R.id.main_menusidesearch) {
Log.i(TAG, "onNavigationItemSelected: estatistica");
}
return true;
}
}
And below is acitivity_main.xml :
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/main_drawer"
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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/main_fragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:name="androidx.navigation.fragment.NavHostFragment"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/main_bottomnav"
app:defaultNavHost="true"
app:navGraph="#navigation/mainnav_graph"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/main_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/main_navmenu"
android:background="#color/colorAccent"
app:itemIconTint="#drawable/botton_item_color"
app:itemTextColor="#drawable/botton_item_color">
</com.google.android.material.bottomnavigation.BottomNavigationView>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/main_sidebar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/main_sidebarmenu"/>
</androidx.drawerlayout.widget.DrawerLayout>
I hope it helps!
If you using includes. Just wrap app bar include with bottom navigation in some layout. For example I'm using ConstraintLayout for most of time.
content_main
<?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:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_main">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/view_pager_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
app_bar_main
<?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">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/app_bar_layout_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/gradient_main"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/material_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:titleTextColor="#color/white" />
</com.google.android.material.appbar.AppBarLayout>
<include
android:id="#+id/content_main_include"
layout="#layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
activity_main
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.android.tool.ui.activty.main.MainActivity"
tools:openDrawer="start">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/app_bar_include"
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:menu="#menu/menu_main" />
</androidx.constraintlayout.widget.ConstraintLayout>
<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"
app:headerLayout="#layout/nav_header_example"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
That's all.
Add a parent to <include ..../> then add BottomNavigationView
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/colorPrimary"
app:itemTextColor="#color/colorAccent"
app:menu="#menu/bottom_navigation_menu"/>
</RelativeLayout>
Use TabLayout instead of bottom navigation
TabLayout is better and easier
create root.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="#+id/drawerlayout"
android:layout_height="match_parent">
<include layout="#layout/activity_main"/>
<include layout="#layout/navi_drawer"/>
</android.support.v4.widget.DrawerLayout>
create navi_drawer
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:background="?attr/navigationBackground"
android:orientation="vertical">
</LinearLayout>
and activity_main.xml
<LinearLayout 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"
android:background="?attr/backgroundActivity"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</android.support.v4.view.ViewPager>
<LinearLayout
android:id="#+id/lnrTab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutDirection="rtl"
android:orientation="vertical"
app:layout_anchor="#+id/viewpager"
app:layout_anchorGravity="bottom|center">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/dividers_color_dark"
app:layout_anchor="#+id/viewpager"
app:layout_anchorGravity="bottom|center" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
app:tabBackground="?attr/backgroundTab"
app:tabContentStart="9dp"
app:tabGravity="fill"
app:tabIndicatorColor="#color/colorAccent"
app:tabIndicatorHeight="1dp"
app:tabMode="scrollable" />
</LinearLayout>
</LinearLayout>
then MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.root);
//config your TabLayout
}
I am using android default navigation drawer and i want that same layout for all the activities i tried searching on internet i got some ideas for customized drawer but not on android studio default drawer. Kindly help me.
navigation drawer.class :
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton)
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();
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView)
findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
app_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.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" />
<android.support.design.widget.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" />
</android.support.v4.widget.DrawerLayout>
app_bar_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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="com.spykid.navig.navig_sample.Main2Activity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.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" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
<android.support.design.widget.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="#android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
Here in app_bar_main layout i would like to change that
include layout="#layout/content_main" with my activity or fragment so that i can have the same layout.
Thanks in advance.
Create an Activity containing only NavigationDrawer and after that OnItemSelected from NavigationDrawer call every activity you want. Then NavigationDrawer will be available in all the activities.
The other solution is create MainActivity with NavigationDrawer and create other Fragments instead of Activities. Call those Fragmnets OnItemSelected from NavigationDrawer. There are alot of example available there.
Edit
In your activity where you have defined navigationDrawer, do the following. And instead of creating new activities for next layouts, create fragments and call them on OnItemSelected on navigationDrawer like below:
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Checking if the item is in checked state or not, if not make it in checked state
if (menuItem.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
//Closing drawer on item click
drawerLayout.closeDrawers();
//Check to see which item was being clicked and perform appropriate action
switch (menuItem.getItemId()) {
//Replacing the main content with ContentFragment Which is our Inbox View;
case R.id.drawer_home:
Intent intent=new Intent(HomeActivity.this, HomeActivity.class);
startActivity(intent);
overridePendingTransition(0, 0);
finish();
return true;
// For rest of the options we just show a toast on click
case R.id.drawer_artist:
android.support.v4.app.FragmentManager fragmentManager=getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, new ArtistsFragment());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
return true;
default:
Toast.makeText(getApplicationContext(), "Somethings Wrong", Toast.LENGTH_SHORT).show();
return true;
}
}
});
Fragment code will be like:
public class ArtistsFragment extends Fragment {
public ArtistsFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootview= inflater.inflate(R.layout.fragment_artists, container, false);
return rootview;
}}
activity_main.xml:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:elevation="4dp"
android:layout_height="fill_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include
android:id="#+id/tool_bar"
layout="#layout/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
/>
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/home">
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
</LinearLayout>
</FrameLayout>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
android:background="#drawable/bg_all"
app:itemIconTint="#android:color/white"
app:itemTextColor="#android:color/white"
app:theme="#style/list_item_appearance"
app:menu="#menu/drawer_menu" >
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>