Android Searchview in toolbar not working in older versions - java

My toolbar has a searchView inside and both ate not registering any touch events on android 4.3 (in fact the event goes to the view below them). It should register homeAsUp, the searchView field (requestFocus) and X button to clear the field. For now what I am thinking is attaching listeners to these but is there a better way.
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem menuItem = menu.findItem(R.id.app_bar_search);
SearchView searchView = new SearchView(this);
searchView.setIconifiedByDefault(false);
searchView.setIconified(false);
searchView.requestFocus();
searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setQueryHint(getString(R.string.search));
ImageView searchViewIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_mag_icon);
ViewGroup linearLayoutSearchView =(ViewGroup) searchViewIcon.getParent();
linearLayoutSearchView.removeView(searchViewIcon);
menuItem.setActionView(searchView);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) { return false; }
#Override
public boolean onQueryTextChange(String newText) {
presenter.queryChanged(newText);
return true;
}
});
return true;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search, menu);
return true;
}
menu/search.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/app_bar_search"
app:actionViewClass="android.support.v7.widget.SearchView"
android:icon="#drawable/ic_search_white_24dp"
android:title="#string/search"
app:showAsAction="always" />
</menu>
It works fine in newer versions though (don't know which one is the border between working/not working).
EDIT:
Attaching a listener to the searchview doesn't work either.

don't make new instance of SearchView fetch it from the menuItem:
replace this line
SearchView searchView = new SearchView(this);
with
SearchView searchView = (SearchView) menuItem .getActionView();
and remove following line:
menuItem.setActionView(searchView);
following code is working fine for me:
#Override
public boolean onCreateOptionsMenu( Menu menu) {
getMenuInflater().inflate( R.menu.menu_main, menu);
MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
final SearchView searchView = (SearchView) myActionMenuItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
if (TextUtils.isEmpty(newText)) {
adapter.filter("");
listView.clearTextFilter();
} else {
adapter.filter(newText);
}
return true;
}
});
return true;
}

what about doing it using EditText ... it is going to run for all versions.
1- In YourActivity.xml remove android.support.design.widget.AppBarLayout attribute then add
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="#style/AppTheme.PopupOverlay" >
<EditText
android:id="#+id/search_edit_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="24dp"
android:backgroundTint="[TINT_COLOR]"
android:hint="Search"
android:inputType="[INPUT TYPE]"
android:textColorHint="[HINT_COLOR]"
android:layout_marginEnd="16dp"/>
</android.support.v7.widget.Toolbar>
2-In YourActivity.java code add this listener on search edittext
private TextWatcher searchTextWatcher =
new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
presenter.queryChanged(charSequence.toString());
}
#Override
public void afterTextChanged(Editable editable) {
}
};

Related

Can't set visibility on a SearchView with savedInstanceState

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;
}

Can't create a menu

I'm new to android trying to create a popup menu, but my app is crashing when I'm calling createMenu() in my activity which is extending to AppCompatActivity can anybody help me about the issue?
#SuppressLint("RestrictedApi")
public void createMenu() {
MenuBuilder menuBuilder = new MenuBuilder(this);
MenuInflater inflater = new MenuInflater(this);
inflater.inflate(R.menu.popup_menu, menuBuilder);
MenuPopupHelper optionsMenu = new MenuPopupHelper(this, menuBuilder);
optionsMenu.setForceShowIcon(true);
menuBuilder.setCallback(new MenuBuilder.Callback() {
#Override
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
switch (item.getItemId()) {
case R.id.one:
return true;
default:
return false;
}
}
#Override
public void onMenuModeChange(MenuBuilder menu) {
}
});
optionsMenu.show();
}
In my XML
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/one"
android:icon="#drawable/ic_one"
android:title="One"
android:orderInCategory="0"/>
</menu>
calling it
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.option) {
createMenu();
}
}
getting error
java.lang.IllegalStateException: MenuPopupHelper cannot be used without an anchor
Add this to menu file android:showAsAction="always"
Use this menu file
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/one"
android:icon="#drawable/ic_one"
android:title="One"
android:showAsAction="always"
android:orderInCategory="0"/>
The issue is the null action view. So showing the menuitem as action view solves the issue
And call this using this code
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.option) {
createMenu(item.getActionView());
}
}
And change your createMenu() to
#SuppressLint("RestrictedApi")
public void createMenu(View v) {
PopupMenu popup = new PopupMenu(getActivity(), v);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.popup_menu, popup.getMenu());
popup.show();
}

