Adding long press to dynamically generated menu items - android

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)).

Related

NavigationView menu's .add not working except in main bodies of onCreate() and onResume()

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>

Add right margin to the options menu sub-items

Currently, my options menu is aligned to the end of the screen. I want to give it a margin, something like android:layout_marginEnd = "20dp". How can I achieve this?
My options menu:
<?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=".MainActivity">
<item
android:id="#+id/menu_items"
android:icon="#drawable/menu_icon"
app:showAsAction="always">
<menu>
<group android:id="#+id/item1">
<item
android:id="#+id/download"
android:icon="#drawable/download_icon"
android:title="Download"></item>
</group>
<group android:id="#+id/item2">
<item
android:id="#+id/invite"
android:icon="#drawable/invite_icon"
android:title="Invite"></item>
</group>
</menu>
</item>
</menu>
My Custom Toolbar:
<androidx.appcompat.widget.Toolbar
android:id="#+id/menu_toolbar"
app:popupTheme="#style/ThemeOverlay.MyTheme"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_below="#id/greetText"> <!--assume it comes somewhere in the centre due to this-->
</androidx.appcompat.widget.Toolbar>
My Theme for menu items:
<style name="ThemeOverlay.MyTheme" parent="ThemeOverlay.AppCompat.Light">
<item name="android:textColor">#color/dimGray</item>
<item name="android:textSize">14sp</item>
<item name="android:layout_marginEnd">20dp</item> <!-- doesn't work-->
<item name="android:fontFamily">#font/quicksand_medium</item>
<item name="android:background">#drawable/options_menu_background</item>
</style>
Here is the image of my problem. It shows how the end of the menu and the screen are aligned. I want space/margin between these two.
This is an interesting problem. I tried with many things found on the internet, but nothing works. I tried setting the actionOverflowMenuStyle with dropDownHorizontalOffset attribute which does not work either. Finally, I ended up getting a PopupMenu which works just fine. Here is the implementation.
Get your initial menu shorter with a single item which will open up the popup menu as a submenu.
<?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_items"
android:icon="#drawable/ic_close_swipe"
android:title="#string/app_name"
app:showAsAction="always" />
</menu>
Then create another menu, in your /res/menu/ folder, named popup_menu.xml like the following.
<?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_items"
android:icon="#drawable/ic_close_swipe"
android:title="#string/app_name"
app:showAsAction="always" />
</menu>
Now in your MainActivity, just add the following functions to handle the click action of the menu button and the popup menu.
public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuItemClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar myToolbar = findViewById(R.id.menu_toolbar);
setSupportActionBar(myToolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_items:
showPopupMenu();
return true;
default:
return false;
}
}
public void showPopupMenu() {
PopupMenu popup = new PopupMenu(this, findViewById(R.id.menu_items));
popup.setOnMenuItemClickListener(this);
popup.inflate(R.menu.popup_menu);
popup.setGravity(Gravity.END);
Object menuHelper;
Class[] argTypes;
try {
Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup");
fMenuHelper.setAccessible(true);
menuHelper = fMenuHelper.get(popup);
argTypes = new Class[]{boolean.class};
menuHelper.getClass().getDeclaredMethod("setForceShowIcon", argTypes).invoke(menuHelper, true);
} catch (Exception e) {
e.printStackTrace();
}
popup.show();
}
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.invite:
Toast.makeText(this, "Invite", Toast.LENGTH_LONG).show();
return true;
case R.id.download:
Toast.makeText(this, "Download", Toast.LENGTH_LONG).show();
return true;
default:
return false;
}
}
}
I put the working code in this Github Branch. You might consider cloning from that branch and run the application to check if that suffices your expectation.
Hope that helps!

How to Add a CheckBox in Toolbar with custom background - android

Hi i'm new in android and here
i want to Have a CheckBox in my Toolbar with a custom background
my use case is : i want to add current post(in my activity) to favorites list by a checkbox in toolbar
and i wanna use a star(on/off) icon.
i tried this but the checkBox is null
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/shwo_menu_download_mp3"
android:title="#string/download_mp3"
app:showAsAction="never"/>
<item android:id="#+id/show_menu_add_to_fav"
android:checked="true"
android:enabled="true"
app:showAsAction="always"
/>
<item android:id="#+id/show_menu_setting"
android:title="#string/show_menu_setting"
app:showAsAction="never" />
and my Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_speech);
initCheckBox();
...
}
CheckBox checkBoxFav;
private void initCheckBox() {
checkBoxFav = (CheckBox) findViewById(R.id.show_menu_add_to_fav);
checkBoxFav.setText("some Text");
}
with toolbar you can do this
setSupportActionBar(toolbar);
View view= getLayoutInflater().inflate(R.layout.view_, null);
Checkbox chbox = view.findViewById(..);
//chbox.do what u want with it
toolbar.addView(logo);
the view layout contains a checkbox and design it as you wish
You have to follow these steps:
1. Create a toolbar and add it to your activity. I'm not going to explain that since there are a ton of tutorials on the matter.
2. Create a menu with a checkbox widget in it:
<?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_star"
android:checkable="true"
app:actionViewClass="android.widget.CheckBox"
app:showAsAction="ifRoom"
android:title="#string/favorite" />
</menu>
Add the set of icons in the drawable folder. One icon for the unchecked state and one icon for the checked state.
Create a resource file and name it whatever you want (In this example the name is star.xml), add it to the drawable folder and insert the following code in it:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_checked="true"
android:drawable="#drawable/star_black"
/>
<item
android:state_selected="true"
android:drawable="#drawable/star_black"
/>
<item
android:state_checked="false"
android:drawable="#drawable/star_border_black"
/>
<item
android:drawable="#drawable/star_border_black"
/>
</selector>
create an onCreateOptionsMenu method in your activity and insert the following code. The icon of the checkbox will change automatically after getting checked or unchecked.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu,menu);
CheckBox checkBox = (CheckBox)menu.findItem(R.id.menu_star).getActionView();
checkBox.setButtonDrawable(R.drawable.star);//set the icon to star.xml
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
//set the action of the checkbox
}
});
return super.onCreateOptionsMenu(menu);
}

