I have a drawer with actions in a group, file a list of files I want to dynamically put in another group. My main activity has this 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"
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">
<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>
Then the loaded NavigationView is:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/test_id">
<group android:checkableBehavior="single" android:id="#+id/group_file_list">
<item
android:id="#+id/file1"
android:icon="#drawable/ic_menu_gallery"
android:title="File 1"/>
...
</group>
<item android:title="Actions">
<menu>
<item
android:id="#+id/nav_share"
android:icon="#drawable/ic_menu_share"
android:title="Share"/>
<item
android:id="#+id/nav_send"
android:icon="#drawable/ic_menu_send"
android:title="Send"/>
</menu>
</item>
</menu>
When I try to get the group where the files are to later add the Items dynamically, all of these return null:
findViewById(R.id.group_file_list); // returns null
View navView = findViewById(R.id.nav_view); // works
navView.findViewById(R.id.group_file_list); // returns null
navView.findViewById(R.id.test_id); // returns null
And yes, I'm calling this after setContentView(). I also tried inside onStart()
Any ideas?
Use this to add items to your drawer:
NavigationView navView = findViewById(R.id.nav_view);
navView.getMenu().add(...);
Or, to add to a group, do this:
navView.getMenu().addSubMenu(Menu.NONE, Menu.NONE, Menu.NONE, groupName).add(...);
See NavigationView and Menu
Those are menu items and not views. You get them by using the options menu
Menu optionsMenu;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
// store the menu to var when creating options menu
optionsMenu = menu;
}
Then you can find the item you want
MenuItem item = optionsMenu.findItem(R.id.test_id);
Related
The question is clear! I need to add another menu beside of the main menu in toolbar. I have created the status.xml menu file like this:
<?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/online"
android:orderInCategory="10"
android:title="#string/action_settings"
app:showAsAction="never" />
<item
android:id="#+id/busy"
android:orderInCategory="20"
android:title="#string/action_settings"
app:showAsAction="never" />
<item
android:id="#+id/invisible"
android:orderInCategory="30"
android:title="#string/action_settings"
app:showAsAction="never" />
</menu>
and added a clickable TextView to toolbar like this:
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
... />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.Toolbar>
Now I need to add it separately to the toolbar, but in code below:
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
menuInflater.inflate(R.menu.status, menu)
return true
}
It add all of items to main menu. Any help will be appreciated.
If this menus have to be separate that appear depending on some kind of condition you can use onPrepareOptionsMenu.
Check this question and developer guide on menus
Android: Multiple Option Menus in one Activity
https://developer.android.com/guide/topics/ui/menus
I am new in Android applications development, and I am trying to develop an application in UI I added a toolbar but In don't know why the three dots in the right side of the toolbar, it is necessary for me because I want to add a logout button there.
here is the toolbar layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:background="#000">
</android.support.v7.widget.Toolbar>
And here is where i add the toolbar inside the activity class:
toolbar= (Toolbar) findViewById(R.id.app_bar);
setSupportActionBar(toolbar);
toolbar.setTitle(R.string.app_name);
toolbar.setTitleTextColor(getResources().getColor(R.color.com_facebook_button_background_color_focused));
and this is my 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"
xmlns:tools="http://schemas.android.com/tools" tools:context=".HomeActivity">
<item android:id="#+id/action_settings"
android:title="Settings"
android:orderInCategory="100"
app:showAsAction="always"
android:icon="#drawable/icon"
/>
<item
android:id="#+id/action_search"
android:title="Search">
</item>
</menu>
And what is weird is that in the android studio preview the three dots are shown:
what I am doing wrong ?
Create Android Resource Directory of type menu in res folder and add xml file named: user_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/logout_menu"
android:orderInCategory="100"
android:title="#string/action_logout"
app:showAsAction="never" />
</menu>
In your Activity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.user_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.logout_menu:
// Do whatever you want to do on logout click.
return true;
default:
return super.onOptionsItemSelected(item);
}
}
The three dots were hidden because they were black, and the toolbar background is black, so I had to add this white theme
android:theme="#style/ThemeOverlay.AppCompat.Dark"
to my toolbar layout.
In onCreateOptionmenu() one file will be inflating automatically. Remove that file and three dots will be removed.
Or
If this function is not included in your activity file then remove the file under res\menu folder.
I want to use android v7.toolbar in my project with fragments. So i did something like below in my main activity xml. Because i dont want to add all fragments xml to android.support.v7.widget.Toolbar
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="#+id/toolBar" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_container">
</FrameLayout>
</LinearLayout>
i am adding fragments with programmatically. And in some fragments i have to change right side of the toolbar. For example in some fragments i have to use just 1 right menu icon and another fragments 2. How can i achieve it?
Also is there a way to change icon resource which is in right side of the toolbar from fragments?
Thanks,
You can create menu.xml and put all your menu items in it. Set all the items visibility to false. This hides everything.
Then in your fragment's onCreate set setHasOptionsMenu(true), this will allow you to override onCreateOptionsMenu(Menu m, MenuInflater inflater).
In this method you can do menu.findItem(id.of.item).setVisible(true/false).
Examples:
menu.xml:
<menu 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"
tools:context="com.sample.app.MainActivity">
<item
android:id="#+id/action_refresh"
android:icon="#drawable/ic_action_refresh"
android:orderInCategory="101"
app:showAsAction="ifRoom"
android:title="#string/action_refresh"
android:visible="false"/>
<item
android:id="#+id/action_edit_account"
android:icon="#drawable/ic_action_edit"
android:orderInCategory="102"
app:showAsAction="never"
android:title="#string/action_edit_account"
android:visible="false"/>
<item
android:id="#+id/action_enable_offline_token"
android:orderInCategory="105"
app:showAsAction="never"
android:title="#string/action_enable_offline_token"
android:visible="false"/>
<item
android:id="#+id/action_disable_offline_token"
android:orderInCategory="105"
app:showAsAction="never"
android:title="#string/action_disable_offline_token"
android:visible="false"/>
<item
android:id="#+id/action_save"
android:icon="#drawable/ic_action_save"
android:orderInCategory="106"
app:showAsAction="ifRoom"
android:title="#string/action_save"
android:visible="false"/>
</menu>
Fragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
super.onCreateOptionsMenu(menu, inflater);
menu.findItem(R.id.action_refresh).setVisible(false);
menu.findItem(R.id.action_save).setVisible(true);
}
To change icons you can just get the menu and do a findItem and setIcon.
Is it possible to take view in menu items of toolbar?
I want view like shown in yellow color between two menu items of toolbar.
Simply create a divider line view in xml file to show a divider line.
dividerLine.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<View
android:layout_width="1dp"
android:layout_height="?android:attr/actionBarSize"
android:background="#android:color/darker_gray"/>
</LinearLayout>
and set actionLayout to an item in menu xml to show divider line
activity_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="#+id/your_icon1"
android:icon="#drawable/image1"
android:title="#string/text1"
app:showAsAction="always"
/>
<item android:id="#+id/icon2TricktoShowDividerLine"
android:actionLayout="#layout/dividerLine"
app:showAsAction="always"
android:title="#string/text2" />
<item android:id="#+id/your_icon3"
android:icon="#drawable/icon"
android:title="#string/text3"
app:showAsAction="always" />
</menu>
android:actionLayout="#layout/dividerLine" shows divider line between menu items. Hope this helps you.
Updated
I am getting this type of view from my above code :
You have to create the custom layout for menuItem uing actionLayout and then in oncreateOptionsMenue get the menuItem view and change your image view icon to vertical drawable
layout_actionitem.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<ImageView
android:id="#+id/actionItemImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="1dp"/>
</LinearLayout>
Your menu xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/item_save"
android:icon="#drawable/exit"
android:showAsAction="always"
android:actionLayout="#layout/layout_actionitem"
android:title=""/>
</menu>
onCreateOptionsMenu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
LinearLayout actionItemLayout = (LinearLayout) menu.findItem(R.id.item_save).getActionView();
ImageView iv = (ImageView)actionItemLayout.findViewById(R.id.actionItemImage);
iv.setBackgroundDrawable(getResources().getDrawable(R.drawable.icon_save));
}
Hope this helps.
I have this Layout:
<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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- The ActionBar -->
<include
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- The main content view -->
<FrameLayout
android:id="#+id/flContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- The navigation drawer -->
<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_menu"
app:headerLayout="#layout/nav_header"/>
So, looking that in NavigationView we have the attribute:
app:menu="#menu/drawer_menu"
And I have this XML id menu folder.
I wanna make dynamic menus, ie, in code I should mount the 'MenuItem' objects and set into NavigationView.
Is this correct?
Is this best pratice?
Is this possible?
Note: My code is working with 'static drawer_menu', I want to improve it.
I'm waiting.
[EDIT]
I make it:
Menu menu = nvDrawer.getMenu();
for (KSMenuItem kmi : menus.values()) {
if (menu.size() == 0) {
menu.add(kmi.getId());
}
if (menu.getItem(kmi.getId()) == null) {
menu.add(kmi.getId());
}
MenuItem mi = menu.getItem(kmi.getId());
mi.setIcon(kmi.getIcon());
mi.setTitle(kmi.getTittle());
}
But this error happened:
06-27 15:26:15.538 15335-15335/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.sticdev30.newdrawer, PID: 15335
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sticdev30.newdrawer/com.example.sticdev30.newdrawer.MainActivity}: android.content.res.Resources$NotFoundException: String resource ID #0x1
KSMenuItem is a POJO with my menu data. In kmi.id I informed incremental integers...
I'm waitning
You can re-inflate NavigationViewat runtime with 2 lines of code using public method inflateMenu. In this example i re-inflate with new_navigation_drawer_items.xml
navigationView.getMenu().clear(); //clear old inflated items.
navigationView.inflateMenu(R.menu.new_navigation_drawer_items); //inflate new items.
You can add menus dynamically by following steps :
Step1. Obtain menu object from Navigation View NavigationView.getMenu()
Step2. Add any item to the menu using Menu.add()
We can dynamically add/remove menu items.
Suppose we have this menu items `
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#mipmap/home_icon_x48"
android:title="Home" />
<item
android:id="#+id/nav_part_catalouge"
android:icon="#mipmap/catalogue_icon_x48"
android:title="Parts Catalogue" />
<item
android:id="#+id/nav_favourite"
android:icon="#mipmap/my_favourate_x48"
android:title="My-Favourite" />\
<item
android:id="#+id/nav_opencarrequest"
android:icon="#mipmap/cart_request"
android:title="Cart-Request" />
<item
android:id="#+id/nav_setting"
android:icon="#mipmap/settings_x48"
android:title="Settings" />
</group>
<item android:title="">
<menu>
<item
android:id="#+id/nav_logout"
android:icon="#mipmap/logout_icon_x48"
android:title="Logout" />
</menu>
</item>
`
In Activity we can add or remove menuitems based on our condition
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);// your activity layout here
NavigationView navigationView= (NavigationView) findViewById(R.id.nav_view); // navigation view which holds menu items
navigationView.setNavigationItemSelectedListener(this);
if(yourCondition){
navigationView.getMenu().getItem(0).setVisible(false); //if you want to hide first item
navigationView.getMenu().getItem(1).setVisible(true); // if you want to show second menu item should be visible
}
}
Hope it will help.
Seems like kmi.getId() returns int(or long).
But Menu.add(int) adds menu with title from the given string resources, which is usually represented as R.string.something, and not for usual integer values.
Menu.add(CharSequence) does add menu with title of CharSequence, so you need to do some int-to-string conversion like menu.add(kmi.getId() + "");