I'm following this Android tutorial to implement the Search View. After fixing some issues, I got it to work. However, the search view needs to be clicked twice to open the editText. Any idea of what's going on?
Filter class:
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.toolbar_menu_filter, menu);
// Associate searchable configuration with the SearchView
SearchManager searchManager =
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView =
(SearchView) menu.findItem(R.id.menu_item_search).getActionView();
searchView.setSearchableInfo(
searchManager.getSearchableInfo(getComponentName()));
searchView.setQueryHint(getResources().getString(R.string.search_hint));
return super.onCreateOptionsMenu(menu);
}
menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".FilterUI">
<item android:id="#+id/menu_item_search"
android:title="Search"
android:icon="#drawable/ic_search_white"
app:actionViewClass="android.widget.SearchView"
app:showAsAction="ifRoom|collapseActionView"/>
<item android:id="#+id/menu_item_options"
android:icon="#drawable/ic_clear_all_white"
app:showAsAction="ifRoom"
android:title="#string/filter_default"/>
Manifest file
<activity android:name=".Activities.FilterUI"
android:screenOrientation="portrait"
android:configChanges="orientation"
android:windowSoftInputMode="adjustNothing">
<meta-data android:name="android.app.searchable"
android:resource="#xml/searchable" />
</activity>
<activity android:name=".Activities.SearchActivity">
<intent-filter>
<action android:name="android.intent.action.SEARCH"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Might be too late to answer but, let's get this done. Like I said, it's better to use:
app:actionViewClass="android.support.v7.widget.SearchView"
For more compatibility and etc. But the point is, in new AndroidX, we can't use android.support since we migrate to AndroidX and there will be only:
app:actionViewClass="android.widget.SearchView"
Available. But, let's see what documentation says for the newest APIs (AndroidX) and etc:
Note: This class is included in the support library for compatibility with API level 7 and higher. If you're developing your
app for API level 11 and higher only, you should instead use the
framework android.widget.SearchView class.
So in AndroidX, I have found:
app:actionViewClass="androidx.appcompat.widget.SearchView"
To use but you still can use: android.widget.SearchView.
Related
In Android 11, when targetSdk is set to 30 and voice search is enabled, the microphone icon doesn't show on the SearchView. However, it works correctly if targetSdk is set to 29. It works on Android 10 devices also with targetSdk 30.
Is there anything extra which needs to be done for 30?
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="Search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="always" />
</menu>
Manifest.xml
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable" />
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
</activity>
searchable.xml
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="#string/app_name"
android:hint="Search"
android:imeOptions="actionSearch"
android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"/>
MainActivity
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.search, menu)
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
val searchView: SearchView = menu.findItem(R.id.action_search).actionView as SearchView
val searchableInfo = searchManager.getSearchableInfo(componentName)
Log.d(TAG, "onCreateOptionsMenu: ${searchableInfo.voiceSearchEnabled}, ${searchableInfo.voiceSearchLaunchRecognizer}")
searchView.setSearchableInfo(searchableInfo)
searchView.setIconifiedByDefault(false)
return super.onCreateOptionsMenu(menu)
}
Android 11 doesn't allow checking all the installed applications, so we need to add a queries block to allow the app to see the voice search app.
Add this in AndroidManifest.xml below the manifest tag for microphone icon to show up:
<queries>
<intent>
<action android:name="android.speech.action.RECOGNIZE_SPEECH" />
</intent>
</queries>
Package visiblility in Android 11
Note: If you get build error(not lint warning) saying queries element not allowed, make sure to update build tools version:
Image taken from https://android-developers.googleblog.com/2020/07/preparing-your-build-for-package-visibility-in-android-11.html
I know this is a common issue.
However, launching another activity whenever user clicks on the searchView (not the icon) is not working unless user submits the query.
Below are functional codes, that result whenever user submits a query, it launches another activity, however, I want to launch another activity as soon as user clicks on the searchView (expanded textfield).
Thanks in advance.
xml
<activity
android:name=".MainPage"
android:label="#string/title_activity_main_page"
android:theme="#style/AppThemeMain">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data
android:name="android.app.default_searchable"
android:value=".SearchActivity" >
</meta-data>
</activity>
<provider android:name=".MySuggestionProvider"
android:authorities="ad.aureus.apicius.MySuggestionProvider" />
<activity android:name=".SearchActivity">
<intent-filter>
<action android:name="android.intent.action.SEARCH"/>
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable"/>
</activity>
MainPage.class
#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_page, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(new ComponentName(this, SearchActivity.class)));
return true;
}
BTW, I have tried where you can write if/switch statements in onOptionsItemSelected method to identify the searchView id then use Intents. Both did not work.
onCreate method:
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);
suggestions.saveRecentQuery(query, null);
I do have this in onCreate, for the recent query suggestions, and I am not sure whether if this is the reason for my issue. I'm assuming that, because this is called initially, it suppresses the onOptionsItemSelected method's attributes? Not sure..
Here's a xml for menu
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_settings"
android:orderInCategory="100"
android:title="#string/action_settings"
app:showAsAction="never" />
<item android:id="#+id/search"
android:title="#string/title_activity_main_page"
app:showAsAction="always"
app:actionViewClass="android.support.v7.widget.SearchView"
/>
Thanks to some of the alternative methods in implementing the if length is 0 start a new activity, and setting setOnClickListener they have worked but only when I clicked on the logo which did not work when I set the icon to false.
In consideration to pskink's comment, I took a different approach that had solved my issue. It was rather a really simple approach where I got rid of the SearchView and changed that to EditText field to allow instant onClick on a single tap to another activity.
Thank you very much for the alternative thoughts and solutions for the issue. They have been a great help as I will reference them later on and that I now know which works and those that don't.
After trying ALL of the solutions in stackoverflow about this problem, I decided to ask it here.
I'm trying to implement search bar in my Action bar.
I'm using AppCompatActivity and imported android.support.v7.widget.SearchView.
For the record, I'm using PageManager and TabLayout if it has any releation.
I get java.lang.NullPointerException error in the following line:
searchView.setSearchableInfo(
searchManager.getSearchableInfo(getComponentName()));
This is my code:
search bar declration at menu_main.xml:
<item
android:id="#+id/searchPlace"
android:title="#string/search_hint"
android:actionViewClass="android.support.v7.widget.SearchView"
android:showAsAction="always"/>
searchable.xml
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="#string/app_name"
android:hint="#string/search_hint" />
AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/Theme.AppCompat.Light.NoActionBar" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.default_searchable"
android:value=".searchResultActivity" />
</activity>
<activity
android:name=".Settings"
android:label="#string/title_activity_settings" >
</activity>
<activity
android:name=".searchResultActivity"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.Light.NoActionBar">
<!-- to identify this activity as "searchable" -->
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable" />
</activity>
Search code in my MainActivity.java onCreateOptionsMenu:
// Associate searchable configuration with the SearchView
SearchManager searchManager =
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView =
(SearchView) menu.findItem(R.id.searchPlace).getActionView();
searchView.setSearchableInfo(
searchManager.getSearchableInfo(getComponentName()));
Logcat error:
Process: il.co.test.test, PID: 1642
java.lang.NullPointerException
at il.co.test.test.MainActivity.onCreateOptionsMenu(MainActivity.java:106)
at android.app.Activity.onCreatePanelMenu(Activity.java:2538)
at android.support.v4.app.FragmentActivity.onCreatePanelMenu(FragmentActivity.java:262)
at android.support.v7.internal.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:85)
at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.onCreatePanelMenu(AppCompatDelegateImplBase.java:267)
at android.support.v7.internal.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:85)
at android.support.v7.internal.app.ToolbarActionBar.populateOptionsMenu(ToolbarActionBar.java:448)
at android.support.v7.internal.app.ToolbarActionBar$1.run(ToolbarActionBar.java:65)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
UPDATE
I'm not sure, and I don't know how to check it - but I am pretty sure my getActionVIew() returns NULL.
UPDATE 2 - FIXED!
After checking some stackoverflow's about getActionView() null problem,
The 2nd answer at getActionView() of my MenuItem return null fixed my problem.
I had to use namespace app instaed of android.
Really painful!
Hope someone can find my mistake and help me fix it, since I tried many solutions for 6 hours.
Thanks in advance!
Search menu item
<item
android:id="#+id/searchPlace"
android:title="#string/search_hint"
android:actionViewClass="android.support.v7.widget.SearchView"
android:title="#string/search"
app:showAsAction="always|collapseActionView"/>
Activity code
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.your_menu, menu);
SearchView searchView = (SearchView) menu.findItem(R.id.searchPlace).getActionView();
searchView.setOnQueryTextListener(queryTextListener);
return true;
}
private OnQueryTextListener queryTextListener = new OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String query) {
//if you need this
return false;
}
#Override
public boolean onQueryTextChange(String query) {
//your code
return true;
}
};
In this this case you dont need searchable configuration, dont need strokes in manifest, dont need SearchManager and other stuff. Just declare search item in the menu and thats it.
After checking some stackoverflow's about getActionView() null problem,
The 2nd answer at getActionView() of my MenuItem return null fixed my problem.
I had to use namespace app instaed of android.
Really painful!
getActionView() is retuning null. What am i doing wrong?
I am extending Activity and using android:minSdkVersion="11" android:targetSdkVersion="19"
<item
android:id="#+id/search"
android:actionViewClass="android.widget.SearchView"
android:icon="#drawable/ic_action_search"
android:showAsAction="collapseActionView|ifRoom"
app:showAsAction="always"
android:title="#string/search"/>
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
searchItem = menu.findItem(R.id.search);
mSearchView = (SearchView) searchItem.getActionView();
mSearchView.setQueryHint("Search");
return true;
}
manifest
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable" />
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
</activity>
I saw that you have app:showAsAction="always" the app namespace means that you are using Appcompat v7 library ...
Appcompat library has it owns method for menu items as static method in MenuCompat/MenuItemCompat classes (and you should use 'em like instead menu.methodXXX() use MenuCompat.methodXXX(menu) )
Now, to define a actionViewClass(and others attributes added in api newer then 11) in menu you should use the app namespace for this instead android namespace
so android:actionViewClass should become app:actionViewClass
in the code you should use MenuItemCompat.getActionView(searchItem) instead searchItem.getActionView()
remeber to add namespace app in root element of menu xml file like xmlns:app ="http://schemas.android.com/apk/res-auto"
also small hint (as you are using 11 as min sdk your code should works fine but ...) replace android.widget.SearchView to android.support.v7.widget.SearchView as it(standard SearchView) not works in the same way on different API versions from 11 to newest one(also you will get method not found if you use methods added in API > 11 to SearchView on devce with API 11)
I'm working around with a searchable action bar. And I gotta a problem that the action bar doesn't react with the searchable activity. THAT IS, I enter something in the action bar's searchable textedit then clicked the submit but nothing happened. The debug tracking shows that the code in my searchresultactivity is never executed. So I'm wondering if there's something wrong in searchable configuration. Well this time I think I've explained the problem clearly and I don't expect any negative votes without any words even spits!
I followed the instruction of developer's document beginning with the manifest.xml, the meta-data is added in the searchresult activity:
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".GermanDictionaryActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SearchResultsActivity">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data android:name="android.app.searchable"
android:resource="#xml/searchable" />
</activity>
</application>
then I initialized the searchview with my menu:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.srhbar, menu);
// Get the SearchView and set the searchable configuration
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
mSrhView = (SearchView) menu.findItem(R.id.search).getActionView();
mSrhView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
mSrhView.setSubmitButtonEnabled(true);
return true;
}
And the searchable item in menu:
<item android:id="#+id/search"
android:title="#string/srh_title"
android:showAsAction="collapseActionView|ifRoom"
android:actionViewClass="android.widget.SearchView" />
Any answer related is appreciated!
I solved the problem by changing this line:
searchView.setSearchableInfo(searchManager.getSearchableInfo(new ComponentName(getApplicationContext(), SearchResultsActivity.class)));