I have implemented SearchView inside one of a Fragment of Tablayout. It is working fine(show/hide) when switching between tablayout fragments.
My issue is that I have a HomeActivity in which I have implemented NavigationDrawer in one of a Fragment I have added TabLayout and in one of TabLayout Fragment I have added SearchView. Issue occurs when I am switching from Fragment which has a SearchView to Fragment from NavDrawer.
Searchview remains up there in other fragments too and when I switch back to that fragment in which I have added searchView then that fragment add one more searchview over Toolbar.
Here's my code from Fragment which as a SearchView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
setHasOptionsMenu(true);
....
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_search, menu);
LogUtils.LOGI("menu added", "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()));
final MenuItem item = menu.findItem(R.id.search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String query) {
LogUtils.LOGI("Search filter", query);
final ArrayList<EventModel> filteredModelList = filter(allEventseventsArrayList, query);
allEventsListAdapter.animateTo(filteredModelList);
eventbriteListRecyclerView.scrollToPosition(0);
return true;
}
});
searchView.setOnSearchClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LogUtils.LOGI("Search", "Search Expands");
titleIconImageView.setVisibility(View.GONE);
}
});
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
#Override
public boolean onClose() {
LogUtils.LOGI("Search", "Search Collapse");
titleIconImageView.setVisibility(View.VISIBLE);
return false;
}
});
MenuItemCompat.setOnActionExpandListener(item,
new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem menuItem) {
// Return true to allow the action view to expand
titleIconImageView.setVisibility(View.GONE);
LogUtils.LOGI("Menu", "Menu Expands");
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem menuItem) {
// When the action view is collapsed, reset the query
LogUtils.LOGI("Menu", "Menu Collapse");
titleIconImageView.setVisibility(View.VISIBLE);
// Return true to allow the action view to collapse
return true;
}
});
super.onCreateOptionsMenu(menu, inflater);
}
Fragment code in which I don't want SearchView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
setHasOptionsMenu(false);
....
}
I haven't added any code related to menu in activity.
First run Image with searchView
Image after switching to different fragment from navMenu
Image again switching to fragment which has menu
It's a bit hacky but I solved it by setting setHasOptionsMenu to true and clearing the Menu in onCreateOptionsMenu via
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater){
menu.clear()
}
Related
Hi i am trying to add "search" functionality to my multiple tabs fragment. it is working fine with one tab, i am able to search and filter data no problem. So i use the same code for my other tabs, however, now the action bar show two search icon instead of one. I tried many different ways by hiding the searchview during detach/ attach action when switching tab, but still two search icons still pop up. One of the search icon will work for my current tab, and the other does not.
here is my code:
upcoming_event_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_upcoming_event_search"
android:title="search event"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
</menu>
past_event_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_past_event_search"
android:title="search event"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
</menu>
fragment 1:
public class EventTabUpcoming extends Fragment implements SearchView.OnQueryTextListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.event_tab_upcoming, container, false);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.listUpcomingEvent);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(sectionAdapter);
setHasOptionsMenu(true);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.upcoming_event_menu, menu);
MenuItem item = menu.findItem(R.id.action_upcoming_event_search);
searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(this);
}
#Override
public boolean onQueryTextChange(String searchText) {
Log.d(logTag, "EventTabUpcoming -> onQueryTextChange w/ searchText: " + searchText);
for (Section section : sectionAdapter.getCopyOfSectionsMap().values()) {
if (section instanceof FilterableEventSection) {
((FilterableEventSection) section).filter(searchText);
}
}
sectionAdapter.notifyDataSetChanged();
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public void onDetach() {
super.onDetach();
Log.d(logTag, "onDetach is called");
if (searchView != null) {
searchView.clearFocus();
searchView.setVisibility(View.GONE);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d(logTag, "onAttach is called");
if (searchView != null) {
searchView.setVisibility(View.VISIBLE);
}
}
Fragment 2 is a cloned from Fragment 1 except the view is now:
final View view = inflater.inflate(R.layout.event_tab_past, container, false);
and menu is
inflater.inflate(R.menu.past_event_menu, menu);
Please let me know how should i correct this problem.
Here is my solution:
Instead of inflate the menu in both tab's activities, i inflate the menu in the viewpager activity only, and in each tab fragment's onCreateOptionMenu, i get the searchview and setQueryTextListener.
ViewPager activity:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
/**
* Inflate menu with searchview item
*/
inflater.inflate(R.menu.event_menu, menu);
}
Tab 1
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
# get the searchview and set listener
MenuItem item = menu.findItem(R.id.action_event_search);
searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(this);
}
Tab 2
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
# get the searchview and set listener
MenuItem item = menu.findItem(R.id.action_event_search);
searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(this);
}
I'm inflating a menu with menu items in Activity's toolbar and overwriting the options in fragment.But the new menu items are not showing up.
Activity
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.encounter_tabacivity_menu, menu);
return true;
}
Fragment
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.clear(); //remove all items
getActivity().getMenuInflater().inflate(R.menu.encounter_frag_problemlist_menu, menu);
}
#Override
public void onResume() {
super.onResume();
getActivity().invalidateOptionsMenu();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
view = inflater.inflate(R.layout.fragment_problem_list, container, false);
init();
return view;
}
You might not have set your toolbar as your actionbar. To view your menu in your actionbar declare your toolbar as actionbar as follows
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
You need setHasOptionMenu(true) in your fragment.
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
You must override this in fragment
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Add your menu entries here
super.onCreateOptionsMenu(menu, inflater);
}
Try this code in your Fragment :
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_record ) {
// startActivity(new Intent(getActivity(),RecordingActivity.class));
startActivity(new Intent(getActivity(),RecordingTestActivity.class));
getActivity().finish();
return true;
}
if (id == R.id.action_search ) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Inflate the menu; this adds items to the action bar if it is present.
inflater.inflate(R.menu.recording, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
if (searchItem != null) {
searchView = (SearchView) searchItem.getActionView();
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
queryTextListener = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) {
Log.i("onQueryTextChange", newText);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
Log.i("onQueryTextSubmit", query);
return true;
}
};
searchView.setOnQueryTextListener(queryTextListener);
} super.onCreateOptionsMenu(menu, inflater);
}
I have been working on an application where I have 6 tabs each of them having a listview in it. I want to filter the listview in each fragment depending upon the text in SearchView which is part of MainActivity. I have a working code for filtering records written in Listview adapter.
The issue is, whenever I want to search something using searchview, the current fragment listview gets filtered but as soon as I move from one fragment to other, the searchview gets reset and the text written in gets clear. That's why I don't get anything in other fragment to search for.
I have following code logic used
In MainActivity :
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_order, menu);
if(searchView == null)
searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
return false;
}
In each of the fragment I have :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_items, container, false);
setHasOptionsMenu(true);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Auto-generated method stub
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
super.onPrepareOptionsMenu(menu);
android.view.MenuItem item = menu.findItem(R.id.action_search);
SearchView sv = new SearchView(((OrderActivity) getActivity()).getSupportActionBar().getThemedContext());
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
MenuItemCompat.setActionView(item, sv);
sv.setOnQueryTextListener(this);
sv.setIconifiedByDefault(false);
}
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
if (listAdapter != null) {
listAdapter.filter(newText);
}
return true;
}
Please suggest for solution on above issue.
Thanks in advance.
I have a MainActivity on which Fragment is placed. Fragment having SearchView ( app:actionViewClass="android.support.v7.widget.SearchView"
) and MainActivity has a SearchView icon in Toolbar.
I want to hide/show the icon from Toolbar when Searchview of Fragment is Show/Hide (like Flipkart app). It is working properly when one of Hiding or Showing method is used, But when i use both of them then it gives error like
java.lang.NullPointerException: Attempt to invoke interface method 'android.view.MenuItem android.view.Menu.findItem(int)' on a null object reference
My code snippets are..
MainActivity
#Override
public boolean onCreateOptionsMenu(final Menu menu)
{
_menu = menu;
final Menu m= menu;
getMenuInflater().inflate(R.menu.menus, menu);
final MenuItem searchItem = menu.findItem(R.id.action_search);
SearchManager searchManager = (SearchManager) DrawerActivity.this.getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = null;
if (searchItem != null) {
searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
}
searchView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
m.performIdentifierAction(searchItem.getItemId(), 0);
}
});
searchItem.setVisible(false);
return super.onCreateOptionsMenu(menu);
}
public void show_search(){
final MenuItem searchItem = _menu.findItem(R.id.action_search);
searchItem.setVisible(true);
// invalidateOptionsMenu(); //if i use this it not show the icon.
}
public void hide_search() {
final MenuItem sitem = _menu.findItem(R.id.action_search); // gives NullPointerException in this line.
sitem.setVisible(false);
invalidateOptionsMenu();
}
Fragment code :
public class Fragment1 extends Fragment
{
scroll = (ScrollView) v.findViewById(R.id.scroll_view);
// Total Height of layout which contains searchview
ViewTreeObserver vas = lin.getViewTreeObserver();
vas.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
ViewGroup.MarginLayoutParams vlp = (ViewGroup.MarginLayoutParams) lin.getLayoutParams();
search_size = lin.getMeasuredHeight() + vlp.topMargin;
lin.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
scroll.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
float y = scroll.getScrollY();
DrawerActivity d = (DrawerActivity) getActivity();
if (y >= search_size)
{
d.show_search();
}
else
{
d.hide_search();
}
}
});
}
Good morning, why do not you inflates other menu.xml the fragment?
For example .. in your fragment insert
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setHasOptionsMenu(true);
}
private Menu mMenu;
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_fragment, menu);
mMenu = menu;
MenuItem searchViewItem = menu.findItem(R.id.search);
final android.support.v7.widget.SearchView searchView =
(android.support.v7.widget.SearchView) MenuItemCompat.getActionView(searchViewItem);
super.onCreateOptionsMenu(menu, inflater);
}
I have helped
When you enter in searchview mode with the action bar, the home button is changed to the manifest android:icon drawable for some reason. Is there a way to keep it unchanged or to change it back to the android:logo drawable?
Here's what I'm doing:
#Override
public void onCreateOptionsMenu(final Menu menu, MenuInflater inflater)
{
getSherlockActivity().getSupportMenuInflater().inflate(R.menu.places_menu, menu);
SearchManager searchManager = (SearchManager) getSherlockActivity().getSystemService(Context.SEARCH_SERVICE);
final SearchView searchView = (SearchView) menu.findItem(R.id.item_menu_search).getActionView();
SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener()
{
public boolean onQueryTextChange(String newText)
{
// this is your adapter that will be filtered
mAdapter.getFilter().filter(newText);
return true;
}
public boolean onQueryTextSubmit(String query)
{
// this is your adapter that will be filtered
mAdapter.getFilter().filter(query);
return true;
}
};
if (null != searchView )
{
searchView.setSearchableInfo(searchManager.getSearchableInfo(getSherlockActivity().getComponentName()));
searchView.setIconifiedByDefault(false);
searchView.setOnQueryTextListener(queryTextListener);
// CLOSE SEARCH WHEN SOFT KEYBOARD DISSMISSES
searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean queryTextFocused) {
if(!queryTextFocused) {
menu.findItem(R.id.item_menu_search).collapseActionView();
searchView.setQuery("", false);
}
}
});
}
super.onCreateOptionsMenu(menu, inflater);
}
It seems to be possible by calling setIcon() with the logo.
ActionBar actionBar = getActionBar();
actionBar.setLogo(R.drawable.ab_logo);
actionBar.setIcon(R.drawable.ab_logo);