I am looking to hide the "Profile" MenuItem from the apps navigation bar when the user is not loggedIn. When the user finally does log in i want to do two things:
Hide the "Login" button
Show the "Profile" button
This should be straightforward, although I'm not sure on how I can access these Menu Item's in which I wish to close and when I try to, I keep getting NullPointerExceptions.
I cant just select elements by id normally like I have tried MenuItem profileBtn= view.findViewById(R.id.nav_profile);
profileBtn.setVisible(true); as it throws a NullPointerException:
java.lang.NullPointerException: Attempt to invoke interface method 'android.view.MenuItem android.view.MenuItem.setVisible(boolean)' on a null object reference
Here is the loginScreen.java fragment from where I look to show the profile button and hide the login button in the "onClick" method at the bottom.
public class loginScreen extends Fragment implements View.OnClickListener{
private loginScreenText loginScreenText;
EditText email;
EditText password;
NavigationView navigationView;
Button button;
SimpleAccountManager accountManager;
Context mContext;
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
mContext = getActivity().getApplicationContext();
accountManager = new SimpleAccountManager(mContext);
button = (Button) inflater.inflate(R.layout.login_page, container, false).findViewById(R.id.loginBtn);
loginScreenText =
ViewModelProviders.of(this).get(loginScreenText.class);
View root = inflater.inflate(R.layout.login_page, container, false);
final TextView textView = root.findViewById(R.id.text_share);
button = root.findViewById(R.id.loginBtn);
email = root.findViewById(R.id.email);
navigationView = root.findViewById(R.id.nav_view);
password = root.findViewById(R.id.password);
button.setOnClickListener(this);
return root;
}
public void onClick(View view){
if(view == button){
User user;
if(accountManager.getUserByEmail(email.getText().toString()) != null){
user = accountManager.getUserByEmail(email.getText().toString());
/* Attempt to reference the profile button which results in NullPointerException as shown
above*/
MenuItem profileBtn= view.findViewById(R.id.nav_profile);
profileBtn.setVisible(true);
Fragment profile = new profileScreen(mContext);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(((ViewGroup)(getView().getParent())).getId(), profile);
fragmentTransaction.commit();
//kill current fragment
getFragmentManager().beginTransaction()
.remove(loginScreen.this).commit();
accountManager.login(user, password.getText().toString());
} else{
loginScreenText.setmText("No user found with email: " + email.getText().toString());
}
}
}
}
Here are the Menu Items in activity_main_drawer.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view"
android:id="#+id/navMenu">
<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_profile"
android:icon="#drawable/ic_menu_gallery"
android:title="Profile"
android:visible="false"/>
<item
android:id="#+id/nav_polls"
android:icon="#drawable/ic_menu_slideshow"
android:title="View Polls" />
<item
android:id="#+id/nav_patients"
android:icon="#drawable/ic_menu_manage"
android:title="View Patients" />
</group>
<item android:title="Log In!">
<menu>
<item
android:id="#+id/nav_login"
android:icon="#drawable/ic_menu_share"
android:title="Login" />
<item
android:id="#+id/nav_login_sp"
android:icon="#drawable/ic_menu_share"
android:title="Login as SP" />
</menu>
</item>
</menu>
Thanks in advance to anyone with advice on how to tackle this problem!
Instead of getting the menu item directly with findViewById you need to get the navigation view first, then get its menu and then get the item from there.
In other words:
NavigationView navigationView = findViewById(R.id.navigation_view); //use the proper id
Menu menu = navigationView.getMenu();
MenuItem menuItem = menu.findItem(R.id.nav_profile);
Related
This is the code of onNavigationItemSelcted
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Menu eventMenu = mNavigationView.getMenu();
eventMenu.add(R.id.events,Menu.NONE,1,"newEvent").setIcon(R.drawable.hangouts_white);
// extra code
}
However, I can perfectly use this add method in onCreate() and onResume(). But, again, if I use this method in onClick() in onCreate() or onResume(), it does not work. As long as it is in their main body, it will work.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNavigationView = findViewById(R.id.navigation_view);
drawerAndToggle();//For drawerlayout setup
Menu eventMenu = mNavigationView.getMenu();
MenuItem eventItem = eventMenu.findItem(R.id.add_custom_event);
eventItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
// This gets executed but does not do anything
eventMenu.add(R.id.events,Menu.NONE,1,"New item");
return true;
}
});
// This one works fine
eventMenu.add(R.id.events,Menu.NONE,1,"New item");
}
But I need to add an item if the user selects "Add Item" which is one of the menu items in the Navigation Drawer. What am I missing or what should I be adding?
Here is my nav_menu XML of my navigation view
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="#+id/events">
<item
android:orderInCategory="1"
android:id="#+id/item1"
android:title="Item 1" />
<item
android:orderInCategory="1"
android:id="#+id/item2"
android:title="Item 2" />
</group>
<group android:id="#+id/settings">
<item
android:orderInCategory="2"
android:id="#+id/add_item"
android:title="Add Item"/>
</group>
</menu>
I have a navigationview with 2 groups, in one of the groups I add a new item programmatically using this example:
How to add an item to a menu group in NavigationView
How to create and get the id for the newly added item and set OnClickListener on him? (because I want to send some to to a database and get).
I want to create this behaviour:
the behaviour I want to create
<menu 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"
tools:showIn="navigation_view">
<group
android:id="#+id/group1"
android:checkableBehavior="single">
<item
android:id="#+id/nav_today"
android:icon="#drawable/ic_today"
android:orderInCategory="0"
android:title="#string/today" />
<item
android:id="#+id/nav_inbox"
android:icon="#drawable/ic_inbox"
android:orderInCategory="0"
android:title="#string/inbox_text" />
</group>
<group
android:id="#+id/group2"
android:checkableBehavior="none">
<item
android:id="#+id/nav_add_list"
android:icon="#drawable/ic_add"
android:orderInCategory="1"
android:title="#string/add_list_text" />
<item
android:id="#+id/nav_random_task"
android:icon="#drawable/ic_random_task"
android:orderInCategory="1"
android:title="#string/random_task" />
<item
android:id="#+id/nav_account"
android:icon="#drawable/ic_account"
android:orderInCategory="1"
android:title="#string/account" />
</group>
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.BlueTheme);
setContentView(R.layout.activity_home_drawer);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TaskBottomSheet taskBottomSheet = new TaskBottomSheet();
taskBottomSheet.showNow(getSupportFragmentManager(), "taskBottomSheet");
}
});
drawer = 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 = findViewById(R.id.nav_view);
if (!TextUtils.isEmpty(listName)) {
addList(listName);
}
private void addList(String listName) {
Menu menu = navigationView.getMenu();
menu.add(R.id.group1, Menu.NONE, 0, listName).setIcon(R.drawable.ic_list);
}
I tried like this:
navigationView = findViewById(R.id.nav_view);
Menu menu = navigationView.getMenu();
final MenuItem menuItem = menu.add(R.id.group1, Menu.NONE, 0,"Read").setIcon(R.drawable.ic_list);
menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(HomeDrawerActivity.this, "Item clicked", Toast.LENGTH_SHORT).show();
menuItem.setCheckable(true);
if (drawer.isDrawerOpen(GravityCompat.START)){
drawer.closeDrawer(GravityCompat.START);
}
return true;
}
});
Another problem is the addList method. The newly menu added is not showed.Only when I add the menu directly after navigationView = findViewById the the item is showing.How to add multiple items and setOnClickListeners for them?
Okay, so I have a dynamic menu (In my navigation drawer), generated like so:
In my Main.java onCreate():
DatabaseManager databaseAccess = DatabaseManager.getInstance(this);
databaseAccess.open();
List<String> folders = databaseAccess.getFolders();
databaseAccess.close();
// Set up the menu items
setupMenu(folders);
This gets the headings into an array called 'folders', then runs the setupMenu function:
private void setupMenu(List<String> folders) {
// Sets up the menu
Log.i("Folder Size",String.valueOf(folders.size()));
NavigationView navView = findViewById(R.id.nav_view);
Menu menu = navView.getMenu();
int x = 0;
while(x < folders.size()) {
menu.add(R.id.myfolders,Menu.NONE,Menu.NONE,folders.get(x++));
}
navView.invalidate();
}
Which adds it to the id:myfolders in activity_main_drawer:
<?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">
<item android:title="My Folders"
android:orderInCategory="1"
android:id="#+id/myfolders">
<menu></menu>
</item>
<item android:checkableBehavior="single" android:orderInCategory="2">
<menu android:id="#+id/about_menu">
<item android:id="#+id/system_about"
android:title="About"
android:icon="#drawable/ic_info" />
</menu>
</item>
</menu>
This all works perfectly, however I want to add longpress functionality to my menu items. I have no idea how to go about doing this, can anyone help?
You get a MenuItem from menu.add() then you can call:
menuItem.getActionView().setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
return false; // true
}
});
But not before you set action view: menuItem.setActionView(new ImageButton(this)).
I have problem with item drawer. I want to get view of item drawer, but it's return null.
this is my menu :
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="none">
<item
android:id="#+id/nav_biodata"
android:icon="#drawable/ic_menu_camera"
android:title="Biodata" />
<item
android:id="#+id/nav_kantor_dinas"
android:icon="#drawable/ic_menu_gallery"
android:title="Kantor Dinas" />
<item
android:id="#+id/nav_aktivitas"
android:icon="#drawable/ic_menu_manage"
android:title="Aktivitas" />
<item
android:id="#+id/nav_logout"
android:icon="#drawable/ic_menu_share"
android:title="Logout" />
</group>
</menu>
and this is try getview :
navigationView = (NavigationView) findViewById(R.id.nav_view);
Menu item = navigationView.getMenu();
MenuItem biodata = item.getItem(0);
v_biodata = biodata.getActionView();
v_biodata is null. So how to fix it ? thanks... sorri for my English.
You can get the views of navigation drawer items using this snippet.
NavigationView navigationView = (NavigationView) mDrawerLayout.findViewById(R.id.navigation_view);
View view = navigationView.getTouchables().get(3); //Pass index to get function to get your desired item view.
I'm trying to use the NavigationView in one of my projects to implement a side menu. The app has two type of users: Admin and User.
I created the login activity and I log in as user or admin. I pass the name, email via intent (putExtra) to my NavigationActivity.
Since I have two type of users I created two type of menus (admin has more menu options).
I check the content of the passed value from the intent and inflate the navigation views menu accordingly.
My problem is I don't know how to separate in the listener the two type of menus. Should I create in my if else two listeners for each case? What would be the right approach? The way I did it doesn't work correctly, in my side menu I have the first two items from the user menu and after that the reamining items of the admin menu.
Here's thecode:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);
Bundle extras = getIntent().getExtras();
String name = extras.getString("name");
String email = extras.getString("email");
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
navigationView = (NavigationView) findViewById(R.id.navigation_view);
if(name.equals("admin")){
// listener for admin here?
navigationView.inflateMenu(R.menu.admin_drawer);
}else{
// listener for user here?
navigationView.inflateMenu(R.menu.user_drawer);
}
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// questionable part here, doesn't work correctly
#Override
public boolean onNavigationItemSelected(MenuItem item) {
if(item.isChecked())
item.setChecked(false);
drawerLayout.closeDrawers();
switch (item.getItemId()){
// this is for user
case R.id.test:
Toast.makeText(getApplicationContext(), "Test Selected", Toast.LENGTH_SHORT).show();
TestFragment testFragment = new TestFragment();
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frameholder, testFragment);
fragmentTransaction.commit();
return true;
// this is for user
case R.id.practice:
Toast.makeText(getApplicationContext(),"Practice Selected",Toast.LENGTH_SHORT).show();
break;
// this is for admin
case R.id.existing_questions:
Toast.makeText(getApplicationContext(),"Questions Selected",Toast.LENGTH_SHORT).show();
break;
// this is for admin
case R.id.new_questions:
Toast.makeText(getApplicationContext(),"New questions Selected",Toast.LENGTH_SHORT).show();
break;
// this is for admin
case R.id.settings:
Toast.makeText(getApplicationContext(),"Settings Selected",Toast.LENGTH_SHORT).show();
break;
// this is for admin
case R.id.users_data:
Toast.makeText(getApplicationContext(),"User data Selected",Toast.LENGTH_SHORT).show();
break;
}
return true;
}
});
Edit:
Here you have the two menus I use:
admin_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/existing_questions"
android:checked="false"
android:icon="#drawable/ic_existq"
android:title="Questions" />
<item
android:id="#+id/new_questions"
android:checked="false"
android:icon="#drawable/ic_addq"
android:title="Add question" />
<item
android:id="#+id/settings"
android:checked="false"
android:icon="#drawable/ic_settings"
android:title="Settings" />
<item
android:id="#+id/users_data"
android:checked="false"
android:icon="#drawable/ic_statistics"
android:title="Statistics" />
</group>
</menu>
user_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/test"
android:checked="false"
android:icon="#drawable/ic_test"
android:title="Test" />
<item
android:id="#+id/practice"
android:checked="false"
android:icon="#drawable/ic_practice"
android:title="Practice" />
</group>
</menu>
A good approach would be to use two groups with different IDs in the same menu. Then you can switch between them easly with .setGroupVisible() like this:
if(name.equals("admin")){
navigationView.menu.setGroupVisible(R.id.menu_group_admin, true);
navigationView.menu.setGroupVisible(R.id.menu_group_user, false);
}
else{
navigationView.menu.setGroupVisible(R.id.menu_group_admin, false);
navigationView.menu.setGroupVisible(R.id.menu_group_user, true);
}
This works seamlessly
Thanks cylon. The mistake was made by me. I inflated the navigation view in the xml, and then from code to.