set suggestions on androidx.appcompat.widget.SearchView - java

I am making an android app in which i used a androidx.appcompat.widget.SearchView I have an arraylist which contains different values now i want to set the suggestions of androidx.appcompat.widget.SearchView from that array list. I tried a lot but it didn't work well.
I also toast in onQueryTextChange to test either it is working or not but it is not working because when i change the text i didn't get the toasr
public static ArrayList<String> phoneNo=new ArrayList<>(); // This one contains names
public static ArrayList<String> cname=new ArrayList<>(); // This one contains phone numbers
private SimpleCursorAdapter mAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View root= inflater.inflate(R.layout.fragment_messages, container, false);
final String[] from = new String[] {"contacts"};
final int[] to = new int[] {android.R.id.text1};
mAdapter = new SimpleCursorAdapter(home_Activity,
android.R.layout.simple_list_item_1,
null,
from,
to,
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
searchView = (SearchView) view.findViewById(R.id.sView);
searchView.setSuggestionsAdapter(mAdapter);
searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
#Override
public boolean onSuggestionClick(int position) {
Cursor cursor = (Cursor) mAdapter.getItem(position);
String txt = cursor.getString(cursor.getColumnIndex("contacts"));
searchView.setQuery(txt, true);
return true;
}
#Override
public boolean onSuggestionSelect(int position) {
// Your code here
return true;
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
populateAdapter(s);
Toast.makeText(home_Activity, "ok", Toast.LENGTH_SHORT).show();
return true;
}
});
}

Related

Android Java: Custom adapter for listview for scrolling and filtering issue

I have searched online that I need a custom adapter for my listview to solve the scrolling and filtering issue. I am using fragments since I have some tabs on my main activity.
I have tried to implement different variations of codes that I found but I could not make it work.
public class Symptoms extends Fragment {
String filename = "symptoms.txt";
private static final String TAG = "SymptomsFragment";
ReadFile rf = new ReadFile();
String[] lines;
ListView simpleList;
Context context;
private EditText filterText;
private ArrayAdapter<String> arrayAdapter;
ArrayList<String> listItems = new ArrayList<String>();
int count = 0;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
final View mView = inflater.inflate(R.layout.symptoms_layout,container,false);
simpleList = (ListView) mView.findViewById(R.id.list);
filterText = (EditText) mView.findViewById(R.id.editText);
try {
lines = rf.readLines(filename, getContext());
arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, lines);
simpleList.setAdapter(arrayAdapter);
}
catch(IOException e) {
// Print out the exception that occurred
Toast.makeText(getContext(), "Unable to create "+filename+": "+e.getMessage(), Toast.LENGTH_LONG).show();
}
filterText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
arrayAdapter.getFilter().filter(s);
}
#Override
public void afterTextChanged(Editable s) { }
});
simpleList.setCacheColorHint(Color.TRANSPARENT);
simpleList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
simpleList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv = (TextView)view.findViewById(android.R.id.text1);
String selectedSymptom = tv.getText().toString();
if(!listItems.contains(selectedSymptom)) {
tv.setTextColor(Color.WHITE);
tv.setBackgroundColor(Color.CYAN);
listItems.add(selectedSymptom);
}else{
tv.setTextColor(Color.BLACK);
tv.setBackgroundColor(Color.TRANSPARENT);
listItems.remove(selectedSymptom);
}
System.out.println(listItems);
}
});
return mView;
}
}
I am reading a text file and saving each line to an arraylist element and I am using the ArrayAdapter for my listview. I am changing the background and text color of the selected items. However when I am using the "EditText" to search on the listview or when I am scrolling the elements that were highlighted are getting shuffled (visually only). I have found many solutions online for people that were facing the same problem with their checkboxes in the listview but I was having a really hard time to implement those solutions. How should the Custom Listview adapter look like in this situation? Thanks in advance!
Try change:
arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, lines);
To:
arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, lines){
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv1 = (TextView)super.getView(position, convertView, parent);
String selectedSymptom = getItem(position);
if(listItems.contains(selectedSymptom)) {
tv1.setTextColor(Color.WHITE);
tv1.setBackgroundColor(Color.CYAN);
}else{
tv1.setTextColor(Color.BLACK);
tv1.setBackgroundColor(Color.TRANSPARENT);
}
return tv1;
}
};
Hope that helps!
The error came from lines = rf.readLines(filename, getContext());
You can not read a file on main thread because application will be ANR
ANR (App Not Responding) is a state in which the app is frozen and does not respond to any user gestures or draw. Unlike unresponsive gestures which are attributed to a design decision (e.g. an image that mistakenly looks like a tappable button), ANRs usually occur due to long running code that freezes the “UI thread”.
You can use AsyncTask class which create a new thread in background for reading file then you can bind the result to UI.
Consider using RecyclerView it would look like this:
Adapter declaration:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements Filterable {
private List<IssuePOJO> myList; // search results
private List<IssuePOJO> myListFull; // all items
}
Constructor:
public RecyclerViewAdapter(Context context, List<String> myList){
this.context = context;
this.myList = myList;
myListFull = new ArrayList<>(myList); // initializing both lists with same data
}
Overriding Filter:
#Override
public Filter getFilter() {
return listFilter;
}
private Filter listFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<String> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) { // checking if filter field is empty
filteredList.addAll(myListFull);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (String item : myListFull) {
if (item.toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
myList.clear();
myList.addAll((List) results.values); // only this list is pressented to users inside RecyclerView, myListFull
notifyDataSetChanged();
}
};
And inside an Activity or Fragment:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu_main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
recyclerAdapter.getFilter().filter(newText);
return false;
}
});
//super.onCreateOptionsMenu(menu, inflater);
}
MENU:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.damianadamski.service.MainActivity">
<item
android:id="#+id/action_search"
android:icon="#drawable/ico_search"
android:title=""
android:tooltipText="Search..."
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>
You don't have to add icon but you just can customize it to fit into your application.

