Infinite loop when using onNavigationItemSelected and invalidateOptionsMenu - android

I have an action bar which contains a list navigation and a sub menu. I want to update the sub menu items according to the user selection in the list navigation. I'm trying to call invalidateOptionsMenu() in the onNavigationItemSelected() but this creates an infinite loop.
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
invalidateOptionsMenu();
Log.i("onNavigationItemSelected", "onNavigationItemSelected called");
return true;
}
I'm using ActionBarSherlock. This is one of my first Android/Java project.

Related

Navigation drawer listview fragment

I want to make a navigation drawer which will populate by listview. Now i want that by clicking each item of the list, open a fragment as per my choice. How do I do this?
The NavigationDrawer doesn't use a ListView in the menu, NavigationDrawer uses directly Menu Items it means that in your source code you can add programmatically items to your menu as you need.
Your NavigationDrawer activity or whatever you named
you can add items to the menu using the
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// To Inflate the menu:
// this adds items to the navigation drawer menu if it is present.
getMenuInflater().inflate(R.menu.dashboard, menu);
return true;
}
by default this method create a static menu using a XML layout in the res/menu/menu_file.xml
but if you follow the next source code you will be able to add more items to your navigation drawer programmatically
the Method add() overloads:
add (int titleRes)
add (CharSequence title)
add (int groupId, int itemId, int order, int titleRes);
add (int groupId, int itemId, int order, CharSequence title);
if you already have all the names of your new menu items in an array like itemsName
you can use something like this:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
for(String itemName : itemsName){
int itemId = Arrays.asList(itemsName).indexOf(itemName);
menu.add(Menu.NONE, itemId, Menu.NONE, itemName);
}
return true;
}
and to manage the click event, on every one, you need to solve it depending on your array of actions to take, in your dynamic array, because you need to know deterministic every action that your menu item need to do or behave, as a menu option.
But in general your click listener for those menu items you use something like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
//here you need the logic of what action
//your item is going to take
//but that is up to you
//how do you want to know what to do
//with a dynamic unknown array of options.
if (itemId == 0){
doSomething();
return true;
}
return false;
}
}
enjoy!!!

Xamarin Android Menu Bar repeats iteslf

I have a Xamarin Android project that contains a menu bar. I'm almost certain this was working correctly yesterday, but since then, every time I click on a menu bar item such as 'settings', which takes me to the Settings Activity, then go back to the Main activity, the menu bar items are repeating themselves.
So where i just had 'Settings' and 'help', i not have 2 settings, and 2 help items. If i do it again, i will have 3 of each.
I'm assuming this is something to do with the onPause() and onResume() methods as the app goes to another activity. But i can't see where i'm going wrong (i'm new to Android)
My code for generating the menu bar in the Main Activity is:
public override bool OnPrepareOptionsMenu(IMenu menu1)
{
MenuInflater.Inflate(Resource.Menu.myMenuBar, menu1);
return base.OnPrepareOptionsMenu(menu1);
}
public override bool OnOptionsItemSelected(IMenuItem item) //do something when an options item is pressed
{
switch (item.ItemId)
{
case Resource.Id.settingsItem:
showSettings ();
return true;
case Resource.Id.helpItem:
//do something
return true;
}
return base.OnOptionsItemSelected(item);
}
Any ideas on this would be appreciated. I'm sure it's something fairly simple but I don't know what.
You should probably have to clear the menu
public override bool OnPrepareOptionsMenu(IMenu menu1)
{
menu1.clear();
MenuInflater.Inflate(Resource.Menu.myMenuBar, menu1);
return base.OnPrepareOptionsMenu(menu1);
}
And perhaps you should inflate the menu in the OnCreateOptionsMenu(IMenu, MenuInflater) method. OnPrepareOptionsMenu(IMenu) is meant for enabling/disabling and dynamically modifying items.

sub menu within a menu

