Hi I want to put a search bar into my navigation drawer which I want to filter the items from Fragment.
I have Fragement under the nav drawer in the ss.
here is a bit of code.
<item android:id="#+id/action_search"
android:title="Search"
app:showAsAction="collapseActionView|ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView"
/>
Menu in the MainActivity
if (id == R.id.action_search) {
final MenuItem searchItem = item.findItem(R.id.action_search);
final SearchView searchView = (SearchView)
MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(this);
}
here is the some chunk of code I got for search
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
newText = newText.toLowerCase();
List<Example> newlist = new ArrayList<>();
for(Example example: newlist){
String name = example.getTitle().getRendered().toLowerCase();
if (name.contains(newText)) newlist.add(example);
}
adapter.setFilter(newlist);
return true;
}
}
Now how will I code the nav drawer in mainActivity or in fragment to make it possible that I can search in the fragment from nav drawer. Thanks.
Make a SearchManager class which fetches your data everytime onQueryTextChange is called. Then make a custom listener in SearchManager and implement it in your fragment and refresh it everytime your listener is called.
I got something like this in my MainActivity
SearchManager searchManager = SearchManager.sharedInstance();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
searchManager.onSearchQueryChanged(query);
return false;
}
#Override
public boolean onQueryTextChange(String query) {
searchManager.onSearchQueryChanged(query);
return false;
}
});
SearchManager class, I use a singleton because I want only one instance I can access from both the activity and the fragment
public class SearchManager {
private static SearchManager searchManager;
private OnSearchResultsListener onSearchResultsListener;
private List<mObject> searchResultList = new ArrayList<>();
public SearchManager() {
}
public void setOnSearchResultsListener(OnSearchResultsListener onSearchResultsListener) {
this.onSearchResultsListener = onSearchResultsListener;
}
public static SearchManager sharedInstance() {
if (searchManager == null) {
searchManager = new SearchManager();
}
return searchManager;
}
public void onContactSearchQueryChanged(String query) {
//do your logic here
this.searchResultList = ...;
onContactsSearchResultsListener.OnSearchResults(searchResultList);
}
}
A simple custom listener
public interface OnSearchResultsListener {
void OnSearchResults(List<mObject> searchResultList);
}
and then in your fragment
public class MFragment extends Fragment implements OnSearchResultsListener {
...
//in your OnCreateView
SearchManager.sharedInstance().setOnSearchResultsListener(this);
...
#Override
public void OnContactsSearchResults(List<mObject> searchResultList) {
//refresh UI
}
Related
I have an SearchView and a button in an ActionBar. The button shows a DialogFragment that contains some checkboxes to filter search results. But when I click OK to close the DialogFragment, the SearchView query resets, and I don't know why. This is my code:
BusquedaActivity.java:
public class BusquedaActivity extends AppCompatActivity implements FiltroTemasDialogFragment.FiltroTemasDialogListener {
RecyclerView rv;
LinearLayoutManager lm;
RecursoAdapter ra;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set actionbar
// Create RecyclerView
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.busqueda, menu);
MenuItem searchItem = menu.findItem(R.id.acc_buscar);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setIconifiedByDefault(false);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String cad) {
buscador(cad);
return true;
}
#Override
public boolean onQueryTextChange(String cad) { return true; }
});
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.acc_listar:
FiltroTemasDialogFragment dialogFragment = new FiltroTemasDialogFragment();
dialogFragment.show(getSupportFragmentManager(),"filtro_temas");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onDialogPositiveClick(FiltroTemasDialogFragment dialog) {
// ...
buscador(((SearchView) findViewById(R.id.acc_buscar)).getQuery().toString());
}
public void buscador(String cad){
// Search
ra.notifyDataSetChanged();
}
}
Thanks in advance.
I think you can declare the SearchView at the class. Then, you can refer it to get the text.
RecyclerView rv;
LinearLayoutManager lm;
RecursoAdapter ra;
private SearchView searchView;
Then change your:
SearchView searchView = (SearchView) searchItem.getActionView();
To
searchView = (SearchView) searchItem.getActionView();
After that, at your onDialogPositiveClick(). You refer it.
#Override
public void onDialogPositiveClick(FiltroTemasDialogFragment dialog) {
// ...
buscador(searchView.getQuery());
}
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.
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;
}
I have been trying to build a searchable interface in this app for a while, and I've been using a lot of the Android developer guides to help, but I recently ran into this error to do with SearchView and OnQueryTextListener that I do not know how to resolve, but it is stopping my app from running.
Here is my MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.overflow, menu);
MenuItem searchItem = menu.findItem(R.id.search);
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setOnQueryTextListener((OnQueryTextListener) searchView);
//this is where the program crashes
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchableInfo info = searchManager.getSearchableInfo(getComponentName());
searchView.setSearchableInfo(info);
return true;
}
public boolean onQueryTextSubmit(String query) {
// User pressed the search button
return false;
}
public boolean onQueryTextChange(String newText) {
// User changed the text
return false;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.constants:
startActivity(new Intent(MainActivity.this, FundamentalPhysicalConstants.class));
return true;
case R.id.joes_rules:
//go to rules
return true;
case R.id.home:
//Go back to the home screen
return true;
case R.id.search:
//open search
return true;
default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);
}
}
}
Here is my SearchableActivity:
public class SearchableActivity extends ListActivity {
DatabaseTable db= new DatabaseTable(this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_searchable);
// get the intent sent when user searches from search widget, verify the action and exxtract what is typed in
Intent intent = getIntent();
handleIntent(intent);
}
public void onNewIntent(Intent intent) {
setIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
Cursor c = db.getWordMatches(query, null);
//still need to process Cursor and display results
}
}
public void onListItemClick(ListView l,
View v, int position, long id) {
// call detail activity for clicked entry
}
private void doSearch(String queryStr) {
// get a Cursor, prepare the ListAdapter
// and set it
}
}
Here is my 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">
</searchable>
Here is my logcat:
06-08 14:57:09.581 28388-28388/com.gmd.referenceapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.gmd.referenceapplication, PID: 28388
java.lang.ClassCastException: android.support.v7.widget.SearchView cannot be cast to android.support.v7.widget.SearchView$OnQueryTextListener
at com.gmd.referenceapplication.MainActivity.onCreateOptionsMenu(MainActivity.java:55)
at android.app.Activity.onCreatePanelMenu(Activity.java:2846)
at android.support.v4.app.FragmentActivity.onCreatePanelMenu(FragmentActivity.java:340)
at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:85)
at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.onCreatePanelMenu(AppCompatDelegateImplBase.java:258)
at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:85)
at android.support.v7.app.ToolbarActionBar.populateOptionsMenu(ToolbarActionBar.java:454)
at android.support.v7.app.ToolbarActionBar$1.run(ToolbarActionBar.java:61)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
I have tried to do a lot of research on this, and I haven't had any luck. I would be extremely grateful for any help on this matter, thanks.
This line is just wrong:
searchView.setOnQueryTextListener((OnQueryTextListener) searchView);
You cannot cast the searchView into OnQueryTextListener. Instead give it a proper parameter as an anonymous class like this:
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
//your logic
}
#Override
public boolean onQueryTextChange(String newText) {
//your logic
}
});
I now see that you have tried to add these two methods in your Activity, which is not the proper way to do it. You either need to create your custom class that implements this SearchView.OnQueryTextListener interface, and then say:
searchView.setOnQueryTextListener(new MyClassThatImplementsTheInterface);
Or do it the way above that I gave you as the first solution. That is the more common way of doing this, using anonymous classes.
the error is clear from the logs you are casting the SearchView to a listener which is wrong try something like
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
});`
I am new on developing an android app. I am already following the code in this website.I wonder how to connect search on action bar that can search data on sqlite database?
This is my MainActivity.java
public class MainActivity extends Activity implements SearchView.OnQueryTextListener {
// More code
}
#Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, 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()));
return super.onCreateOptionsMenu(menu);
}
}
This is my SearchResultsActivity.java
public class SearchResultsActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handleIntent(getIntent());
}
#Override
protected void onNewIntent(Intent intent) {
//super.onNewIntent(intent);
setIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
// use the query to search your data somehow
ListView listView = (ListView) findViewById(R.id.listView1);
DatabaseHandler db = new DatabaseHandler(this);
listView.setAdapter(null);
db.searchContacts(query);
}
}
}