Trying to filter a ListView with a SearchView. No items are displayed no matter which word I enter, even if relevant items exist on the ListView

There are more than 2,000 items on my listview and no matter which item I search for, after pressing a letter, listView goes blank like as if there were no relevant items.
I'm guessing it's beacuse I'm using the simple_list_item_2 layout which is provided by Android Studio. It has two textView fields on it and that is why filtering may be messed up. It's just a guess of mine though.
Here's the adapter and listview:
adapter = new ArrayAdapter(ViewExistingCustomersActivity.this, android.R.layout.simple_list_item_2, android.R.id.text1, customers) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView text1 = (TextView) view.findViewById(android.R.id.text1);
TextView text2 = (TextView) view.findViewById(android.R.id.text2);
text1.setText(customers.get(position).getDefinition());
text2.setText(customers.get(position).getAddress1() + " Bakiye: " + customers.get(position).getBalance());
return view;
}
};
customersListView.setAdapter(adapter);
// Dokunulan ListView elemanının detaylarını gösterecek ekranı çağıran kod.
customersListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent viewCustomerDetailsIntent = new Intent(ViewExistingCustomersActivity.this, CurrentStatementActivity.class);
viewCustomerDetailsIntent.putExtra("customer", customers.get(i));
viewCustomerDetailsIntent.putExtra("user", user);
startActivity(viewCustomerDetailsIntent);
}
});
And here's the searchView:
customersSearchView.setOnQueryTextListener(new OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
If you're using a ContentProvider to retrieve your data list, then the following line in onQueryTextChange() will not work:
adapter.getFilter().filter(newText);
If you are using a CursorLoader (with the ContentProvider), you must filter the data using the LoaderManager callbacks, not using the adapter directly. You would need to change your onQueryTextChange() method to something like this:
private String cursorFilter;
#Override
public boolean onQueryTextChange(String newText) {
cursorFilter = !TextUtils.isEmpty(newText) ? newText : null;
getLoaderManager().restartLoader(0, null, this);
return true;
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Uri baseUri;
if (cursorFilter != null) {
// Filter the data with the cursorFilter
baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
Uri.encode(cursorFilter));
} else {
baseUri = MyContentProvider.CONTENT_URI;
}
...
}
See here for an example: http://android-er.blogspot.co.uk/2013/02/query-contacts-database-using-loader.html
You may implement the Custumer model toString to return the string you wanna to filter with.
the model you have (the on that reuturn in customers.get(position))
public class Custumer {
//The rest as is
#Override public String toString() {
return getDefinition();
}
}

Android: onItemCheckedStateChanged is called only once

