My activity has a menu which includes a SearchView, and I'm setting the SearchView visibility programmatically. I'm using savedInstanceState to preserve the Visibility value eg between rotations, but this aspect is not working: in the scenario where the SearchView visibility is GONE before rotation, the SearchView icon is showing after rotation.
If I debug and evaluate mSearchView.getVisibility() after picking up its value from savedInstanceState, it appears to be correctly set to 8.
There are lines in my code which setVisibility(View.VISIBLE), but none of them are hit between the value from savedInstanceState being set, and the rotated layout appearing to the user.
Layout:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- "Mark Favorite", should appear as action button if possible -->
<item android:id="#+id/action_search"
android:title="#string/action_search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom"/>
Activity (onSaveInstanceState):
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
switch (mSearchView.getVisibility()){
case View.VISIBLE:
outState.putInt("SearchViewVisibility",View.VISIBLE);
case View.GONE:
outState.putInt("SearchViewVisibility",View.GONE);
};
}
Activity (Menu setup):
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
//setup SearchView and callbacks
final MenuItem searchItem = menu.findItem(R.id.action_search);
mSearchView = (SearchView) searchItem.getActionView();
if(mSavedInstanceState != null){
switch (mSavedInstanceState.getInt("SearchViewVisibility")){
case View.VISIBLE:
mSearchView.setVisibility(View.VISIBLE);
case View.INVISIBLE:
mSearchView.setVisibility(View.INVISIBLE);
case View.GONE:
mSearchView.setVisibility(View.GONE);
}
}
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
#Override
public boolean onQueryTextSubmit(String query) {
SetFragmentAndFilter(query);
return true;
}
#Override
public boolean onQueryTextChange(String query) {
// check whether this change is clearing all text from the search
if(query.isEmpty()){
// close the searchView
mSearchView.post(new Runnable(){
#Override
public void run(){
mSearchView.clearFocus();
}
});
mSearchView.setIconified(true);
}
//have the list match the new query text
SetFragmentAndFilter(query);
return true;
}
});
return true;
}
Would really appreciate any thoughts!
You should use setVisible method to set the visibility of a menu item.
Change your code to
// Add this property
MenuItem mSearchMenuItem;
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("isVisible", mSearchMenuItem.isVisible());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
//setup SearchView and callbacks
mSearchMenuItem = menu.findItem(R.id.action_search);
if (mSavedInstanceState != null) {
boolean isVisible = mSavedInstanceState.getBoolean("isVisible", true);
mSearchMenuItem.setVisible(isVisible);
}
mSearchView = (SearchView) mSearchMenuItem.getActionView();
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String query) {
// check whether this change is clearing all text from the search
if (query.isEmpty()) {
// close the searchView
mSearchView.post(new Runnable() {
#Override
public void run() {
mSearchView.clearFocus();
}
});
mSearchView.setIconified(true);
}
return true;
}
});
return true;
}
Related
I created a resource menu file i did all the xml work and also added the
` public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.option_menu, menu);
MenuItem item=menu.findItem(R.id.Search);
SearchView searchView=(SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
return false;
}
});
return true;
}`
Now how do I connect my data of notes which is created by user. And once he tries to use the search bar he should be able search among words or notes he has created.
You have to write your search query listener in your
onOptionsItemSelected() instead of OnCreateOptionsMenu like:
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.search_item:
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
//your logic of search goes here...
searchView.clearFocus(); //disables the keyboard show up on rotation.
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
return true;
}
});
return true;
}
return super.onOptionsItemSelected(item);
}
I have a very simple question. I have implemented searchview in my menu. So the activity starts with expanded searchview. And now when I press back button, the searchview first collapse and goes back to previous activity.
Here's my code
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.menu_search, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
searchItem.expandActionView();
SearchView mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
mSearchView.setQueryHint(getString(R.string.search_hint));
mSearchView.setIconifiedByDefault(false);
mSearchView.setFocusable(true);
mSearchView.setIconified(false);
mSearchView.requestFocus();
mSearchView.setGravity(Gravity.END);
mSearchView.setTextDirection(View.TEXT_DIRECTION_RTL);
//mSearchView.setLayoutParams(new Toolbar.LayoutParams(Gravity.END));
//String searchQuery = getIntent().getStringExtra("SEARCH");
//SearchActivity.this.myAdapter.filter(searchQuery);
TextView searchText = mSearchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
//searchText.setText(searchQuery);
Typeface customFont = Typeface.createFromAsset(this.getAssets(), "fonts/font.ttf");
searchText.setTypeface(customFont);
try {
ThaanaUtils.thaanafyTextViewSubclass(searchText, "fonts/faruma.ttf");
}catch (IOException e){
e.printStackTrace();
}
searchText.addTextChangedListener(new ThaanaTextWatcher());
View xIcon = ((View) mSearchView.findViewById(R.id.search_plate));
xIcon.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
SearchActivity.this.myAdapter.filter(newText);
return true;
}
});
MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
onBackPressed();
return true;
}
});
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_favorites) {
//Intent newActivity = new Intent(SearchActivity.this,FavoritesActivity.class);
//startActivity(newActivity);
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed()
{
finish();
}
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
But I don't want to show searchview collapsing when pressed back button. I want to go back to previous activity without collapsing searchview.
How can I achieve that?
Any help is appreciated.
Override the onBackPressed() method in your activity and then put your activity redirection code inside the method. This will solve your problem. Happy coding!
#Override
public void onBackPressed() {
// enter your activity redirection code here.
}
If you didn't call finish() on your previous activity, then just call finish() inside the onBackPressed method. This will destroy the current activity(search activity) and will load previous one. Else you need to go through the usual way by declaring an intent.
I have a tabbed activity with two tabs, and when I am in the second one I want to have a search action be shown in the actionbar. I do not want it to show in the first tab, only the second.
This is what I have for my LaunchActivity.java
public class LaunchActivity extends ActionBarActivity {
ViewPager pager;
int Numboftabs = 2;
boolean searchDisabled = false;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
...
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if (position == 0) {
searchDisabled = true;
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
...
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_launch, menu);
return super.onCreateOptionsMenu(
}
...
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem search = menu.findItem(R.id.action_search);
if(searchDisabled) {
search.setEnabled(false);
}
super.onPrepareOptionsMenu(menu);
return true;
}
}
menu_launch.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=".LaunchActivity">
<item android:id="#+id/action_search"
android:title="#string/action_search"
android:icon="#drawable/ic_action_search"
app:showAsAction="ifRoom" />
<item android:id="#+id/action_settings"
android:title="#string/action_settings"
android:orderInCategory="100"
app:showAsAction="never" />
</menu>
Does anyone know why this is not working? The search action shows up but doesn't hide when on the first tab.
Approach:
You can solve this by adding a class variable for the MenuItem.
MenuItem search;
Then in onPrepareOptionsMenu you only initialize it:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
search = menu.findItem(R.id.action_search);
super.onPrepareOptionsMenu(menu);
return true;
}
Then in your onPageChangeListener you do this to show/hide the search item:
#Override
public void onPageSelected(int position) {
if (position == 0) {
search.setEnabled(false);
search.setVisible(false);
} else {
search.setEnabled(true);
search.setVisible(true);
}
}
That should achieve what you want to do.
Approach:
Alternative better solution would be to set up the options menu in the fragment:
Add hasOptionsMenu(true) to your Fragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
And set the visibility in onCreateOptionsMenu (also in the fragment!):
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem search = menu.findItem(R.id.action_search);
search.setEnabled(false);
search.setVisible(false);
super.onCreateOptionsMenu(menu, inflater);
}
The Android SearchView icon won't show up in the ActionBar, instead, if there is room, the word 'SEARCH' will be displayed instead.
How we're using it:
public static MenuItem addSearchItem(Menu menu, SearchView searchView) {
MenuItem item = menu.add(Menu.NONE, R.id.search_item, Menu.NONE, R.string.search_label);
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
MenuItemCompat.setActionView(item, searchView);
...
}
Called like so:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
if (itemsLoaded) {
inflater.inflate(R.menu.new_episodes, menu);
final SearchView sv = new SearchView(getActivity());
MenuItemUtils.addSearchItem(menu, sv);
If, however, we just use SHOW_AS_ACTION_IF_ROOM, then we'll get the icon, but the SearchView won't work if the search was collapsed in to the menu.
Any ideas about why this might be?
UPDATE
This behavior occurs even if the SearchView is defined within the menu xml. It seems to only behave properly if you don't specify 'collapseActionView'.
The layout:
<item android:id="#+id/action_search"
android:icon="?attr/searchIcon"
android:title="#string/search_label"
custom:showAsAction="ifRoom|collapseActionView"
custom:actionViewClass="android.support.v7.widget.SearchView"/>
The creation code:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
if (itemsLoaded) {
inflater.inflate(R.menu.new_episodes, menu);
final MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
sv.setQueryHint(getString(R.string.search_hint));
SearchViewCompat.setOnQueryTextListener(sv, new SearchViewCompat.OnQueryTextListenerCompat() {
#Override
public boolean onQueryTextSubmit(String s) {
sv.clearFocus();
((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s));
return true;
}
#Override
public boolean onQueryTextChange(String s) {
return false;
}
});
I added Search menu item to filter my list. Everything is working fine with filtering and reset filter.
But I cannot find a way to reset the filter when user click on back button. Actually when user add some text in search field, the first back click will hide the keyboard, and the second click will collapse search field and remove my search text ... but the list still filtered.
What should I do to reset the list?
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search_menu, menu);
searchMenuItem = menu.findItem(R.id.action_search);
SearchView mSearchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
if (mSearchView != null) {
mSearchView.setIconifiedByDefault(true);
mSearchView.setOnQueryTextListener(this);
}
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onQueryTextChange(String s) {
refreshSearch(s);
return false;
}
private void refreshSearch(String s) {
FragmentManager fm = getSupportFragmentManager();
MyListFragment listFragment = (MyListFragment)fm.getFragments().get(0);
MyArrayAdapter arrayAdapter = (MyArrayAdapter)listFragment.getListAdapter();
arrayAdapter.getFilter().filter(s);
}
Edit my question by adding some extra code, that may help to know the reason
#Override
public boolean onQueryTextSubmit(String s) {
hideKeyboard();
return false;
}
#Override
public boolean onQueryTextChange(String s) {
refreshSearch(s);
return false;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_search:
return true;
default:
return false; //return super.onOptionsItemSelected(item);
}
}
I solve the problem by doing this:
searchMenuItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
refreshSearch("");
return true;
}
});
You will need to override onBackPressed() in your activity:
#Override
public void onBackPressed() {
if (mSearchView != null && !mSearchView.isIconified()) {
mSearchView.setIconified(true);
} else {
super.onBackPressed();
}
}
searchView should be global variables then you need to do in onQueryTextSubmit method
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem searchMenuItem = menu.findItem(R.id.app_bar_search);
if (searchMenuItem != null) {
searchView = (SearchView) searchMenuItem.getActionView();
searchView.setFocusable(true);
searchView.setQueryHint("Ara...");
searchView.requestFocusFromTouch();
}
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
searchView.clearFocus();
return false;
}
#Override
public boolean onQueryTextChange(String s) {
adapter.getFilter().filter(s);
return true;
}
});
return super.onCreateOptionsMenu(menu);
}
then onBackPressed method
#Override
public void onBackPressed() {
if (!searchView.isIconified() && searchView != null) {
searchView.setIconified(true);
searchView.onActionViewCollapsed();
} else {
super.onBackPressed();
}
}
after a few hours attempt I figured it out.
I'm using support library widgets.
setOnCloseListener for SearchView no longer works, the way you should do it is to use onQueryTextChange in the below code
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
try {
listView.setAdapter(new MyAdapter();
listView.setVisibility(View.VISIBLE);
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
#Override
public boolean onQueryTextChange(String s) {
listView.setVisibility(View.GONE);
return false;
}
});
onQueryTextChange is responsible for changes made to your search edittext input. so if you noticed, by default when you press SearchView's back button it clears the text you inputed. well back button will trigger onQueryTextChange cause you changed the text, so if you set visibily of your listview to GONE the problem is fixed
#Override
public boolean onQueryTextChange(String s) {
listView.setVisibility(View.GONE);
return false;
}