Today I decide to translate my android app from Java to Kotlin ! :) But I was very surprise when I type this :
val searchItem = menu.findItem(R.id.action_search)
val searchView = MenuItemCompat.getActionView(searchItem) as SearchView
And Android Studio told me : " 'getActionView(MenuItem!):View!' is deprecated. Deprecated in Java "
So before to ask you the solution I ask to Google what is the solution and I believed I find the solution : "Use getActionView() directly."
So I modified my code like this :
val searchView = MenuItemCompat.getActionView() as SearchView
But getActionView() is still crossed so I don't understand at all...
I will be very happy if you can help me :) Thank you !
The Javadoc says:
Use getActionView() directly.
Hence, what you should do is:
val searchView = searchItem.getActionView() as SearchView
As suggested by egor, you can do like this
getMenuInflater().inflate(R.menu.menu_items, menu);
MenuItem menuItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) menuItem.getActionView();
search(searchView);
return true;
You can use the same as provided on android developer website
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the options menu from XML
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
// Get the SearchView and set the searchable configuration
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
// Assumes current activity is the searchable activity
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default
return true;
}
Use actionView directly in Kotlin, like this:
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.actions, menu)
val searchItem = menu?.findItem(R.id.action_search)
val searchView = searchItem?.actionView as SearchView
searchView.animate()
// TODO: Configure the search info and add any event listeners...
return super.onCreateOptionsMenu(menu)
}
Related
I would like to change the menu items displayed in my ActionBar depending on the current destination of my NavController. By "change" I mean inflate a specified menu-xml for each destination.
The behavior could be compared to the integrated way the new navigation system changes the ActionBar title, depending on the given android:label for the destination fragment in the navigation-xml.
So far I setup a basic activity with ActionBar and DrawerLayout using the new Android navigation. Also I created all necessary XML files and Fragments to navigate between.
...
#Override
protected void onCreate(Bundle savedInstanceState)
{
...
this._drawerLayout = this.findViewById(R.id.drawer_layout);
Toolbar toolbar = this.findViewById(R.id.action_bar);
this.setSupportActionBar(toolbar);
ActionBar actionbar = Objects.requireNonNull( this.getSupportActionBar() );
actionbar.setDisplayHomeAsUpEnabled(true);
actionbar.setHomeAsUpIndicator(R.drawable.ic_menu);
NavigationView navigationView = this.findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(menuItem -> {
menuItem.setChecked(true);
this._drawerLayout.closeDrawers();
return true;
});
NavController navController = Navigation.findNavController(this, R.id.navigation_host);
NavigationUI.setupWithNavController(toolbar, navController, this._drawerLayout);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Here I inflate the ActionBar menu that is kept between all destinations.
// Instead of keeping the same menu between all destinations I want to display different menus depending on the destination fragment.
this.getMenuInflater().inflate(R.menu.actionbar_items, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch(item.getItemId())
{
case android.R.id.home:
this._drawerLayout.openDrawer(GravityCompat.START);
return true;
case R.id.appbar_search:
return true;
}
return super.onOptionsItemSelected(item);
}
I thought about using an individual toolbar in each destination fragment
but I discarded the idea, because I would lose the transition animation between hamburger icon and back-arrow icon.
Is there any way to achieve this with the new navigation system or in any other way?
I just tested this. With the current version (2.2.2) of the navigation library, menu items inflated by each fragment will be added and removed as you navigate around.
But onCreateOptionsMenu is not called by default! To make things work, you have to sprinkle the magic dust and call setHasOptionsMenu(true) during initialisation.
Beware, any menu items inflated by the containing activity will always appear alongside the ones from the current fragment, so if you don't want any common menu items, it's probably easiest to not inflate a menu in the Activity.
Side note: in the Fragment class, onCreateOptionsMenu(menu, inflater) is an empty method, so the call to super.onCreateOptionsMenu(menu, inflater) in your code is a no-op.
I found a way to achieve the desired behavior by calling menu.clear(); before inflating the updated layout. I am still wondering if there is a built-in way to achieve this with the new navigation system.
In the destination Fragment I am using this now:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.toolbar_items_idle, menu);
}
I'm using SearchView to filter my ListView data. I managed to implement it, but I can't get this code to work.
searchView.setSubmitButtonEnabled(false);
This is my full code:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.add_group_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
MenuItem searchMenuItem = menu.findItem(R.id.search);
SearchView searchView = (SearchView) searchMenuItem.getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setQueryHint(getResources().getString(R.string.hint_type_something));
searchView.setSubmitButtonEnabled(false);
int searchPlateId = searchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
View searchPlate = searchView.findViewById(searchPlateId);
if (searchPlate != null) {
int searchTextId = searchPlate.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
TextView searchText = (TextView) searchPlate.findViewById(searchTextId);
if (searchText != null) {
searchText.setTextColor(Color.WHITE);
searchText.setHintTextColor(getResources().getColor(R.color.white));
}
}
searchView.setSubmitButtonEnabled(true);
searchView.setOnQueryTextListener(this);
return true;
}
Image:
If anyone have a clue in How to I hide the submit button beside searchview?
Remove this line of code from your code.
//remove this line
searchView.setSubmitButtonEnabled(true);
So this I the code I use in the Activity that should get a search function:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
// Associate searchable configuration with the SearchView
SearchManager searchManager =
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView =
(SearchView) menu.findItem(R.id.search).getActionView();
***searchView.setSearchableInfo(
searchManager.getSearchableInfo(getComponentName()));***
return true;
}
I got this code from the androidDeveloper site. The two lines that I made highlighted are the ones that are making trouble.
What am I doing wrong?
I found the solution in the first answer of this post, just in case someone else has the same problem!
Android - NullPointerException on SearchView in Action Bar
I’m trying to add a SearchView in the ActionBar of a Fragment which is a part of DrawerLayout. I need the SearchView only for one fragment. I do the following in the onCreateOptionsMenu() method of the Fragment.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Auto-generated method stub
menu.clear();
inflater.inflate(R.menu.alarm_list_menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
}
mSearchView is null every time. Have I missed some thing? I ‘m able to see the search icon on the ActionBar, but nothing more can be done.
I've got 2 activites : the first, HomepageActiviy, have a search widget that search data using another activity, SearchActivity.
What I want to do is when I go back from SearchActiviy to HomepageActivity, the search widget go collapsed and with a empty text.
I've tried to do this following thing :
public class HomepageActivity extends Activity {
#TargetApi(11)
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.projectslist, menu);
if(Build.VERSION.SDK_INT >= 11) {
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.homepage_search).getActionView();
ComponentName component = new ComponentName(this, SearchActivity.class);
searchView.setSearchableInfo(searchManager.getSearchableInfo(component));
searchView.setIconifiedByDefault(true);
searchView.setQuery("", false);
}
return super.onCreateOptionsMenu(menu);
}
[…]
#TargetApi(11)
#Override
protected void onRestart() {
super.onRestart();
if(Build.VERSION.SDK_INT >= 11)
invalidateOptionsMenu();
launchAsynchronousImageDownload();
}
}
If the widget is well displayed as collapsed, the text in the widget still remember searched text (after I re-open the widget).
How can I reset the text of the widget?
Thanks for any help! ;)
You might also try the following:
searchView.setQuery("", false);
searchView.clearFocus();
this is the magic
searchView.setQuery("", false); // clear the text
searchView.setIconified(true); // close the search editor and make search icon again
in the HomepageActivity insert the onSaveInstanceState function after oncreate function
this function will trigger everytime you open a new activity ,
before opening new activity it will reset the value of Search Widget
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
searchView.setQuery("", false);
searchView.setIconified(true);
}
This worked for me:
First, I declared the menu item variable at the top of the activity:
private MenuItem mSearchMenuItem;
I defined the variable in OnCreateOptionsMenu():
mSearchMenuItem = menu.findItem(R.id.action_search);
I declared invalidateOptionsMenu() in onResume():
#Override
protected void onResume() {
invalidateOptionsMenu();
super.onResume();
}
Lastly, I called collapseActionView() on the menu item in onPrepareOptionsMenu().
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
mSearchMenuItem.collapseActionView();
return super.onPrepareOptionsMenu(menu);
}
searchView.setQuery("", false);
searchView.setIconified(false);
I had this problem too and it worked if I put it in onPrepareOptionsMenu.
#Override
public boolean onPrepareOptionsMenu (Menu menu) {
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setQuery("", false);
// rest of code...
}
Kotlin
Here's a cleaner solution, it fixes the following:
Issue of showing filtered list after screen rotation.
Issue of showing filtered list when the user switches to other app and returns back.
Issue of search menu shifting to the left when the user returns back.
No need to iconify if you are invalidating, it's done automatically.
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
searchView.setQuery("", false)
(activity as YourActivity).invalidateOptionsMenu()
}
Make sure to change YourActivity to the Activity name in which you have your Fragment.
Just found an ugly way to make it work (read comments to see differences):
public class HomepageActivity extends Activity {
// Declaring SearchView as an instance object
private SearchView searchView;
#TargetApi(11)
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.projectslist, menu);
if(Build.VERSION.SDK_INT >= 11) {
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
// Using instance var instead of local var
searchView = (SearchView) menu.findItem(R.id.homepage_search).getActionView();
ComponentName component = new ComponentName(this, SearchActivity.class);
searchView.setSearchableInfo(searchManager.getSearchableInfo(component));
searchView.setIconifiedByDefault(true);
// Setting query is not anymore required
//searchView.setQuery("", false);
}
return super.onCreateOptionsMenu(menu);
}
[…]
#TargetApi(11)
#Override
protected void onRestart() {
super.onRestart();
// Do not need to recreate menu
/*if(Build.VERSION.SDK_INT >= 11)
invalidateOptionsMenu();*/
if(Build.VERSION.SDK_INT >= 11) {
// Calling twice: first empty text field, second iconify the view
searchView.setIconified(true);
searchView.setIconified(true);
}
launchAsynchronousImageDownload();
}
}
It's pretty ugly, I think, so if anybody as a better idea, just tell me :)