Fragment class:
public class MultiFragmentListContent extends ListFragment
{
ListView listView;
ActionMode actionMode;
ArrayAdapter<String> arrayAdapter;
List<String> stringList;
Set<String> checkList;
AbsListView.MultiChoiceModeListener choiceModeListener = null;
#Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
super.onCreateView(inflater,container,savedInstanceState);
View rootView = inflater.inflate(R.layout.fragment, container, false);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
checkList = new HashSet<>();
stringList = new LinkedList<>();
stringList.add("A");
stringList.add("B");
stringList.add("C");
stringList.add("D");
stringList.add("E");
listView = getListView();
arrayAdapter = new ArrayAdapter<String>(getActivity(),R.layout.string,stringList);
listView.setAdapter(arrayAdapter);
choiceModeListener = new AbsListView.MultiChoiceModeListener()
{
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked)
{
if(checked)
checkList.add(stringList.get(position));
else
checkList.remove(stringList.get(position));
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu)
{
actionMode = mode;
MenuInflater menuInflater = mode.getMenuInflater();
menuInflater.inflate(R.menu.contentmenu2,menu);
arrayAdapter = new ArrayAdapter<String>(getActivity(),R.layout.checkbox,stringList);
listView.setAdapter(arrayAdapter);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return true;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item)
{
switch(item.getItemId())
{
case R.id.contextmenu2:
for(String k : checkList)
{
stringList.remove(k);
Log.i(k,k);
}
actionMode.finish();
break;
}
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode)
{
arrayAdapter = new ArrayAdapter<String>(getActivity(),R.layout.string,stringList);
listView.setAdapter(arrayAdapter);
checkList.removeAll(checkList);
}
};
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(choiceModeListener);
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener()
{
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)
{
listView.setMultiChoiceModeListener(choiceModeListener);
return true;
}
});
}
}
I noted that the method onItemCheckedStateChanged is called only once.
Before that method worked, I mean it was always called.
I tried to find on the web but I didn't find a solution.
I think that the problem is
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
but I don't know where to put it. If I put it in other places, the app crashes.
It's possible if you create one boolean value for your control in onItemCheckedStateChanged, the call always called, but will a have control.

android spinner doesn't work. it selected nothing

I'm using a Spinner in a Fragment. When the activity is created, the spinner doesn't show anything. It has no item when I click on the spinner, but the items are shown correctly.
When I select on the item nothing happens even though I call a Toast message.
P.S. The items come from an ArrayList of String from a database.
This is the code of the fragment:
public class RegStudentFragment extends Fragment {
private Spinner uniSpinner;
private RegistrationStudent activity;
private ArrayList<String> listaUni;
private int pos;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.regs_frag, container, false);
uniSpinner=(Spinner) view.findViewById(R.id.spinnerUni);
System.out.println("fvfebeer");
manageUSpinner();
return view;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.activity = (RegistrationStudent) activity;
}
#Override
public void onActivityCreated(Bundle savedInstancestate) {
super.onActivityCreated(savedInstancestate);
listaUni = new ArrayList<String>();
new RequestFtp().setParameters(activity, "univer.php", "spinnerUni", RegStudentFragment.this).execute();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this.getActivity().getApplicationContext(), android.R.layout.simple_spinner_item, getListaUni());
adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
uniSpinner.setAdapter(adapter);
uniSpinner.setPrompt("Seleziona tra le seguenti:");
}
private void manageUSpinner() {
uniSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(activity.getApplicationContext(),"you selected ",Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
Toast.makeText(activity.getApplicationContext(),"No select ",Toast.LENGTH_SHORT).show();
}
});
System.out.println("vvsvsvsvsvs");
}
public void numeroel(ArrayList<ObjDb> result) {
ObjDb res= result.get(0);
String str=res.get("num");
int num=Integer.parseInt(str);
//numUni=new String[num];
}
public void arrayU(ArrayList<ObjDb> result){
int i=0;
while(i<result.size()) {
ObjDb res = result.get(i);
String str=res.get("nome");
listaUni.add(str);
i++;
}
}
public ArrayList<String> getListaUni(){
return listaUni;
}
}

Custom listview and Sherlock List Fragment

