I'm trying to implement SearchView according to some online tutorials. But when i clicked the search icon, it did not expand, instead another search icon appeared to the left and i must click again; this time it worked.
Are there something i'm missing here?
Here are the captured images, sorry i can't post these to stackoverflow yet.
http://1drv.ms/186yI2Y
If i delete collapseActionView then it worked, but i can't customize search icon.
<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/search"
android:title="#string/search_title"
android:icon="#drawable/ic_action_search"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.widget.SearchView"/>
</menu>
In MainActivity.java
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
// Associate searchable configuration with the SearchView
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
MenuItem searchItem = menu.findItem(R.id.search);
mSearchView = (SearchView) searchItem.getActionView();
mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
mSearchView.setIconifiedByDefault(true);
mSearchView.setOnSearchClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showResultsFragment();
}
});
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
boolean toggleHandled = mDrawerToggle.onOptionsItemSelected(item);
return toggleHandled || super.onOptionsItemSelected(item);
}
Thank in advance!
in your menu xml i changed app:actionViewClass="android.support.v7.widget.SearchView"
<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/search"
android:title="wrwrwr"
android:icon="#drawable/abc_ic_menu_copy_mtrl_am_alpha"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>
and in your activity
import android.support.v7.widget.SearchView; //don't import android.widget.SearchView
I am trying to add actions items in my action bar using appcompat. I added search action when I click on it my application crash with NullPointerException. In onCreateOptionsMenu I am getting this view reference but there I am always getting null. Any suggestion to resolve this ??
main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_bar_refresh"
android:icon="#drawable/ic_action_refresh"
app:showAsAction="ifRoom"
android:title="#string/action_refresh" />
<item
android:id="#+id/action_bar_search"
android:icon="#drawable/ic_action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="ifRoom"
android:title="#string/action_search" />
<item
android:id="#+id/action_bar_settings"
android:title="#string/action_settings"
app:showAsAction="never" />
</menu>
MainActivity.java
public class MainActivity extends ActionBarActivity {
private SearchView mSearchView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_bar_search);
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_bar_search:
mSearchView.setIconified(false);
return true;
}
return false;
}
}
Here I am getting null value in searchView
MenuItem searchItem = menu.findItem(R.id.action_bar_search);
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
Screenshot
<item
android:id="#+id/action_bar_search"
android:icon="#drawable/ic_action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="collapseActionView|ifRoom"
android:title="#string/action_search" />
You change showAsAction attribute.
I fixed issue by setting Application Theme to Theme.AppCompat.Light
<style name="AppBaseTheme" parent="#style/Theme.AppCompat.Light">
I was trying to create an action bar search in my application, but in the expanded state the SearchView is not taking the entire action bar width( it is still showing other actions)!
So, how to make the SearchView fill the full ActionBar Area (as in GMAIL app)?
None of the above solutions worked for me. Setting the MaxWidth of the SearchView worked for me:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_search, menu);
SearchView searchView = (SearchView)menu.findItem(R.id.menu_search).getActionView();
searchView.setMaxWidth(Integer.MAX_VALUE);
Got it
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.my_swipe_tabbed, menu);
MenuItem searchViewItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchViewItem.getActionView();
searchView.setIconifiedByDefault(false);
ActionBar.LayoutParams params = new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT, ActionBar.LayoutParams.MATCH_PARENT);
searchView.setLayoutParams(params);
searchViewItem.expandActionView();
return true;
}
<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=".MySwipeTabbedActivity" >
<item android:id="#+id/action_search"
android:title="Search"
android:icon="#android:drawable/ic_menu_search"
android:showAsAction="always|collapseActionView"
android:actionViewClass="android.widget.SearchView"
/>
<item android:id="#+id/action_share"
android:title="Share"
android:icon="#android:drawable/ic_menu_share"
android:showAsAction="ifRoom" />
<item android:id="#+id/action_settings"
android:title="Settings"
android:icon="#android:drawable/ic_menu_preferences"
android:showAsAction="never" />
</menu>
[Optional] Avoid the searchView from collapsing:
searchViewItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
return false; //never collapse
}
});
The Answer given by #Hiep is correct i followed those steps to get my solution.but i was using ActionbarCompact lib so it take some changes to made so that i get it to work This solution is only the modified answer of Hiep if you are using appcompact
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:materialdesign="http://schemas.android.com/apk/res-auto" >
<item android:id="#+id/action_search"
android:title="search"
android:icon="#drawable/abc_ic_search_api_mtrl_alpha"
materialdesign:showAsAction="always|collapseActionView"
materialdesign:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
And in the Main Class onCreateOptionsMenu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my_swipe_tabbed, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
// Get the SearchView and set the searchable configuration
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
ActionBar.LayoutParams params = new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT, ActionBar.LayoutParams.MATCH_PARENT);
searchView.setLayoutParams(params);
searchView.setIconified(false);
MenuItemCompat.expandActionView(searchItem);
return super.onCreateOptionsMenu(menu);
}
Avoid the searchView from collapsing:If u use the above method in Appcompact it will create a crash so use this solution to avoid that.
MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
/* (non-Javadoc)
* #see android.support.v4.view.MenuItemCompat.OnActionExpandListener#onMenuItemActionExpand(android.view.MenuItem)
*/
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
}
/* (non-Javadoc)
* #see android.support.v4.view.MenuItemCompat.OnActionExpandListener#onMenuItemActionCollapse(android.view.MenuItem)
*/
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
return false;
}
});
Thank you
Try This Only will work and keep all other items set to ifRoom
<item
android:id="#+id/action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
android:title="#string/action_search"
app:showAsAction="always"/>
Yes, I'm really late :)
But I would like to share one more alternative solution. The idea is just to hide the grouped menu items when the SearchView gets expanded.
Step 1:
Group your menu items. Please make sure showAsAction of search view item is app:showAsAction="collapseActionView|always"
<group android:id="#+id/myMenuGroup">
<item
android:id="#+id/actionSearch"
android:icon="#drawable/ic_search"
android:title="#string/search"
app:actionViewClass="android.widget.SearchView"
app:iconTint="#color/textColorVariant2"
app:showAsAction="collapseActionView|always" />
<item
android:id="#+id/actionFilter"
android:icon="#drawable/ic_filter"
android:orderInCategory="0"
android:title="#string/filter"
app:iconTint="#color/textColorVariant2"
app:showAsAction="ifRoom" />
..... </group>
Step 2: Get the menu reference in onPrepareOptionsMenu() callback
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
super.onPrepareOptionsMenu(menu)
this.menu = menu // this.menu is a global scoped variable
return true
}
Step 3
Add MenuItem.OnActionExpandListener into your activity and implement onMenuItemActionExpand() and onMenuItemActionExpand() like below
override fun onMenuItemActionExpand(p0: MenuItem?): Boolean {
menu?.setGroupVisible(R.id.myMenuGroup, false)
return true
}
override fun onMenuItemActionCollapse(p0: MenuItem?): Boolean {
menu?.setGroupVisible(R.id.myMenuGroup, true)
return true
}
This approach will expand the SearchView completely inside the ActionBar even if there are other menu icons present
I'm having a problem with the alignment of the SearchView when it's expanded. For some reason, when collapsed it aligns rights, but when expanded it aligns left. I did everything folowing the ActionBarSherlock examples.
Here are two screenshots of the problem:
Screenshot collapsed http://img59.imageshack.us/img59/8976/.png
Screenshot expanded http://img577.imageshack.us/img577/9890/.png
I have yet to decide if I want to use ActionBar tabs. I don't want the searchView to hide them when expanded. But that's for another question. My main issue here is the alignment of the SearchView when exapanded. I want it to keep the right alignment no matter what.
Here's my onCreateOptionsMenu:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.menu_main, menu);
searchMenuItem = menu.findItem(R.id.action_search);
refreshMenuItem = menu.findItem(R.id.action_refresh);
refreshMenuItem.setActionView(R.layout.refresh_progressbar);
searchMenuItem.setOnActionExpandListener(new OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
flightsListAdapter.getFilter().filter("");
return true;
}
});
searchView = (SearchView)searchMenuItem.getActionView();
searchView.setQueryHint(getResources().getString(R.string.search_hint));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
searchView.clearFocus();
return true;
}
#Override
public boolean onQueryTextChange(String query) {
flightsListAdapter.getFilter().filter(query);
return true;
}
});
searchView.clearFocus();
return true;
}
And here is my menu_main.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/action_search"
android:title="#string/search"
android:icon="#drawable/ic_search"
android:showAsAction="always|collapseActionView"
android:actionViewClass="com.actionbarsherlock.widget.SearchView" />
<item
android:title="#string/date"
android:icon="#drawable/ic_compose"
android:showAsAction="always" >
<menu>
<item
android:id="#+id/menuYesterday"
android:title="Yesterday"/>
<item
android:id="#+id/menuToday"
android:title="Today"/>
<item
android:id="#+id/menuTomorrow"
android:title="Tomorrow"/>
</menu>
</item>
<item
android:id="#+id/action_refresh"
android:icon="#drawable/ic_refresh"
android:showAsAction="always"
android:title="#string/action_refresh" />
</menu>
Thank you for reading :)
Ok. Just for the sake of common knowledge, I'm answering my own question.
The trick was to remove "collapseActionView" on the SerchView. Once I removed that, the SearchView stays in place (to the right) when exanded.
I just implemented the v7 AppCompat support library but the MenuItemCompat.getActionView always return null in every Android version I tested (4.2.2, 2.3.4 ....)
The SearchView is displayed in action bar but it doesn't respond to touch actions and doesn't expand to show its EditText and is just like a simple icon.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
if (searchView != null) {
SearchViewCompat.setOnQueryTextListener(searchView, mOnQueryTextListener);
searchView.setIconifiedByDefault(false);
Log.d(TAG,"SearchView not null");
} else
Log.d(TAG, "SearchView is null");
}
return super.onCreateOptionsMenu(menu);
}
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/action_search"
app:showAsAction="always|collapseActionView"
android:icon="#drawable/abc_ic_search"
android:title="#string/action_bar_search"
android:actionViewClass="android.support.v7.widget.SearchView"/>
<item android:id="#+id/action_refresh"
android:icon="#drawable/refresh"
android:title="#string/action_bar_refresh"
app:showAsAction="ifRoom"/>
</menu>
Finally I found the solution.
Changing namespace of actionViewClass from android:actionViewClass to app:actionViewClass
Implementing android.support.v7.widget.SearchView.OnQueryTextListener interface for current activity.
Directly use setOnQueryTextListener instead of SearchViewCompat.setOnQueryTextListener
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
if (searchView != null) {
searchView.setOnQueryTextListener(this);
}
return super.onCreateOptionsMenu(menu);
}
In my case it was ProGuard file. You need to add this line:
-keep class android.support.v7.widget.SearchView { *; }
For me, an incorrect menu.xml namespace import caused this problem.
My original menu.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/tools">
<item android:id="#+id/action_search"
android:title="#string/map_option_search"
android:icon="#drawable/ic_action_search"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>
It looks like the xmlns:app="http://schemas.android.com/tools" was causing MenuItemCompat.getActionView() to return null. Changing this import to xmlns:app="http://schemas.android.com/apk/res-auto" fixed the problem.
New working menu.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/action_search"
android:title="#string/map_option_search"
android:icon="#drawable/ic_action_search"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>
I think that the problem is that you use the SearchView from the Support V7 package and maybe your API level is set to.....22??.
Changing your code to the following in order to fix the problem:
menu.xml
<?xml version="1.0" encoding="UTF-8" ?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/action_search"
android:icon="#drawable/actionbar_button_search"
android:title="Search"
android:showAsAction="always"
android:actionViewClass="android.widget.SearchView" />
</menu>
I was with the same error, my method getActionView() was always returning null. So, I've made the following things:
<item android:id="#+id/action_search"
android:icon="#drawable/abc_ic_search"
android:title="#string/search_title"
android:showAsAction="always"
android:actionViewClass="android.widget.SearchView"/>
I saw in some posts that the people are using app: or yourapp, but i've used normally android:ActionVewClass.
On my onCreateOptionsMenu method:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.feed, menu);
// Associate searchable configuration with the SearchView
SearchManager searchManager =
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.action_search)
.getActionView();
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
return true;
}
And do not forget to put in the onCreate method:
// enabling action bar app icon and behaving it as toggle button
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
This works very well for my activity "extending" for FragmentActivity and ActionBarActivity.
Mohsen Afshin's answer above was my starting point and I made some tweaks to get it working with my setup:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
// SearchView searchView = (SearchView) MenuItemCompat
// .getActionView(searchItem);
SearchView searchView = (SearchView) searchItem.getActionView();
if (searchView != null) {
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
// do something with s, the entered string
query = s;
Toast.makeText(getApplicationContext(),
"String entered is " + s, Toast.LENGTH_SHORT).show();
return true;
}
#Override
public boolean onQueryTextChange(String s) {
return false;
}
});
}
return super.onCreateOptionsMenu(menu);
}
menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity" >
<item android:id="#+id/action_search"
android:orderInCategory="5"
android:title="Search"
android:icon="#drawable/ic_action_search"
android:showAsAction="ifRoom|collapseActionView"
android:actionViewClass="android.widget.SearchView" />
</menu>
I did this by manual set in java code:
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/user_info"
android:title="#string/user_name_title"
app:actionLayout="#layout/menu_item_username"
android:showAsAction="always" />
</menu>
Layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal">
<TextView
android:id="#+id/usr_name_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:contentDescription="#string/user_info_image_des"
android:padding="5dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:text="#string/user_name_title"
android:textStyle="bold"
android:visibility="visible" />
</LinearLayout>
Then in java code:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.connect_menu, menu);
// show user name on the top of menu
Log.e("menu", "Size: " + menu.size());
MenuItem item = menu.getItem(0);
item.setActionView(R.layout.menu_item_username);
View v = item.getActionView();
if (null == v) {
Log.e("NULL POINTER EX", "NULL MENU VIEW");
} else {
TextView usrNameTitle = v.findViewById(R.id.usr_name_title);
if (null != usrName && usrName.length() > 0) {
usrNameTitle.setText(usrName);
}
}
return true;
}
I had the same code, but instead of using the import android.support.v7.widget.SearchView; I was using import android.widget.SearchView; . This fixed my problem with the null value.
So just change this code in your search activity and it will work and also change the namespace in xml file.
Here's a snippet of how to handle the searchView from support library v7 :
#Override
public void onCreateOptionsMenu(final Menu menu,final MenuInflater inflater)
{
menu.clear();
getActivity().getMenuInflater().inflate(...,menu);
_searchView=(SearchView)MenuItemCompat.getActionView(_searchMenuItem);
_searchView.setQueryHint(...);
if(VERSION.SDK_INT<VERSION_CODES.HONEYCOMB)
{
final EditText searchTextView=(EditText)searchView.findViewById(R.id.search_src_text);
if(searchTextView!=null)
{
searchTextView.setScroller(new Scroller(_context));
searchTextView.setMaxLines(1);
searchTextView.setVerticalScrollBarEnabled(true);
searchTextView.setMovementMethod(new ScrollingMovementMethod());
searchTextView.setTextColor(_context.getResources().getColor(App.getResIdFromAttribute(_context,android.R.attr.textColorPrimary)));
}
}
_searchView.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener()
{
...
});
MenuItemCompat.setActionView(_searchMenuItem,_searchView);
MenuItemCompat.setOnActionExpandListener(_searchMenuItem,new OnActionExpandListener()
{
...
});
super.onCreateOptionsMenu(menu,inflater);
}
public static int getResIdFromAttribute(final Activity activity,final int attr)
{
if(attr==0)
return 0;
final TypedValue typedvalueattr=new TypedValue();
activity.getTheme().resolveAttribute(attr,typedvalueattr,true);
return typedvalueattr.resourceId;
}
Also, if you use Proguard, add this to its configuration :
-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class android.support.v7.widget.SearchView { *; }
-keepattributes *Annotation*
I had a very similar issue with the difference being I was attempting to use a class that extended android.widget.ImageView
If you're using ProGuard, you need to specify to allow the methods involved in this class.
-keep public class * extends android.widget.ImageView{
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
http://proguard.sourceforge.net/manual/examples.html
This says, "Allow all needed constructors that might be called from xml and allow any custom setters it uses as well (add more as needed)"
Remove code:
public class DemoActivity extends ActionBarActivity
Replace by:
public class DemoActivity extends Activity