I want to implement the Android Searchview function in a listview fragment populated with data from a Firebase Database.
Code to get the Firebase Data
mPOIAdapter = new FirebaseListAdapter<Poi>(
getActivity(),
Poi.class,
R.layout.item_layout_poi,
FirebaseDatabase.getInstance().getReference("poi").orderByChild("name")) {
#Override
protected void populateView(View v, Poi model, int position) {
TextView pointsText = (TextView) v.findViewById(R.id.poi_textview);
pointsText.setText(model.getName());
TextView pointDescr = (TextView) v.findViewById(R.id.poi_building);
pointDescr.setText(model.getDescription());
}
};
mPOIListView.setAdapter(mPOIAdapter);
Searchview code :
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.options_menu,menu);
MenuItem item = menu.findItem(R.id.search);
item.setVisible(true);
SearchView searchView = (SearchView) item.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
return false;
}
});
}
I want to use code like this to filter the Listview items based on the input of the users
searchView.setOnQueryTextListener(new OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
getListAdapter().getFilter().filter(s);
return true;
}
});
Because the FirebaseListAdapter doesn't have the same possibilities as the ListAdapter, i can't use the getListAdapter().getFilter().filter(s)
Is there an alternative way to use the search function in a Listview fragment populated with Firebase Data
You don't need in any array just create new method "firebaseUserSearch"
the copy your RecyclerView adapter and paste inside. use you databaseReference to filter it.
My FB structure is :
BLABLA:
Bars:
01:
BarName: "Best bar"
02:
BarName: "The Worst bar"
And code is here:
....
databaseReference = FirebaseDatabase.getInstance().getReference ("Bars");
.....
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String searchText) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextChange(String searchText) {
searchText = searchView.getQuery().toString();
firebaseUserSearch (searchText);
return true;
}
});
return true;
}
private void firebaseUserSearch (final String searchText) {
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter <Bar, ViewHolder>(
Bar.class,
R.layout.custom_row,
ViewHolder.class,
databaseReference.orderByChild("barName").startAt(searchText.toUpperCase()).endAt(searchText + "\uf8ff"))
{
#Override
protected void populateViewHolder(ViewHolder viewHolder, Bar model, final int position) {
....
FirebaseDatabase.getInstance().getReference("poi").orderByChild("name").equalTo("anyName")) {
try this orderByChild("name").equalTo("nameString")
it'll check if there is any matched name belongs to name child. if there is any it'll show that to list
Related
This is my OnCreateOptionMenu
An error is showing in setOnQueryListener
here contact_object is model class
#Override
public boolean onCreateOptionsMenu(Menu menu) {
{
MenuInflater inflater=getMenuInflater();
inflater.inflate(R.menu.search_list,menu);
final MenuItem myMenuItem=menu.findItem(R.id.search_contact);
SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem (R.id.search_contact) .getActionView ();
changedSearchViewTextColor(searchView);
// ((EditText)searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text)).setHintTextColor(getResources().getColor(R.color.white));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
if (!searchView.isIconified()){
searchView.setIconified(true);
}
myMenuItem.collapseActionView();
return false;
}
}
#Override
public boolean onQueryTextChange(String newText) {
newText=newText.toLowerCase();
final List<Contact_Object> filtermodelist=filter(contacts,newText);
adapter.setFilter(filtermodelist);
return true;
}
});
return true;
}
I have implemented the filter option as below
public List<Contact_Object> filter(List<Contact_Object> p,String query )
{
query=query.toLowerCase();
final List<Contact_Object> filterModeList=new ArrayList<>();
for (Contact_Object model :p){
final String text=model.getName().toLowerCase();
if (text.startsWith(query)){
filterModeList.add(model);
}
}
return filterModeList;
}
I have declared the setFilter function as follow in CustomAdapter class
public void setFilter(List<Contact_Object> listItem){
parentList=new ArrayList<>();
parentList.addAll(listItem);
notifyDataSetChanged();
}
I have tried hard but didn't get the appropriate answer
please anyone help me,waiting for answer
There is no logic in onQueryTextChange because newText is not passed anywhere. You are passing the empty list to the setFilter method.
#Override
public boolean onQueryTextChange(String newText) {
newText = newText.toLowerCase();
final List<Contact_Object> filterModeList=new ArrayList<>();
for (Contact_Object obj : p) {
String name = obj.getName().toLowerCase();
if(name.contains(newText))
filterModeList.add(obj);
}
adapter.setFilter(filtermodelist);
return true;
}
Currently, I'm working on an activity that has a RecyclerView and SearchView in it.Now the RecyclerView and SearchView are working fine but there is a problem that I don't know how to resolve, you see in the searchView part we were a task to make a SearchView that accepts 2 or more searchItems that must be separated by a comma or space in order to filter the recyclerview again if the second searchitem matches an item in the RecyclerView, for example I type in searchitem "Big" i'll need to separate it again with another searchitem like "Black"
here is the code for the SearchView
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pet_book_main);
if(savedInstanceState != null){
mSearchString=savedInstanceState.getString(SEARCH_KEY);
}
pet_title=(TextView)findViewById(R.id.pet_book_title);
petbook=(RecyclerView)findViewById(R.id.pet_book_pet);
navbot=(BottomNavigationView) findViewById(R.id.petbook_navbot);
toolbar=(Toolbar)findViewById(R.id.petbook_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(false);
toolbar.setTitle("");
linearLayoutManager=new LinearLayoutManager(this);
petbook.setHasFixedSize(true);
petbook.setLayoutManager(linearLayoutManager);
refresh();
disableShiftMode(navbot);
}
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
MenuInflater menuInflater= getMenuInflater();
menuInflater.inflate(R.menu.petbook_searck,menu);
searchItem=menu.findItem(R.id.pet_book_search_mode);
searchView =(SearchView)MenuItemCompat.getActionView(searchItem);
if (mSearchString != null && !mSearchString.isEmpty()) {
searchItem.expandActionView();
searchView.setQuery(mSearchString, true);
searchView.clearFocus();
}
search(searchView);
MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
pet_title.setVisibility(View.INVISIBLE);
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
pet_title.setVisibility(View.VISIBLE);
return true;
}
});
return true;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mSearchString = searchView.getQuery().toString();
outState.putString(SEARCH_KEY, mSearchString);
}
public void search(android.support.v7.widget.SearchView search)
{
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
newText=newText.toLowerCase();
newList=new ArrayList<>();
for(petbook_getItem items : bookItem){
String pets=items.getPet_name().toLowerCase();
if(pets.contains(newText))
newList.add(items);
}
adapter.filterSearch(newList);
adapter.notifyDataSetChanged();
return true;
}
});
}
This code handles user input in search which can be multiple comma separated search items:
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
.....
#Override
public boolean onQueryTextChange(String newText) {
newText = newText.toLowerCase();
// remove leading comma or space
String string2 = newText.replaceAll("^[,\\s]+", "");
// return early for invalid input (empty)
if (string2.isEmpty()) {
return true;
}
// split by comma & space if any
List<String> inputList = Arrays.asList(string2.split("[,\\s]+"));
newList = new ArrayList<>();
for (petbook_getItem items : bookItem){
String pets = items.getPet_name().toLowerCase();
// Check for matching by looping through each search items
for (String inputTxt : inputList) {
if (pets.contains(inputTxt)) {
newList.add(items);
break;
}
}
}
adapter.filterSearch(newList);
adapter.notifyDataSetChanged();
return true;
}
});
I'm trying to add a "Search User" Activity to a simple App I'm trying to make. But I'm having trouble taking the user input (from a SearchView) and using it to make a query into the Firebase Database to finally display everything in a Listview (using FirebaseListAdapter).
The problem is mainly with the Firebase part that I can't really figure out. Here is the code:
SearchView userSearchView;
ListView userListView;
SearchUserListAdapter UserAdapter;
String currentUserName;
String currentEnteredQuery = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_user);
userSearchView = (SearchView) findViewById(R.id.user_searchview);
userListView = ( ListView) findViewById(R.id.listview_search);
final Intent startConversation = new Intent(this,ConversationActivity.class);
//Start a new conversation
userListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startActivity(startConversation);
}
});
Query query = UserDbRef.orderByChild(currentEnteredQuery);
final FirebaseListAdapter firebaseListAdapter = new FirebaseListAdapter<UserItem>(this, UserItem.class, R.layout.user_item, query) {
#Override
protected void populateView(View v, UserItem userItem) {
((TextView)v.findViewById(android.R.id.text1)).setText(userItem.getUser_name());
}
};
userListView.setAdapter(firebaseListAdapter);
userSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String inputQuery) {
currentEnteredQuery = inputQuery;
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_search_user, menu);
return true;
}
Put your query inside the Listener for the SearchView so that it would query everytime you search with a specific criteria:
userSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String inputQuery) {
currentEnteredQuery = inputQuery;
//Your Firebase Query here
Query query = UserDbRef.orderByChild(currentEnteredQuery);
final FirebaseListAdapter firebaseListAdapter = new FirebaseListAdapter<UserItem>(this, UserItem.class, R.layout.user_item, query) {
#Override
protected void populateView(View v, UserItem userItem) {
((TextView)v.findViewById(android.R.id.text1)).setText(userItem.getUser_name());
}
};
userListView.setAdapter(firebaseListAdapter);
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
Also in these lines:
final FirebaseListAdapter firebaseListAdapter = new FirebaseListAdapter<UserItem>(this, UserItem.class, R.layout.user_item, query) {
#Override
protected void populateView(View v, UserItem userItem) {
((TextView)v.findViewById(android.R.id.text1)).setText(userItem.getUser_name());
}
};
You are using R.layout.user_item as your layout for the list but you are using android.R.id.text1. As far as I know, android.R are resources built-in the Android SDK. I think this is the view if you are using android.R.layout.simple_list_item_1. Go ahead and check your R.layout.user_item and change the id to the corresponding view in your layout.
I am looking for a way of filtering my data in a RecyclerView using a searchView but am still stuck. I read this post Filtering a recyclerview with a firebaserecycleradapter and Filter data on firebase using Searchview, but there is no any clear answer. And they are the only posts available.
There are also no clear examples on this issue. I am looking for a full simple example on Filtering data in a RecyclerView with Firebase using SearchView.
Below is Load() method ic all it in OnCreate() to load the list of Items.
void Load(){
// mAuth.addAuthStateListener(mAuthLitsener);
FirebaseRecyclerAdapter<Event,EventViewHolder> firebaseRecyclerAdapter_ = new FirebaseRecyclerAdapter<Event, GraduationListActivity.EventViewHolder>(Event.class,
R.layout.item_event_view,
GraduationListActivity.EventViewHolder.class,
queryRef) {
#Override
protected void populateViewHolder(GraduationListActivity.EventViewHolder viewHolder, final Event model, final int position) {
final String key_post = getRef(position).getKey();
viewHolder.setEventLocation(model.getEventLocation());
viewHolder.setEventName(model.getEventName());
viewHolder.setEventType(model.getEventType());
viewHolder.setEventDate(model.getEventDate());
viewHolder.setEventPic(c, model.getEventImage());
viewHolder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Toast.makeText(EventViewActivity.this,"This is : "+position,Toast.LENGTH_LONG).show();
Intent loadMainActivity = new Intent(GraduationListActivity.this,BlogActivity.class);
loadMainActivity.putExtra("PARTY_NAME", model.getEventName());
startActivity(loadMainActivity);
}
});
}
};
mRecyclerview_event_view.setAdapter(firebaseRecyclerAdapter_);
}
and this is my onCreateOptionsMenu()
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.search, menu);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
// ????????
}
#Override
public boolean onQueryTextChange(String newText) {
//??????
return true;
}
});
return super.onCreateOptionsMenu(menu);
}
So am using a searchView to search but am confused: what should I put in onQueryTextChange() and onQueryTextSubmit() according to Firebase?
I am stumbed with animated searchview onQueryTextListener. When activity and fragment created first it works nice. Then I press home button, open other apps, do some work there to wipe the data of searchview activity and then return to the app. And when activity and fragment resume onQueryTextChange method is triggered by it's own. I tried this issue
Fragment replacement triggers onQueryTextChange on searchview
but it did not help, helps only when searchview SHOW_AS_ACTION_NEVER, but in this case I can not see searchview. How to prevent self-triggering of OnQueryTextListener?
Snippet from fragment
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
searchView = new SearchView(getSherlockActivity().getSupportActionBar()
.getThemedContext());
searchView.setOnQueryTextListener(new OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
if (newText.length() > 0) {
fpAdapter.getFilter().filter(newText);
} else {
loadData();
}
return false;
}
});
TextView searchText = (TextView) searchView
.findViewById(R.id.abs__search_src_text);
searchText.setTextColor(Color.WHITE);
searchText.setCursorVisible(false);
ImageView searchButton = (ImageView) searchView
.findViewById(R.id.abs__search_button);
searchButton.setImageResource(R.drawable.search_menu_button);
LinearLayout searchEditFrame = (LinearLayout) searchView
.findViewById(R.id.abs__search_edit_frame);
searchEditFrame.setBackgroundResource(android.R.color.transparent);
View searchPlate = searchView.findViewById(R.id.abs__search_plate);
searchPlate.setBackgroundColor(Color.argb(0, 0, 0, 0));
menu.add("Search")
.setActionView(searchView)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
final MenuItem searchMenuItem = menu.getItem(0);
final Animation in = AnimationUtils.loadAnimation(getSherlockActivity()
.getApplicationContext(), R.anim.search_in);
final Animation out = AnimationUtils.loadAnimation(
getSherlockActivity().getApplicationContext(),
R.anim.search_out);
searchView.setQueryHint(getResources().getText(
R.string.search_messages_hint));
searchView.setIconifiedByDefault(true);
searchView
.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view,
boolean queryTextFocused) {
if (!queryTextFocused) {
// searchView.startAnimation(out);
searchMenuItem.collapseActionView();
} else {
searchView.startAnimation(in);
}
}
});
super.onCreateOptionsMenu(menu, inflater);
}
Update: This appears only in HTC sensation XL with Android 4.0.3, on 4.2 I don't see this problem.
Found the only one solution - set listener in onResume:
#Override
public void onResume() {
super.onResume();
searchView.setOnQueryTextListener(new OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
if (newText.length() > 0) {
fpAdapter.getFilter().filter(newText);
} else {
loadData();
}
return false;
}
}); }
use this code
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(final String s) {
if(searchView.getWidth()>0)
{
// your code here
}
return false;
}
});
You can set to use the SearchView only when it's in focus. I had a similar problem where the search was performing in my fragment every time when users resumed it. I solve it with the following method:
-Add a boolean to see when SearchView is in focus:
//by default the SearchView isn't in focus so set it to false.
private boolean shouldSearch = false;
searchView.setOnQueryTextFocusChangeListener((view, hasFocus) -> {
if (hasFocus) {
shouldSearch = true;
} else {
shouldSearch = false;
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
if (shouldSearch) {
//do your search here
}
return true;
}
});
This is a known issue. You can fix by checking to see if the search is "iconified" i.e only showing the magnifying glass icon or if it is expanded ( which means the user is interacting with the search view)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
//your code here
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
//this will catch firing event
if (searchView.isIconified) {
return true
}
//your code here
return true
}
})