Add menu Item in a group dynamically android navigation menu

I have a navigation menu which looks like this -
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/nav_home"
android:icon="#drawable/ic_home"
android:title="Home" />
<item
android:id="#+id/nav_logout"
android:icon="#drawable/ic_logout"
android:title="Logout" />
<item
android:id="#+id/choose_bus"
android:title="Choose a bus">
<menu>
<group
android:id="#+id/group_select_bus"
android:checkableBehavior="single">
<!--<item-->
<!--android:id="#+id/menu_option1"-->
<!--android:title="Bus 1" />-->
<!--<item-->
<!--android:id="#+id/menu_option2"-->
<!--android:title="Bus 2" />-->
</group>
</menu>
</item>
I want to add menu_option1 and menu_option2 dynamically from the activity. I tried this but nothing adding -
#Override
public boolean onNavigationItemSelected(MenuItem item) {
NavigationView navView = (NavigationView) findViewById(R.id.nav_view);
Menu menu = navView.getMenu();
MenuItem item1 = menu.getItem(2);
SubMenu subMenu = item1.getSubMenu();
subMenu.add("Bus 1");
subMenu.add("Bus 2");
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
Try some thing like this
Menu menu = navView.getMenu();
menu.add(R.id.group_select_bus,Menu.NONE,Menu.NONE,Youritem);
Try this:
MenuItem item = mNavigationView.getMenu().getItem(2);
item.getSubMenu().add(R.id.group_select_bus, id, Menu.NONE, "Youritem");
Another approach is to add all items in navigation menu and then change their visibility on specific activity or fragment, like
MenuItem item = mNavigationView.getMenu().getItem(5);
item.setVisible(false);
Seems a little late to answer. There is workaround/hack for this. No need to add list. Just add this little line above your code. It surely works.
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.candidates -> {
binding.navSideView.post {
navSideView.menu.findItem(R.id.candidateManagement).isVisible = !navSideView.menu.findItem(R.id.candidateManagement).isVisible
}
}
}
return true
}
You need to add navigationview.post Runnable before changing visibility. It will update the menu. It works with group too. :)

Android Menu onOptionsItemSelected styling menu items

I'm trying to highlight menu item title when it is selected in action bar and display its corresponding view in a fragment below. Fragment loading is working good but I'm not able to style menu items when they are clicked.
What I would like to have is something like below mentioned methods-
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// item.setSiblingsStyle(R.style.passive_menu_item);
// item.setStyle(R.style.active_menu_item);
}
Is it possible to style menu title in "onOptionsItemSelected" method? Please help !
You could try to use selector definition:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
<item android:state_pressed="true" android:color="#color/blue_light"/> <!-- pressed -->
<item android:state_enabled="false" android:color="#color/grey_cloud"/> <!-- focused -->
<item android:color="#color/black"/> <!-- default -->
</selector>
I've figured using just text is not a good way. So I decide to add icons and use state of items to toggle by maintaining few variables. Here is an implementation:
private current_selected_menu;
private main_menu;
public void updateMenuState(){
if (main_menu==null){
return;
}
int sz = main_menu.size();
for(int i=0;i<sz;i++){
if(main_menu.getItem(i).getItemId()==current_selected_menu){
main_menu.getItem(i).setEnabled(false);
}
else{
main_menu.getItem(i).setEnabled(true);
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.sample_menu, menu);
current_selected_menu = menu.getItem(0).getItemId(); // I'm using first item as enabled by default
main_menu = menu;
int sz = menu.size();
for(int i=0;i<sz;i++){
if(menu.getItem(i).getItemId()==current_selected_menu){
menu.getItem(i).setEnabled(false);
}
else{
menu.getItem(i).setEnabled(true);
}
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item1:
// Do something
current_selected_menu = item.getItemId();
updateMenuState();
return true;
case R.id.item2:
// Do something
current_selected_menu = item.getItemId();
updateMenuState();
return true;
default:
// Do Something
return super.onOptionsItemSelected(item);
}
}
As suggested by Xingchen, One can use selectors to define multiple icons. Below is a sample implementation:
icon_selector.xml file in res/drawable:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/icon_passive" android:state_enabled="false"/>
<item android:drawable="#drawable/icon_active" android:state_enabled="true"/>
</selector>
Note: icon_passive.png and icon_active.png are two image files used as icons.
sample_menu.xml file in res/menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/menu1" android:icon="#drawable/icon_selector" android:title="menu1" android:showAsAction="always|withText" android:visible="true"></item>
<item android:id="#+id/menu2" android:icon="#drawable/icon_selector" android:title="menu2" android:showAsAction="always|withText" android:visible="true"></item>
<item android:id="#+id/menu3" android:icon="#drawable/icon_selector" android:title="menu3" android:showAsAction="always|withText" android:visible="true"></item>
</menu>
I feel there could be better ways than above mentioned. I'll keep this open. Please feel free to suggest better solutions or better practices : )

Categories

Resources