there you have the video that shows how my app actually behaves:
https://www.youtube.com/watch?v=81XIdEo0lks&feature=youtu.be
You see that when I click the search icon, it just moves it to the left side, then I need to click it again, then i need to click the x button 2 times before I actually get out of the search view, a complete mess.
Here's how I want my search view to behave:
https://www.youtube.com/watch?v=sJ-Z9G0SDhc&t
MainActivity.java (only the relevant part)
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
MenuItem searchItem = menu.findItem(R.id.app_bar_search);
SearchManager searchManager = (SearchManager) MainActivity.this.getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = null;
if (searchItem != null) {
searchView = (SearchView) searchItem.getActionView();
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(MainActivity.this.getComponentName()));
}
return super.onCreateOptionsMenu(menu);
}
options_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/app_bar_search"
android:icon="#drawable/ic_search_black_24dp"
android:title="Search"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.widget.SearchView" />
<item
android:id="#+id/logout_btn"
android:title="Log Out" />
</menu>
I want my search view to behave like the search view in that video, click on the search, the keyboard appears, you can type, you can exit. I also want to make this 3 vertical dots icon disappear when I enter the search view.
First declare a state variable to determine when menu item(s) needs to be hidden
boolean isHideMenuState = false;
Then reference the item(s) needed to be hidden inside onCreateOptionsMenu block
MenuItem logoutItem = menu.findItem(R.id.logout_btn);
//... initialize other menu items here
//use hidden state to define when to hide item(s)
if(isHideMenuState){
logoutItem.setVisible(false);
//by now the ellipses(...) should go off
//if not try using setShowAsAction passing (SHOW_AS_ACTION_NEVER)
}
else{
logoutItem.setVisible(true);
}
Next: Add focus change listener to your searchView
searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
// Toggle isHideMenuState when search widget has focus/no focus
isHideMenuState = hasFocus
//Tell menu to re-create itself
invalidateOptionsMenu(); // onCreateOptionsMenu(...) is called again
}
});
And lastly for the UI try changing the actionViewClass of your searchView item
app:actionViewClass="android.support.v7.widget.SearchView"
click on the search, the keyboard appears, you can type, you can exit.
In order to do that, you need to do this:
in onCreateOptionsMenu:
add searchView.setIconifiedByDefault(false);
add
searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
searchView.setIconified(false);
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
searchView.setIconified(true);
searchView.clearFocus();
return true;
}
});
The purpose of searchView.setIconifiedByDefault(false); is to show the expanded view of SearchView by default when user pressed the search icon. The searchView.setIconified(false); is to let the view has focus and show the soft-keyboard. The searchView.setIconified(true); is to clear the text when your user exit from the SearchView. Lastly, the searchView.clearFocus(); is to hide the soft-keyboard.
I also want to make this 3 vertical dots icon disappear when I enter the search view.
For this, you can do this:
add logoutItem.setVisible(false); in onMenuItemActionExpand
add logoutItem.setVisible(true); in onMenuItemActionCollapse
Related
For some reason, my optionItemSelected is not being called when i click the button associated with it. The timber log is not called, but this appears in the logs the moment after i click the button:
D/ViewRootImpl#ba4d36e[POIHistoryFlowActivity]: ViewPostImeInputStage processPointer 0
D/ViewRootImpl#ba4d36e[POIHistoryFlowActivity]: ViewPostImeInputStage processPointer 1
Here is the code i have:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.activity_recent_destinations, menu);
Timber.d("Menu was inflated");
}
#Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_action_item_clear:
Timber.d("Clear button was clicked");
// clear the destinations
return true;
default:
return super.onOptionsItemSelected(item);
}
}
In similar fragments, the parent's activity does not override either onCreateOptionsItem() nor onOptionsItemSelected(), but their associated buttons work while in this fragment they do not and after combing through everything with the debugger I'm at a loss as to what the root cause could be. Any help would me super appreciated!
update:
activity_recent_destinations.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/menu_action_item_clear"
android:title="#string/menu_item_title_clear"
app:actionLayout="#layout/action_item_clear"
app:showAsAction="always" />
</menu>
You are using an "action layout" for this item. This is just going to act like a normal view and clicking on it won't trigger the onOptionsItemSelected callback. You have to get a reference to the layout itself and add a click listener:
#Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.activity_recent_destinations, menu);
MenuItem item = menu.findItem(R.id.menu_action_item_clear);
View actionView = item.getActionView();
// Set the listener on the root view or any children if necessary
actionView.setOnClickListener(...);
}
My Android app has a navigation drawer with a menu. In the free version of the app, I want to have a menu item to allow the user to Upgrade to the paid version. Obviously I don't want this in the paid version.
How do I hide the menu item in the paid version?
The menu looks like this:
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/action_home"
android:icon="#drawable/btn_home"
android:title="#string/nav_home"
/>
<item
android:id="#+id/action_acc_upgrade"
android:icon="#drawable/ic_star_black"
android:title="#string/str_acc_upgrade" />
<item
android:id="#+id/action_help"
android:icon="#drawable/ic_help_black"
android:title="#string/nav_help"
/>
</menu>
In the activity, I have:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = this.getMenuInflater();
inflater.inflate(R.menu.activity_main_drawer, menu);
if(isPaid()) {
MenuItem upgrade = menu.findItem(R.id.action_acc_upgrade);
upgrade.setVisible(false);
}
return true;
}
If I run this through the debugger, it reaches the line if(isPaid()) and then evaluates it as true, so goes into the setVisible part. The item still shows up in the menu, though.
I also tried removing the item from the menu instead of hiding it; the debugger shows that the item is removed, but then it still shows up when the menu is displayed.
How can I hide/remove this item?
Edit
I'm using a navigation drawer to hold the menu. This is set up in onCreate as follows:
// Set up toolbar
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Set up navigation drawer
DrawerLayout drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.nav_drawer_open, R.string.nav_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
I suspect that this somehow bypasses onPrepareOptionsMenu etc? Is there a way of adding a listener which is called when the "open navigation drawer" button is clicked? I can only find callbacks for the drawer being opened or closed, and they're called after the drawer has moved - I need to call them before.
You can do it in onCreate() of your activity:
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
Menu navMenu = navigationView.getMenu();
navMenu.removeItem(R.id.action_acc_upgrade);
replace nav_view with your NavigationView's id.
There are several options:
The most convenient option: create 2 different productFlavours in your build.gradle file
productFlavors {
free {
...
}
paid {
...
}
}
And then override your menu file without action_acc_upgrade item for paid flavour.
If you want change visibility programmatically, try to use onPrepareOptionsMenu instead of onCreateOptionsMenu:
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if(isPaid()) {
MenuItem upgrade = menu.findItem(R.id.action_acc_upgrade);
upgrade.setEnabled(false);
upgrade.setVisible(false);
}
}
If you need to change your menu after creation, invoke invalidateOptionsMenu().
You should override onPrepareOptionsMenu like this:
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if(isPaid()) {
menu.findItem(R.id.action_settings).setVisible(false);
}
}
Notice:
Ensure get right value of isPaid() before onPrepareOptionsMenu callback, such as in onCreate() or onResume().
If it's on the fly, you need to override onPrepareOptionsMenu and call invalidateOptionsMenu if applicable:
#Override public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.action_acc_upgrade).setVisible(!isPaid());
}
See Activity.onPrepareOptionsMenu:
Prepare the Screen's standard options menu to be displayed. This is
called right before the menu is shown, every time it is shown. You can
use this method to efficiently enable/disable items or otherwise
dynamically modify the contents.
I am trying to add a simple button to my action bar, but when I try to use the following code, the items are added as items under the overflow menu, not on the actionbar itself. Any help would be appreciated,
Jacob
Here is my Java:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_review, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case android.R.id.home:
super.onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
and my XML:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yourapp="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/seda"
android:icon="#drawable/redpinreal"
android:title="Hello Worldh"
android:showAsAction="withText|always"/>
</menu>
I also have this enabled:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Part of your code (android:showAsAction, instead of yourapp:showAsAction) is attempting to use the native action bar. Part of your code (getSupportActionBar(), instead of getActionBar()) is attempting to use the appcompat-v7 action bar backport. Choose one and stick with it.
I'm creating an android action bar menu for an app. What I'm looking for is a way to show the logical groupings of menu items. So what I have currently is:
Whereas what I'd like is:
I'm creating the menu as follows:
#Override
public boolean onCreateOptionsMenu(Menu menu){
//Note, on 2.3.x - 3.0 this is called when user opens the menu for the first timed
//on 3.0+ it is called when the activity starts
MenuInflater inflater = getMenuInflater();
//adds the (currently empty) menu, after login it will be filled with options
inflater.inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu){
menu.add("example");
menu.add("example");
return true;
}
Menu XML:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:compat="http://schemas.android.com/apk/res-auto"
>
</menu>
I had hoped menu groups would help, but I understand that they are just for modifying all the menu items properties together. Equally, submenu actually creates a hidden menu that is opened free-floating when clicked.
Is there any way to create this logical grouping of menu items that I'm looking for?
I've been playing with Honeycomb for the last week and had a hard time to find something about more than one drop-down list in Action Bar.
I've used this tutorial and successfully added one drop-down list to it. But I don't know how to add another one. Please tell me if you know how to do it.
Thanks.
P.S. also one little this how can I change the position of elements in Action Bar(this is off topic)?
Not sure about Honeycomb but I was able to add two drop down lists to my action bar in JellyBean without using a custom view.
res/menu/main_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/menu_main_spinner"
android:actionViewClass="android.widget.Spinner"
android:showAsAction="always"/>
<item
android:id="#+id/menu_status_spinner"
android:actionViewClass="android.widget.Spinner"
android:showAsAction="always"/>
</menu>
MyActivity.java
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate( R.menu.main_menu, menu );
MenuItem mainMenuSpinner = menu.findItem( R.id.menu_main_spinner);
setupMainMenuSpinner( mainMenuSpinner );
MenuItem statusSpinner = menu.findItem( R.id.menu_status_spinner );
setupStatusSpinner( statusSpinner );
return super.onCreateOptionsMenu(menu);
}
private void setupMainMenuSpinner(MenuItem item) {
View view = item.getActionView();
if (view instanceof Spinner) {
Spinner spinner = (Spinner) view;
spinner.setAdapter(ArrayAdapter.createFromResource(this,
R.array.main_menu_options,
android.R.layout.simple_spinner_dropdown_item));
}
}
private void setupStatusSpinner(MenuItem item) {
View view = item.getActionView();
if (view instanceof Spinner) {
Spinner spinner = (Spinner) view;
spinner.setAdapter(ArrayAdapter.createFromResource(this,
R.array.status,
android.R.layout.simple_spinner_dropdown_item));
}
}
You would have to do that yourself. Instead of setNavigationMode(), use setCustomView().
P.S. also one little this how can I change the position of elements in Action Bar(this is off topic)?
Generally, you can't. You control the order (e.g., toolbar buttons via the order they are in your options menu XML). That's pretty much it.