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
Related
My toolbar contains search icon and refresh icon,when i click on search icon then search view inflate from onCreateOptionMenu() but the refresh icon does not get hide.If i hide refresh icon in onMenuItemActionExpand() then on back press of search view back icon both menu items search and refresh gets hide and default setting icon gets visible.Below is the code which i have implemented.Please help me!!!
MenuItem.java
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
item_search = menu.findItem(R.id.action_search);
item_refresh = menu.findItem(R.id.action_refresh);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item_search);
searchView.setOnSearchClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// hide action item
if (menu != null) {
menu.findItem(R.id.action_refresh).setVisible(false);
}
}
});
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
#Override
public boolean onClose() {
// re-show the action button
if (menu != null) {
menu.findItem(R.id.action_refresh).setVisible(true);
}
return false;
}
});
Well you could imitate that yourself by hiding all the other items when the SearchView is expanded:
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
final MenuItem searchItem = menu.findItem(R.id.search);
SearchView searchView = (android.widget.SearchView) searchItem.getActionView();
// Detect SearchView icon clicks
searchView.setOnSearchClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setItemsVisibility(menu, searchItem, false);
}
});
// Detect SearchView close
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
#Override
public boolean onClose() {
setItemsVisibility(menu, searchItem, true);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
private void setItemsVisibility(Menu menu, MenuItem exception, boolean visible) {
for (int i=0; i<menu.size(); ++i) {
MenuItem item = menu.getItem(i);
if (item != exception) item.setVisible(visible);
}
}
MenuItem action_search;
MenuItem action_refresh;
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
action_search = menu.findItem(R.id. action_search);
action_refresh = menu.findItem(R.id. action_refresh);
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
item_search = menu.findItem(R.id.action_search);
item_refresh = menu.findItem(R.id.action_refresh);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item_search);
searchView.setOnSearchClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// hide action item
if (action_refresh != null) {
action_refresh.setVisible(false);
invalidateOptionsMenu();
}
}
});
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
#Override
public boolean onClose() {
// re-show the action button
if (action_search != null) {
action_search.setVisible(true);
}
if (action_refresh != null) {
action_refresh.setVisible(true);
}
invalidateOptionsMenu();
return false;
}
});
It seems that it's a bug from android, you can use the solution here!
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 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()
}
I have a Action Bar with Search View and I have a Fragment set has Option Menu. In my MainActivity SearchView work fine but in my Fragment (I need handle event OptionMenuItem to do something), after setHasOptionMenu then SearchView can't work. Here is my code
Option Menu in MainActivity
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
// Create SearchView
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setSubmitButtonEnabled(false);
searchView.setQueryHint("Search Here");
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
if(s.length() > 0){
Tab1.listadaptor.getFilter().filter(s);
Tab2.listadaptor.getFilter().filter(s);
}else{
pager.setAdapter(adapter);
if(SlidingTabLayout.userState){
pager.setCurrentItem(0);
}else{
pager.setCurrentItem(1);
}
}
return true;
}
};
searchView.setOnQueryTextListener(queryTextListener);
return super.onCreateOptionsMenu(menu);
}
OptionMenuItem in Fragment
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
//Do Something
}
return super.onOptionsItemSelected(item);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
This works!! is in Kotlin, if you need more help, say me.
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
val inflater = menuInflater
inflater.inflate(R.menu.search_activity_menu, menu)
searchView = menu.findItem(R.id.btn_search_station).actionView as
SearchView
return true
}
private fun setErrorOnSearchView(searchView: SearchView, errorMessage: String) {
val id = searchView.context
.resources
.getIdentifier("android:id/search_src_text", null, null)
val editText = searchView.find<EditText>(id)
editText.error = errorMessage
}
private fun cleanErrorOnSearchView(searchView: SearchView) {
val id = searchView.context
.resources
.getIdentifier("android:id/search_src_text", null, null)
val editText = searchView.find<EditText>(id)
editText.error = null
}
I add ActionBarCompat to my project based on this tutorial. But I get confused on how to give event for user input when search button is clicked.
public class MainActivity extends ActionBarActivity {
ActionBar ab;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ab = getSupportActionBar();
ab.setTitle("Test");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
return super.onCreateOptionsMenu(menu);
}
}
And I found out that to get the input from user is with implements SearchView.OnQueryTextListener, as I found from here. Don't forget to add this listener to the SearchView at onCreateOptionsMenu(Menu menu) method, likt this :
#Override
public boolean onCreateOptionsMenu(Menu menu) {
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
mSearchView.setOnQueryTextListener(this);
return true;
}