How To Search In Listview From Toolbar In Fragment

I was using this code to search from my MainActivity Toolbar in a ListView:
SearchView searchView;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate( R.menu.main, menu);
MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
searchView = (SearchView) myActionMenuItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
adapter.getFilter().filter(s);
return false;
}
});
return true;
}
But now I moved my Listview to a fragment, how can I pass the adapter from the fragment to the main activity? How can I update the typing?
Is there any better way then passing the adapter?
Thank you in advance
A better approach can be using EventBus. It's really helpful in a scenario like this in which we have to pass certain data from an Activity to a Fragment.
For using EventBus, you need to define a POJO class, somewhat like this:
class SearchQueryEvent {
String query;
public SearchQueryEvent(String query) {
this.query=query;
}
public String getQuery() {
return query;
}
}
Now, your code should be modified like this:
MainActivity.java
SearchView searchView;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate( R.menu.main, menu);
MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
searchView = (SearchView) myActionMenuItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
EventBus.getDefault().post(new SearchQueryEvent(s));
return false;
}
});
return true;
}
YourFragment.java
#Override
public void onResume() {
super.onResume();
EventBus.getDefault().register(this);
}
#Override
public void onPause() {
EventBus.getDefault().unregister(this);
super.onPause();
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onSearchQuery(SearchQueryEvent event) {
String query=event.getQuery();
adapter.getFilter().filter(query);
}
Try This code,
activity_main.xml :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#009688" />
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment"
android:name="ru.lemmaproj.toolbar_search.MainActivityFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/fragment_main" />
</LinearLayout>
fragment_main.xml :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivityFragment">
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
search_layout.xml :
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cursorVisible="true"
android:imeOptions="actionDone"
android:inputType="text" />
MainActivity.java :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
}
MainActivityFragment.java :
public class MainActivityFragment extends Fragment {
private final String[] items = new String[] { "Android", "iOS", "Windows Phone",
"Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2" };
private ListView listView;
private ArrayAdapter<String> adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
listView = (ListView) view.findViewById(R.id.list);
adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, items);
listView.setAdapter(adapter);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_fragment, menu);
MenuItem searchItem = menu.findItem(R.id.menu_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
if (searchView != null) {
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return true;
}
});
}
}
}
1-> Create a static method in fragment
public static void doSearch(String query){
yourAdapter.filter(query);
}
2-> Call this method from activity on onQueryTextChange method and pass the query you want to search
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.home, menu);
MenuItem myActionMenuItem = menu.findItem(R.id.action_search);
searchViewShop = (SearchView) myActionMenuItem.getActionView();
searchViewShop.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
YourFragment.doSearch(newText);
return true;
}
});
return true;
}

Menu bar in android studio project

I'm new to Android Studio and I'm having many problems doing a menubar. I have searched for many solutions but they weren't going right.
I tried this but I don't know what to do next:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu (Menu menu) {
super.onCreateOptionsMenu(menu);
//Inflate the menu; this adds item to the action
//bar if its present
getMenuInflater().inflate(R.menu.my_context_menu, menu);
String title = "Item Three";
int groupId = Menu.NONE;
int itemID = MENU_ITEM;
int order = 103;
menu.add(groupId, itemId, order, title);
return true;
}
First create a main_menu.xml file in your menu rescource folder (or any other...) :
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/one"
android:title="Button 1"/>
<item android:id="#+id/two"
android:title="Button 2"/>
</menu>
Then
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.one:
// do something
return true;
case R.id.two:
//do something
return true;
default:
return super.onOptionsItemSelected(item);
}
}

Enable and disable search action in a tabbed activity

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);
}

Categories

Resources