I am trying to display a menu item named "share" by clicking the menu button.
now i need to create a submenu item for this share menu item.
The sub menu item should be visible when the share menu item is clicked alternatively (when clicked first time becomes visible next time invisible and so on.).
I found few solutions which are displaying the sub menuitems but those are being displayed along with the menu item.
This is my code for creating menus
public boolean onCreateOptionsMenu(Menu m) {
m.add(1,1,0,"one").setIcon(R.drawable.icon);
m.add(1,2,0,"two").setIcon(R.drawable.icon);
m.add(1,3,0,"three").setIcon(R.drawable.icon);
m.add(1,4,0,"four").setIcon(R.drawable.icon);
m.getItem(0).setVisible(false);
m.getItem(1).setVisible(false);
return true;
}
and my onPrepareOptionsMenu()
public boolean onPrepareOptionsMenu(Menu m) {
if(isvisible)
{
isvisible = false;
m.getItem(0).setVisible(true);
m.getItem(1).setVisible(true);
}
else{
isvisible = true;
m.getItem(0).setVisible(false);
m.getItem(1).setVisible(false);
}
return super.onPrepareOptionsMenu(m);
}
I need the remaining two items to be shown when i click on the menu item rather than on the menu button.
Can anyone suggest me please
override the below method:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
return super.onPrepareOptionsMenu(menu);
}
The above method is called every time before the menu is shown.
Here you can maintain a bool and hide the submenu depending upon the condition of your check.
EDIT:
By default set bool to false and on false show the menu and set the bool to true and on next call check this bool and if it is true, set it false and make the menu invisible.use this line to make the menu visible or invisible:
menu.getItem(index).getSubMenu().getItem(index).setVisible(true);
Store the bool in sharedpreference.

android action bar onNavigationItemSelected

I'm developing for android 3+
In my action bar i have a drop-down list(see how to hide/unhide the actionbar list on android 3? for the dropdown i intend). The problem is i need to do a certain action when the user selects something, but Android calls onNavigationItemSelected() as soons as it draws the view, so no selection actually happened.
How can i detect if the user actually pressed something and it is not a fake call from android ?
public class ListDittaListener implements OnNavigationListener{
private BaseActivity activity;
private ListDittaListener()
{
}
public ListDittaListener(BaseActivity activity)
{
this.activity = activity;
}
#Override
public boolean onNavigationItemSelected(int itemPosition, long itemId)
{
MyApp appState = ((MyApp)this.activity.getApplicationContext());
appState.setDittaSelezionata( (int) itemId);
SharedPreferences settings = this.activity.getSharedPreferences(MyApp.PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putInt("ditta_id_selezionata", (int) itemId);
////////restart activity this.activity.recreate();
return false;
}
}
You can easily just ignore the first call to onNavigationItemSelected if you like:
public class Whatever implements OnNavigationListener {
private boolean synthetic = true;
#Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
if (synthetic) {
synthetic = false;
return true;
}
// do whatever you really wanted here
}
}
Method onNavigationItemSelected(int itemPosition, long itemId) will be called anyway by the action bar.
What you may want to do is to tell action bar what itemPosition it should pass to the method on the first call. (In other words, to tell action bar what navigation item should be set after activity is created). Here is the code:
mActionBarMenuSpinnerAdapter = ...;
mActionBar = getActionBar();
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
mActionBar.setListNavigationCallbacks(mActionBarMenuSpinnerAdapter, this);
mActionBar.setSelectedNavigationItem(###your_default_navigation_item_here###);
After doing this you can solve your problem by applying changes in the onNavigationItemSelected(int itemPosition, long itemId) if only itemPosition is different.
The android system will call onNavigationItemSelected(0, 0) after the activity is setup. (Which means later than onResume()).
As other guys mentioned, you'd better not do any hack like ignore first call, otherwise the android system won't call onNavigationItemSelected() again when you select the first index. (The system thought the first item is already selected)
My solution is call actionbar.setSelectedNavigationItem(the real item# you want) after you setup the actionbar. Then the system will call onNavigationItemSelected() twice. First onNavigationItemSelected(0, 0) and then the onNavigationItemSelected(the real item#).
Well I cannot see anything wrong in your current code.
How did you create your dropdown elements. And what element is "select" by Android after the view is created. And what are your doing in your onCreate method where the ActionBar is initialized.
I did it as instructed here and it worked for me:
http://developer.android.com/guide/topics/ui/actionbar.html#Dropdown
I have viewpager with fragments and I need set custom action bar for every fragment in pager
In desired page I have navigation list, fragment fires onNavigationItemSelected automatically when I swipe pages, want to avoid this behavior and run tasks only if I selected nav item manually.
public class MyFragment extends Fragment implements ActionBar.OnNavigationListener {
private boolead fireReady = false;
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
// every time make it false, this method invoked on swipe action
fireReady = false;
if (isVisibleToUser) {
// setup actionbar, you also can setup action bar in activity
String[] array = getActivity().getResources().getStringArray(R.array.users_order);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_item, array);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
getActivity().getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
getActivity().getActionBar().setListNavigationCallbacks(adapter, this);
}
}
#Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
if (fireReady) {
// task fire only when you directly press navigation item
UsersTask task = new UsersTask(getActivity());
task.setTaskListener(this);
task.execute(usersUrls[itemPosition]);
} else {
// make it true first time when page displayed
fireReady = true;
}
return false;
}
}
}