In my application I'm trying to make navigation between pages by Dropdown navigation menu, but when i'm running the application there is no items in my list
Main Activity
public class Main extends SherlockFragmentActivity implements OnNavigationListener{
//----------------------------------New Variables
private static final String KEY_MODELS="models";
private static final String KEY_POSITION="position";
private static final String[] labels= { "All", "Downloads","Completed","Later" };
private CharSequence[] models=new CharSequence[4];
private DownloadList frag=null;
private int lastPosition=-1;
//----------------------------------
ActionBar act;
ViewPager myviewpager;
int mSelectedPageIndex=1;
DownloadService downloadservice;
Intent serviceIntent ;
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
frag=(DownloadList)getSupportFragmentManager().findFragmentById(android.R.id.content);
if (frag==null) {
frag=new DownloadList();
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, frag).commit();
}
if (state != null) {
models=state.getCharSequenceArray(KEY_MODELS);
}
if (downloadservice==null)
downloadservice= new DownloadService();
ArrayAdapter<String> nav=null;
act=getSupportActionBar();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
{
nav= new ArrayAdapter<String>(act.getThemedContext(),
android.R.layout.simple_spinner_item,labels);
}
else
{
nav=new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,labels);
}
nav.setDropDownViewResource(android.R.layout.simple_list_item_1);
act.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
act.setDisplayShowTitleEnabled(false);
act.setHomeButtonEnabled(false);
act.setListNavigationCallbacks(nav, this);
if (state != null) {
act.setSelectedNavigationItem(state.getInt(KEY_POSITION));
}
serviceIntent= new Intent(Main.this,downloadservice.getClass());
if (startService(serviceIntent)==null)
startService(serviceIntent);
act.setTitle("");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater infalter = getSupportMenuInflater();
infalter.inflate(R.menu.mymenu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()==R.id.sub1)
{
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Downlaod New File");
alert.setMessage("Enter URL");
final EditText input = new EditText(this);
alert.setView(input);
input.setText( "http://205.196.123.184/ddpha7c5b8lg/616c36j0d1xbztf
/Lecture+ppt+Ch2.ppt");
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String value = input.getText().toString();
downloadservice.addandstart(value);
Log.d("value",value);
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
alert.show();
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
#Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
lastPosition=itemPosition;
frag=(DownloadList)getSupportFragmentManager().findFragmentById(android.R.id.content);
return false;
}
Custom adapter and SherlockFragmentList
public class DownloadList extends SherlockListFragment {
int index=0;
Button downloadButton;
Button pauseButton;
Button resumeButton;
TextView textLink;
TextView progressbar;
DownloadService downloadservice= new DownloadService();
MyAdapter listadapter;
Intent serviceIntent ;
String state;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setContentView(R.layout.downloadlist);
setListAdapter(new MyAdapter(getSherlockActivity(), downloadservice.downloads));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle
savedInstanceState) {
View rootView = inflater.inflate(R.layout.downloadlist, container, false);
setListAdapter(new MyAdapter(getSherlockActivity(), downloadservice.downloads));
return rootView;
}
int getIndex()
{
return index;
}
public class MyAdapter extends ArrayAdapter<NewDownload>
{
private final List<NewDownload> list;
//private final Activity context;
Thread t;
public MyAdapter(Context context,List<NewDownload> list) {
super(context, R.layout.list_item, list);
// this.context = (Activity) context;
this.list = list;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)
getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.list_item, null);
pauseButton = (Button) row.findViewById(R.id.btn1);
resumeButton = (Button) row.findViewById(R.id.btn2);
textLink = (TextView) row.findViewById(R.id.tv1);
progressbar = (TextView) row.findViewById(R.id.progressBar1);
textLink.setText(downloadservice.downloads.get(position).getName());
progressbar.setBottom(downloadservice.downloads.get(position).getDownloadedSize());
progressbar.setTop(downloadservice.downloads.get(position).getTotalSize());
final int p = position;
final NewDownload r = list.get(p);
if (r.state=="downloading")
{
progressbar.setText("DownLoading...");
pauseButton.setEnabled(true);
resumeButton.setEnabled(false);
}
else if (r.state=="pause")
{
pauseButton.setEnabled(false);
resumeButton.setEnabled(true);
progressbar.setText(r.state);
}
pauseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
downloadservice.pause(p);
setListAdapter(listadapter );
}
});
resumeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (getActivity().startService(serviceIntent)==null)
getActivity().startService(serviceIntent);
downloadservice.resume(p);
setListAdapter(listadapter );
}
});
return row;
}
}
Anyone can tell me how to implement my list right and where is my mistake ?
thx a lot
Don't set the layout from your fragment big no no!
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// getActivity().setContentView(R.layout.downloadlist); // Never do this!
// Also this will do nothing remove this! This should be in your `onActivityCreated()`
// setListAdapter(new MyAdapter(getSherlockActivity(), downloadservice.downloads));
}
Don't override onCreateView in your Fragment, SherlockListFragment creates the ListView layout for you.
If you want to set the adapter, remove your onCreateView and set you adapter in onActivityCreated()
#Override
public void onActivityCreated(Bundle saveState){
setListAdapter(new MyAdapter(getSherlockActivity(), downloadservice.downloads));
}
Setting your setListAdapter(listadapter ); in your Adapter getView is wrong too. If you update your List<?> of data make sure you call notifyDataSetChanged() from the mainThread after you update the list.
Otherwise make sure you layout has a ListView with android:id="#android:id/list" defined otherwise SherlockListView won't have a view to set the adapter too.

Categories