I decided to execute a Firebase Robo Test for my app and noticed that it always crashes after opening an external activity and then returning back to the app. I was able to duplicate the problem by enabling the "Don't keep activities" in the Developer options.
Crash: java.lang.ClassCastException: com.example.problemtesting.Fragments.Fragment_2 cannot be cast to androidx.navigation.fragment.NavHostFragment
It indicates that the problem is caused by this line of code: NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
How to duplicate the problem:
Enable "Don't keep activities"
Open the app and then the app drawer
Select "Fragment 2"
Press on the Share button
Press on the Messages button (or any other external app)
Return to the app (Crash)
The app works fine if "Don't keep activities" is disabled.
MainActivity
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
DrawerLayout drawer;
NavigationView navigationView;
FragmentManager fragmentManager;
AppBarConfiguration mAppBarConfiguration;
NavController navController;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getSupportFragmentManager();
drawer = findViewById(R.id.drawer_layout);
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_fragment_1, R.id.nav_fragment_2)
.setOpenableLayout(drawer)
.build();
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
if (navHostFragment != null)
navController = navHostFragment.getNavController();
else navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(MainActivity.this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
setNavigationViewListener();
}
#Override
public boolean onSupportNavigateUp() {
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
private void setNavigationViewListener() {
navigationView.setNavigationItemSelectedListener(MainActivity.this);
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.nav_fragment_1: {
fragmentManager.beginTransaction()
.replace(R.id.nav_host_fragment, new Fragment_1())
.commitNow();
MainActivity.this.setTitle("Fragment 1");
break;
}
case R.id.nav_fragment_2: {
fragmentManager.beginTransaction()
.replace(R.id.nav_host_fragment, new Fragment_2())
.commitNow();
MainActivity.this.setTitle("Fragment 2");
break;
}
}
drawer.closeDrawers();
return true;
}
}
Fragment 1
public class Fragment_1 extends Fragment{
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
container.removeAllViews();
View root = inflater.inflate(R.layout.fragment_1, container, false);
return root;
}
}
Fragment 2
public class Fragment_2 extends Fragment {
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
container.removeAllViews();
View root = inflater.inflate(R.layout.fragment_2, container, false);
Button share = root.findViewById(R.id.share);
share.setOnClickListener(view -> {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Message");
startActivity(Intent.createChooser(intent, "Title"));
});
return root;
}
}
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"
>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:tag="my_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="#navigation/mobile_navigation"
/>
<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/main_drawer"
/>
</androidx.drawerlayout.widget.DrawerLayout>
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"
app:startDestination="#+id/nav_fragment_1">
<fragment
android:id="#+id/nav_fragment_1"
android:name="com.example.problemtesting.Fragments.Fragment_1"
tools:layout="#layout/fragment_1"
/>
<fragment
android:id="#+id/nav_fragment_2"
android:name="com.example.problemtesting.Fragments.Fragment_2"
tools:layout="#layout/fragment_2"
/>
</navigation>
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_fragment_1"
android:title="Fragment 1" />
<item
android:id="#+id/nav_fragment_2"
android:title="Fragment 2" />
</group>
</menu>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.problemtesting">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name="com.example.problemtesting.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
It's a frustrating problem that I can't figure out. I have tried to remove the NavigationView.OnNavigationItemSelectedListener listener and it works fine, but I need that listener for other controls such as fragment switching animations and drawer layout transitions.
The problem is that your onNavigationItemSelected is doing a FragmentTransaction, replacing the entire NavHostFragment with a Fragment. This is always the wrong way to change fragments when using a NavHostFragment - you should always be navigating to a destination.
However, in your case, you are doing way more work than is actually necessary. Instead, you should:
Remove your OnNavigationItemSelectedListener code entirely. Navigation has already set one up for you when you call NavigationUI.setupWithNavController(navigationView, navController); That includes closing the drawer and using the correct cross fade animation as per the Material design spec.
As per the top app bar guide, you should not be manually setting the title of the acctivity, but instead add an android:label to each destination in your graph and the setupActionBarWithNavController call you've done will do that for you.
Related
I have a problem. I wanted to create a back arrow, but it doesn't show. The title also doesn't show. I created the toolbar with an extra .xml file. So I hope you can help me, guys! Thanks in advance.
These are my files:
Files
This is my standard screen:
Standard screen
This is my settings screen:
setting screen
SettingsActivity.java
public class SettingsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("My title");
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
int id = item.getItemId();
if (id == android.R.id.home)
{
onBackPressed();
return true;
}
else
{
return super.onOptionsItemSelected(item);
}
}
}
activity_settings.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"
tools:context=".SettingsActivity">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello Settings!"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/menu_info"
android:icon="#drawable/ic_info_white_24dp"
android:title="Info"
app:showAsAction="ifRoom"/>
<item android:id="#+id/menu_settings"
android:icon="#drawable/ic_settings_white_24dp"
android:title="Settings"
app:showAsAction="ifRoom"/>
</menu>
style.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
<style name="MyActionButtonOverflow" parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
<item name="android:src">#drawable/ic_settings_white_24dp</item>
<item name="android:contentDescription">"Lala"</item>
</style>
</resources>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".SettingsActivity"
android:parentActivityName=".MainActivity"></activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#color/colorPrimary"
android:elevation="4dp"
app:titleTextColor="#fff">
</androidx.appcompat.widget.Toolbar>
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch(item.getItemId()) {
case R.id.menu_info:
Toast.makeText(this, "Info", Toast.LENGTH_LONG).show();
return true;
case R.id.menu_settings:
setContentView(R.layout.activity_settings);
return true;
}
return super.onOptionsItemSelected(item);
}
}
Hi Change the following in your code
Add this line to setting class setSupportActionBar(toolbar);
I never called the right SettingsActivity.java
So change
setContentView(R.layout.activity_settings);
to
Intent intentAccess = new Intent(getApplicationContext(), SettingsActivity.class);
startActivity(intentAccess);
Toolbar mToolbar = findViewById(R.id.toolbar);
(AppCompatActivity) setSupportActionBar(mToolbar);
(AppCompatActivity) getSupportActionBar().setDisplayHomeAsUpEnabled(true);
(AppCompatActivity) getSupportActionBar().setDisplayShowHomeEnabled(true);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
My question is that I was trying to make a simple app, and I used both navigation bar and bottom navigation in the same activity, but I am having a simple problem, such as When I run the app, I'm in home fragment, but when I drag the navigation bar and click on movies, it goes into movies fragment, and my movies item got checked, but the problem is when I again click on home in bottom navigation menu than in my navigation menu the movies item still become checked. Please tell how should I do that if I click on home in bottom navigation then in my navigation bar my movies item become unchecked.
Hope you will understand my problem
Here is my code:-
MainActivity : -
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private FirebaseAuth mAuth;
private DrawerLayout drawerLayout;
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.nav_home:
selectedFragment = new HomeFragment();
break;
case R.id.nav_search:
selectedFragment = new SearchFragment();
break;
case R.id.nav_features:
selectedFragment = new FeaturesFragment();
break;
case R.id.nav_myMusic:
selectedFragment = new MyMusicFragment();
break;
}
assert selectedFragment != null;
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
selectedFragment).commit();
return true;
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
drawerLayout = findViewById(R.id.Drawyer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
mAuth = FirebaseAuth.getInstance();
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(navListener);
Fragment selections = null;
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new HomeFragment()).commit();
}
}
#Override
protected void onStart() {
super.onStart();
FirebaseUser currentuser;
currentuser = mAuth.getCurrentUser();
if (currentuser == null) {
SendUserToSelectTypeActivity();
}
}
private void SendUserToSelectTypeActivity() {
Intent testintent = new Intent(MainActivity.this, Selecttype.class);
testintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(testintent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_right);
finish();
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_Movies:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MoviesFragment()).commit();
break;
case R.id.nav_log_out:
SendUserToSelectTypeActivity();
mAuth.signOut();
break;
case R.id.nav_live:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container
, new LiveVideosFragment()).commit();
}
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
#Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
}
HomeFragment : -
public class HomeFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_home , container , false);
}
}
navigation menu:-
<?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_Movies"
android:icon="#drawable/ic_movie"
android:title="Movies" />
<item
android:id="#+id/nav_live"
android:icon="#drawable/ic_movie"
android:title="Live Videos" />
</group>
<item android:title="Communicate">
<menu>
<item
android:id="#+id/nav_share"
android:icon="#drawable/ic_share_black_24dp"
android:title="Share" />
<item
android:id="#+id/nav_contact"
android:icon="#drawable/ic_report_black_24dp"
android:title="Report us" />
<item
android:id="#+id/nav_log_out"
android:icon="#drawable/ic_arrow_back_black_24dp"
android:title="Log Out" />
</menu>
</item>
</menu>
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/Drawyer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:fitsSystemWindows="true"
tools:context=".MainClasses.MainActivity"
tools:openDrawer="start">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottom_navigation">
</FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/design_default_color_primary_dark"
app:itemIconTint="#color/White"
app:itemTextColor="#color/White"
app:menu="#menu/bottom_navigation_menu" />
</RelativeLayout>
<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"
app:menu="#menu/naviation_menu_main"
>
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
Please answer me if you found the solution
Make one file in drawable like "bottom_icon_color.xml"
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="#color/red" />
<item android:state_checked="false" android:color="#color/lightgray" />
</selector>
Then apply it to your bottom navigation
app:itemIconTint="#drawable/bottom_icon_color"
app:itemTextColor="#drawable/bottom_icon_color"
According to the problem you had mentioned in the question
you have to first store the previously clicked MenuItem and then make it as unchecked by using setCheckable(false) of MenuItem.
I'm assuming that the rest of all the functions are working, for example, check the item of NavigationView when the bottom navigation item is selected.
In your onNavigationItemSelected store, the clicked MenuItem in one variable say prevMenuItem of type MenuItem.
Now in your BottomNavigationView.OnNavigationItemSelectedListener() make this prevMenuItem as unchecked using this.
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.getMenu().findItem(previousMenuItem.getId()).setCheckable(false);
I am trying to use NavigationView from Android Support Design library in my app. For some reason, OnNavigationItemSelected listener is not being called. Here is my code
Activity Layout
<?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"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/drawer_header"
app:menu="#menu/drawer_menu" />
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.DrawerLayout>
Activity onCreate()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutID());
toolbar = (Toolbar) findViewById(R.id.activity_toolbar);
setSupportActionBar(toolbar);
toolbar.inflateMenu(R.menu.common_menu);
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu_white_24dp);
actionBar.setDisplayHomeAsUpEnabled(true);
}
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(final MenuItem menuItem) {
Snackbar.make(contentLayout, menuItem.getTitle() + " pressed", Snackbar.LENGTH_LONG).show();
menuItem.setChecked(true);
// allow some time after closing the drawer before performing real navigation
// so the user can see what is happening
drawerLayout.closeDrawer(GravityCompat.START);
mDrawerActionHandler.postDelayed(new Runnable() {
#Override
public void run() {
navigate(menuItem.getItemId());
}
}, DRAWER_CLOSE_DELAY_MS);
drawerLayout.closeDrawers();
return true;
}
});
usernameTextView = (TextView) findViewById(R.id.drawer_header_username);
usernameTextView.setText(getAppDContext().getAccount().getUsername());
}
When you make XML layout, you should write down NavigationView after BaseLayout (FrameLayout, LinearLayout, etc..)
<DrawerLayout>
<FrameLayout />
<NavigationView />
</DrawerLayout>
For me this did the trick!
navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.bringToFront();
Your activity main layout should look like this:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/navigationDrawer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/activity_main_content" />
<android.support.design.widget.NavigationView
android:id="#+id/navigationView"
style="#style/NavigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
app:headerLayout="#layout/header"
app:menu="#menu/menu_drawer"/>
</android.support.v4.widget.DrawerLayout>
In this NavigationView I linked header.xml and menu_drawer.xml (from menu folder)
for example menu_drawer.xml :
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav1"
android:checked="true"
android:icon="#drawable/logo"
android:title="Navigation item 1"/>
<item
android:id="#+id/nav2"
android:icon="#drawable/logo"
android:title="Navigation item 2"/>
</group>
</menu>
than your java code:
public class ActivityMain extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpToolbar();
setUpNavDrawer();
}
private void setUpNavDrawer() {
NavigationView view = (NavigationView) findViewById(R.id.navigationView);
mDrawerLayout = (DrawerLayout) findViewById(R.id.navigationDrawer);
view.setNavigationItemSelectedListener(this);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawerOpen, R.string.drawerClose);
mDrawerLayout.addDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();
}
Check if this work for you. In my project works like a charm.
I have created the navigation drawer menu and now i want it to appear in my main activity.
I have the following code in my main activity:
public class MainActivity extends sideMenu {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FrameLayout contentFrameLayout = (FrameLayout) findViewById(R.id.content_frame);
getLayoutInflater().inflate(R.layout.activity_main, contentFrameLayout);
}}
When i run the app it crashes when entering main activity and it tells this:
**Caused by: java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.**
It specifies the error is in two places:
Menu activity -
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Main activity -
super.onCreate(savedInstanceState);
If someone can shed some light here i'd be grateful!
EDIT:
Android manifest:
<?xml version="1.0" encoding="utf-8"?>
<!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".LoginActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:theme="#style/AppTheme.NoActionBar">
</activity>
<activity android:name=".Registo" />
<activity android:name=".ListaEmpresas" />
<activity android:name=".ListaFavoritos" />
<activity android:name=".Candidaturas" />
<activity
android:name=".sideMenu"
android:label="#string/title_activity_side_menu"
android:theme="#style/AppTheme.NoActionBar"></activity>
</application>
menu activity code:
public class sideMenu extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_side_menu);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setSupportActionBar(toolbar);
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.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView)
findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout)
findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is
present.
getMenuInflater().inflate(R.menu.side_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
// Handle the camera action
} else if (id == R.id.nav_gallery) {
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout)
findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
Menu 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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/content_frame"/>
</LinearLayout>
<include
layout="#layout/app_bar_side_menu"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="250dp"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/nav_header_side_menu"
app:menu="#menu/activity_side_menu_drawer" />
app_bar_side_menu 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"
tools:context="amsi.dei.estg.ipleiria.pt.ima.sideMenu">
<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_height="wrap_content"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_side_menu" />
</android.support.design.widget.CoordinatorLayout>
Content_side_menu xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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:context="amsi.dei.estg.ipleiria.pt.ima.sideMenu"
tools:showIn="#layout/app_bar_side_menu">
</android.support.constraint.ConstraintLayout>
nav_header_side_menu:
<?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:backgroundTint="#android:color/holo_red_dark"
android:gravity="bottom"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#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: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="IMA"
android:textAppearance="#style/TextAppearance.AppCompat.Body1" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NOME USER" />
</LinearLayout>
Your theme already has an ActionBar so you will have to convert it to NoActionBar.
For Whole App:
Open the styles.xml and make sure the last line of the parent has a word NoActionBar for example :
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- changed .DarkActionBar to .NoActionBar -->
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
For An Activity:
Or you can just change it for one particular activity in the Manifest like by adding this atrribute in the Manifest :
android:theme="#style/Theme.AppCompat.Light.NoActionBar"
use this theme.
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
I have the following problem:
getActionBar().setDisplayHomeAsUpEnabled(true);
java.lang.NullPointerException
I know that there are many post with the same problem, but this one i can resolve. I tried all solution that I found, but no one help me, I work this Fragment and Drawer (Android)
this is the code : MainActivity.java
package com.example.erik.test2;
import android.app.Activity;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawer;
private Toolbar toolbar;
private ActionBarDrawerToggle mDrawerToggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
//requestWindowFeature(Window.FEATURE_ACTION_BAR);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set a Toolbar to replace the ActionBar.
toolbar = (Toolbar) findViewById(R.id.toolbar);
//setSupportActionBar(toolbar);
// getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Find our drawer view
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
NavigationView nvDrawer = (NavigationView) findViewById(R.id.nvView);
setupDrawerContent(nvDrawer);
//---- Open Drawer on clic icon BUT CAUSE NULLPOINT EXEPTION--- //
//*
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);//*/
/*
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);//*/
//*
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawer, R.drawable.logo_tam, R.string.ouverture, R.string.fermeture) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(R.string.titre);
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(R.string.titre_apres_ouverture);
invalidateOptionsMenu();
}
};
mDrawer.setDrawerListener(mDrawerToggle); //*
//-----------------------------------------------------------------------------------------------------------------
/*
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawer, R.drawable.logo_tam, R.string.ouverture, R.string.fermeture ) {
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
getActionBar().setTitle("Fermer");
}
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getActionBar().setTitle("Ouvert");
}
};
// Set the drawer toggle as the DrawerListener
mDrawer.setDrawerListener(mDrawerToggle);*/
// getActionBar().setDisplayHomeAsUpEnabled(true);
//getActionBar().setHomeButtonEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// The action bar home/up action should open or close the drawer.
switch (item.getItemId()) {
case android.R.id.home:
mDrawer.openDrawer(GravityCompat.START);
return true;
}
return super.onOptionsItemSelected(item);
}
// Make sure this is the method with just `Bundle` as the signature
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
}
private void setupDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
selectDrawerItem(menuItem);
return true;
}
});
}
public void selectDrawerItem(MenuItem menuItem) {
// Create a new fragment and specify the planet to show based on
// position
Fragment fragment = null;
Class fragmentClass;
switch(menuItem.getItemId()) {
case R.id.nav_first_fragment:
fragmentClass = FirstFragment.class;
break;
case R.id.nav_second_fragment:
fragmentClass = SecondFragment.class;
break;
case R.id.nav_third_fragment:
fragmentClass = ThirdFragment.class;
break;
default:
fragmentClass = FirstFragment.class;
}
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();
// Highlight the selected item, update the title, and close the drawer
menuItem.setChecked(true);
setTitle(menuItem.getTitle());
mDrawer.closeDrawers();
}
}
code of styles.xml (I already try to change theme to Theme.AppCompat.Light but it doesn't work)
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
</resources>
code of toolbar.xml
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
app:theme="#style/Theme.AppCompat.Light"
android:background="?attr/colorPrimaryDark">
</android.support.v7.widget.Toolbar>
Code activity_main.xml
<!-- This DrawerLayout has two children at the root -->
<android.support.v4.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">
<!-- This LinearLayout represents the contents of the screen -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- The ActionBar displayed at the top -->
<!-- <include
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" /> -->
<!-- The main content view where fragments are loaded -->
<FrameLayout
android:id="#+id/flContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- The navigation drawer that comes from the left -->
<!-- Note that `android:layout_gravity` needs to be set to 'start' -->
<android.support.design.widget.NavigationView
android:id="#+id/nvView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/white"
app:menu="#menu/drawer_view"
app:headerLayout="#layout/nav_header"
/>
</android.support.v4.widget.DrawerLayout>
and code of manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.erik.test2">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I tried many options with the Theme but it doesn't work in my ActivityMain in the comment you can see all the tests that I tried.
Bad Approach
Use deprecated code . Avoid calling ActionBarActivity .
Advice
Since the version 22.1.0, the class ActionBarActivity is deprecated.
You should use AppCompatActivity.
You are getting
getActionBar().setDisplayHomeAsUpEnabled(true);
java.lang.NullPointerException
Comment out this line At First .
<include
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
2ndly , You can use getSupportActionBar() instead getActionBar() & add null checking
if (getSupportActionBar() != null)
{
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
You can change your theme because you are using NoActionBar
parent="Theme.AppCompat.Light.NoActionBar"
Using the Toolbar to replace an ActionBar is pretty straight forward
and begins with making sure that the activity extends
ActionBarActivity. Also make sure that the theme for this activity is
a child of either Theme.AppCompat.NoActionBar or
Theme.AppCompat.Light.NoActionBar.
Please check #SO Answer What to use instead of getSupportActionBar()
and
https://developer.android.com/intl/pt-br/reference/android/support/v7/widget/Toolbar.html
getActionBar().setDisplayHomeAsUpEnabled(true); is giving NullPointerException because in your styles.xml you have given parent Theme.AppCompat.Light.NoActionBar which means there is no ActionBar.
Solution:
Change your style with the style given below in your styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
Now in your MainAcitivity use this code
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Let me know if this helps you.
you have two ways:
1. use getSupportActionBar() instead getActionBar()
2. change your activity to extend ActionBarActivity
do it in this way
// Set a Toolbar to replace the ActionBar.
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Find our drawer view
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
NavigationView nvDrawer = (NavigationView) findViewById(R.id.nvView);
setupDrawerContent(nvDrawer);
//---- Open Drawer on clic icon BUT CAUSE NULLPOINT EXEPTION--- //
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
also change your layout
<!-- This LinearLayout represents the contents of the screen -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- The ActionBar displayed at the top -->
<include
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- The main content view where fragments are loaded -->
<FrameLayout
android:id="#+id/flContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- The navigation drawer that comes from the left -->
<!-- Note that `android:layout_gravity` needs to be set to 'start' -->
<android.support.design.widget.NavigationView
android:id="#+id/nvView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/white"
app:menu="#menu/drawer_view"
app:headerLayout="#layout/nav_header"
/>
you are not getting action bar, uncomment following code from your xml.
<!-- <include
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" /> -->
Also use default theme currently you are using NoActionBar
You are using AppCompat.So, use this:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
As you are using AppCompactActivity which is in support library. so you need to get ActionBar instance using getSupportActionBar()
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
Since you have given NoActionBar theme. uncomment the toolbar include related you need to add toolbar.Either give Theme with ActionBar not NoActionBar. or Give Toolbar in layout and add it.
<android.support.v4.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">
<!-- This LinearLayout represents the contents of the screen -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- The ActionBar displayed at the top -->
<include
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- The main content view where fragments are loaded -->
<FrameLayout
android:id="#+id/flContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- The navigation drawer that comes from the left -->
<!-- Note that `android:layout_gravity` needs to be set to 'start' -->
<android.support.design.widget.NavigationView
android:id="#+id/nvView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/white"
app:menu="#menu/drawer_view"
app:headerLayout="#layout/nav_header"
/>
</android.support.v4.widget.DrawerLayout>