How to invoke the ActionBar's ContextMenu-like behavior?

In Android 3.0, when you select some text for example, the ActionBar switches to a ContextMenu-like mode, which enables you to do actions with the selected text: copy/share/etc, and a "Done" button appears on the left side to enable the user to leave this mode.
How can I switch the ActionBar into this mode in my app (with my menu items of course)? I just couldn't find this in the docs.
To use the new contextual action bar, see "Enabling the contextual action mode for individual views".
It states:
If you want to invoke the contextual action mode only when the user selects specific
views, you should:
Implement the ActionMode.Callback interface. In its callback methods, you
can specify the actions for the contextual action bar, respond to click events on action items, and handle other lifecycle events for the action mode.
Call startActionMode() when you want to show the
bar (such as when the user long-clicks the view).
For example:
Implement the ActionMode.Callback interface:
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
return true;
}
// Called each time the action mode is shown. Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_share:
shareCurrentItem();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
// Called when the user exits the action mode
#Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
Notice that these event callbacks are almost exactly the same as the callbacks for the options menu, except each of these also pass the ActionMode object associated with the event. You can use ActionMode APIs to make various changes to the CAB, such as revise the title and
subtitle with setTitle() and setSubtitle() (useful to indicate how many items are
selected).
Also notice that the above sample sets the mActionMode variable null when the
action mode is destroyed. In the next step, you'll see how it's initialized and how saving
the member variable in your activity or fragment can be useful.
Call startActionMode() to enable the contextual
action mode when appropriate, such as in response to a long-click on a View:
someView.setOnLongClickListener(new View.OnLongClickListener() {
// Called when the user long-clicks on someView
public boolean onLongClick(View view) {
if (mActionMode != null) {
return false;
}
// Start the CAB using the ActionMode.Callback defined above
mActionMode = getActivity().startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
When you call startActionMode(), the system returns
the ActionMode created. By saving this in a member variable, you can
make changes to the contextual action bar in response to other events. In the above sample, the
ActionMode is used to ensure that the ActionMode instance
is not recreated if it's already active, by checking whether the member is null before starting the
action mode.
Enabling batch contextual actions in a ListView or GridView
If you have a collection of items in a ListView or GridView (or another extension of AbsListView) and want to
allow users to perform batch actions, you should:
Implement the AbsListView.MultiChoiceModeListener interface and set it
for the view group with setMultiChoiceModeListener(). In the listener's callback methods, you can specify the actions
for the contextual action bar, respond to click events on action items, and handle other callbacks
inherited from the ActionMode.Callback interface.
Call setChoiceMode() with the CHOICE_MODE_MULTIPLE_MODAL argument.
For example:
ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
// Here you can do something when items are selected/de-selected,
// such as update the title in the CAB
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// Respond to clicks on the actions in the CAB
switch (item.getItemId()) {
case R.id.menu_delete:
deleteSelectedItems();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate the menu for the CAB
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context, menu);
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
// Here you can make any necessary updates to the activity when
// the CAB is removed. By default, selected items are deselected/unchecked.
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// Here you can perform updates to the CAB due to
// an invalidate() request
return false;
}
});
That's it. Now when the user selects an item with a long-click, the system calls the onCreateActionMode()
method and displays the contextual action bar with the specified actions. While the contextual
action bar is visible, users can select additional items.
In some cases in which the contextual actions provide common action items, you might
want to add a checkbox or a similar UI element that allows users to select items, because they
might not discover the long-click behavior. When a user selects the checkbox, you
can invoke the contextual action mode by setting the respective list item to the checked
state with setItemChecked().
Yeah, I couldn't find it either -- I had to ask at Google I|O.
Use startActionMode(). Here is one of their samples that demonstrates it. I need to do more work in this area myself.
Maybe a bit late but here's a tutorial for the actionmode:
http://www.vogella.com/articles/AndroidListView/article.html#listview_actionbar

Categories

Resources