I have an android app that has a gridview in it. The gridview items contain among other things, a button to show context sensitive menus. So, I implemented a popup menu that comes up when they touch the button in the gridview item.
This menu contains 3 items:
Edit Item
Delete Item
Share Item
I have successfully implemented the edit and delete menu items. The problem is with the "Share Item" menu item. It is a ShareActionProvider. I previously implemented these menu choices as an ActionMode (menu items across the top). But now that the menu is a popup, I'm not sure how to implement the "Share Item" menu option.
Here is my popup_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">
<group android:id="#+id/group_edit_mode">
<item
android:id="#+id/MenuItemEdit"
android:title="#string/item_option_edit"
app:showAsAction="withText|ifRoom" />
<item
android:id="#+id/MenuItemDelete"
android:title="#string/delete"
app:showAsAction="withText|ifRoom" />
<item
android:id="#+id/MenuItemShare"
android:title="#string/share"
app:showAsAction="ifRoom"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>
</group>
</menu>
Here is the popup menu code:
PopupMenu popupMenu = new PopupMenu(MINMainActivity.getSharedInstance(), optionButton);
MenuInflater inflater = popupMenu.getMenuInflater();
inflater.inflate(R.menu.gridview_edit_menu_single_item, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener()
{
#Override
public boolean onMenuItemClick(MenuItem item)
{
boolean choiceHandled = false;
int itemID = item.getItemId();
switch (itemID)
{
case R.id.MenuItemEdit:
MINPageTypeGridFragment.launchAlbumItemDetails(mFragment, albumItem, mPageItem.pageConfigFileName);
mFragment.currentMode = MINPageTypeGridFragment.MODE_STANDARD;
choiceHandled = true;
break;
case R.id.MenuItemDelete:
MINPageTypeGridFragment.deleteItem(mFragment, mAlbum, albumItem);
mFragment.currentMode = MINPageTypeGridFragment.MODE_STANDARD;
choiceHandled = true;
break;
case R.id.MenuItemShare:
choiceHandled = true;
mFragment.currentMode = MINPageTypeGridFragment.MODE_STANDARD;
break;
}
return choiceHandled;
}
});
popupMenu.show();
This was WAY overthought. I just kept it as a button and created a chooser.
public void onShareClick(MINAlbumItem albumItem)
{
List<MINAlbumItem> albumItemsArray = new ArrayList<MINAlbumItem>();
albumItemsArray.add(albumItem);
// Creates intent and loads data from items array
Intent intent = mFragment.Share(albumItemsArray);
MINMainActivity.getSharedInstance().startActivity(Intent.createChooser(intent, MINMainActivity.getSharedInstance().getResources().getString(R.string.send_to)));
}
Related
I am having an issue where i have 2 items in my action bar (one 'refresh' button and one 'Save' Button, but for some reason they do not show, instead they are nested inside an options menu (3 dots). Would anyone know how to remove the 3 dots menu and display my 2 items? I have tried many things but ultimately I just end up removing all three items. Thanks in advance.
Here is my code
add_event_action.xml (this is my menu xml)
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/action_refresh"
android:showAsAction="always"
android:icon="#drawable/ic_action_refresh"
android:title="Refresh"/>
<item
android:id="#+id/action_save"
android:showAsAction="always"
android:title="#string/save"/>
</menu>
Here is my Java class
public class RandomActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_events_list);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.add_event_action, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// action with ID action_refresh was selected
case R.id.action_refresh:
Toast.makeText(this, "Refresh selected", Toast.LENGTH_SHORT)
.show();
break;
// action with ID action_settings was selected
case R.id.action_save:
Toast.makeText(this, "Save selected", Toast.LENGTH_SHORT)
.show();
break;
default:
break;
}
return true;
}
}
If I understood correctly, you need two menu buttons in your toolbar.
This works for me, place it in your menu.xml:
<item
android:id="#+id/done"
android:title="#string/done"
app:showAsAction="always|withText"/>
Try to use app:showAsAction instead of android:showAsAction
To expand on the other answers somewhat:
When your activity extends from AppCompatActivity, your menu items should use app:showAsAction. When your activity does not (that is, when you're not using the AppCompat support libraries), your menu items should use android:showAsAction.
Documentation: http://tools.android.com/tips/lint-checks
AppCompatResource
Summary: Menu namespace
Priority: 5 / 10
Severity: Error
Category: Correctness
When using the appcompat library, menu resources should refer to the
showAsAction in the app: namespace, not the android: namespace.
Similarly, when not using the appcompat library, you should be using the android:showAsAction attribute.
I am in strange situation and I tried to search everywhere but i didn't find anything useful. May be I am following bad design. But here is my situation:
I have AppBar in my app and I have added ActionButton on app bar which we do normally. Now I want to display context menu when user clicks on any of the action button of app bar.
For example: If I have setting button on app bar and if user clicks on that button then I want to display context menu having multiple options.
I know how to create context menu and handle context menu item clicks but i don't know how to transfer control from action button click which lead to display ContextMenu.
Here is my code:
//inflating context menu which will display when user clicks app bar button example like setting
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu_sort, menu);
}
//handling context menu item clicks
#Override
public boolean onContextItemSelected(MenuItem item) {
return super.onContextItemSelected(item);
}
But I am not sure how to handle app bar button clicks which will display context menu:
//Below code is to handle app bar item clicks
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
//handling the menu clicks on menu.xml
switch (id){
//on below action_add click i want to display context menu
case R.id.action_add:
//not sure what to code here
break;
}
Thanks for your help
If i am understanding you right you want to show a submenu?
Then you need to add a menu tag in your R.menu.context_menu_sort.
Like this:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/file"
android:title="#string/file" >
<!-- "file" submenu -->
<menu>
<item android:id="#+id/create_new"
android:title="#string/create_new" />
<item android:id="#+id/open"
android:title="#string/open" />
</menu>
</item>
</menu>
For more informations see https://developer.android.com/guide/topics/ui/menus.html
I originally had a menu that looked like:
Line1
Line2
Line3
The app was published. I then added in another Item, so it now looks like this:
Line1
Line2
Line4 << newly added item
Line3
I updated all my code and it works, but with some added side effects. The original "Line3" was pulling up a app list to share 'something'. Line 4 was added in to open another specific app. What happens now is if I click on Line4, the app opens and all is well until I hit the back button to go back to the original app, I see that the app list for sharing 'Something' opened up as well, meaning I have to click the back button twice.
This is my code (representing the second example above)
/**creates action bar**/
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
/**handles which action item is selected**/
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.stuff:
startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
return true;
case R.id.MoreStuff:
//things
return true;
case R.id.TheProblemStuff:
Intent intent1 = getPackageManager().getLaunchIntentForPackage("anApp");
if (intent1 != null)
{
/* we found the activity now start the activity */
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent1);
}
else
{
/* bring user to the market or let them choose an app? */
intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse("a website .com"));
startActivity(intent);
}
case R.id.TheOtherProblemStuff:
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, "Check out this app!");
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT,("myapp"));
startActivity(Intent.createChooser(sharingIntent,"Share using"));//this is the menu that still comes up when "TheProblemStuff" is clicked. This use to be in the spot that "TheProblemStuff" was
return true;
default:
return super.onOptionsItemSelected(item);
}
}
and here is my xml
<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="com.example.gpstest1.MainActivity" >
<item
android:id="#+id/Stuff"
android:title="#string/action_settings"
android:orderInCategory="1"
app:showAsAction="never"/>
<item
android:id="#+id/MoreStuff"
android:title="#string/action_map"
android:orderInCategory="2"
app:showAsAction="never"/>
<item
android:id="#+id/TheProblemStuff"
android:title="#string/speedometer"
android:orderInCategory="3"
app:showAsAction="never"/>
<item
android:id="#+id/TheOtherProblemStuff"
android:title="#string/action_share_app"
android:orderInCategory="4"
app:showAsAction="never"/>
</menu>
you forgot the return true; line inside the R.id.TheProblemStuff: case, so it continues to the R.id.TheOtherProblemStuff case and only then stops.
I use an xml to for my ContextMenu, which is like :
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/Ordermenu" android:title="Order">
<menu android:id="#+id/OrderBySubMenu">
<item android:id="#+id/OrderByASC" android:title="Order ASC" />
<item android:id="#+id/OrderByDESC" android:title="Order DESC" />
<item android:id="#+id/Cancel" android:title="Cancel" />
</menu>
</item>
<item android:id="#+id/ActionAmenu" android:title="Action A"/>
</menu>
I use following code to display the menu, in my onCreateContextMenu
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.layout.my menu, menu);
I manage option click with following code :
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.Displaymenu:
//do stuff
return true;
case R.id.OrderByASC:
//do stuff
return true;
case R.id.OrderByDESC:
//do stuff
return true;
default :
return(super.onOptionsItemSelected(item));
}
Starting the Context Menu it display Two options:
Order
Action A
Clicking on Order show a submenu :
Order ASC
Order DESC
Cancel
Now, If the user click on cancel (or click on the hardware back button), no action is specified, so it call super.onOptionsItemSelected(item) which go back to my main activity.
How can I manage to go back to the main menu in such case? i.e. diplay the initial :
Order
Action A
I tried this long ago but i think you will have to override onPrepareOptionsMenu as well to get this to work. This is called before it shows, and you will have to put flags here on what items to show for the user.
Try something like this:
#Override
public boolean onPrepareOptionsMenu(Menu menu)
{
// Clear the previous layout
menu.clear();
if(showMainMenu)
{
// Add main menu items..
menu.add(0, R.id.ordermenu, 0, "True");
}
else
{
// Add sub-menu items
menu.add(0, R.id.ordermenuASC, 0, "True");
}
return super.onPrepareOptionsMenu(menu);
}
So when user clicks a main menu item, change the boolean flag a redo the process.
Finally, it worked only by adding :
case R.id.Cancel:
openContextMenu(findViewById(selected_view_id));
return true;
in public boolean onContextItemSelected(MenuItem item)
selected_view_id is stored by
selected_view_id=v.getId();
in onCreateContextMenu
Hope it will help others.
(Newbe)
When I click on a menu the above method returns an ID from the first menu, not the one I clicked. If I check for the Title Condensed of the menu it is correct.
int id = item.getItemId(); //returns id of an incorrect menu
String Title = (String) item.getTitleCondensed(); //this returns the correct title.
Any ideas welcome.
I had the same problem. Generated files from the build are not properly updated.
I got the same effect if i reordered the menu items in the xml...build and surprise. Clicking on menu brings other codes than expected.
Do a clean and try again
You should have set each menu item a unique ID in onCreateOptionsMenu and onCreateContextMenu.
For example:
public static final int CONTEXT_MENU_DELETE = Menu.FIRST;
public static final int CONTEXT_MENU_EDIT = CONTEXT_MENU_DELETE + 1;
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
menu.add(0, CONTEXT_MENU_DELETE, 1, R.string.delete);
menu.add(0, CONTEXT_MENU_EDIT, 2, R.string.edit);
}
// And then
#Override
public boolean onContextItemSelected(MenuItem item) {
switch(item.getItemId()) {
case CONTEXT_MENU_DELETE:
// Delete item
break;
case CONTEXT_MENU_EDIT:
// Edit item
break;
}
}
The same is for onCreateOptionsMenu and onOptionsItemSelected. You should have a unique constant for every menu option.
Added:
Didn't you check out this tutorial?
The idea is the same. You should set different ids in menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/new_game"
android:icon="#drawable/ic_new_game"
android:title="#string/new_game" />
<item android:id="#+id/help"
android:icon="#drawable/ic_help"
android:title="#string/help" />
</menu>
And then use those ids in onOptionsItemSelected:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.new_game:
newGame();
return true;
case R.id.help:
showHelp();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Check out these code blocks from official Android Menu tutorial and compare to your own code. You could also publish your menu.xml, onCreateOptionsMenu and onOptionsItemSelected so it would be easy to figure out your problem.