Search Action Bar is not working with AsyncTask Class - android

I have created a Search Icon in my Action Bar. I tried to use Strings Array, it worked well.
But, when I tried to get data from a web server. The search is not working well. Though I have tried to fixed it. But, it still doesn't work.
Here is my class :
public class MainActivity extends AppCompatActivity {
private String URL=
"TTTTTTTTTT.php";
private String Contact_NAME[] ;
private JSONParser jsonParser = new JSONParser();
private ListView mListView;
private my_Adapter ContactViewAdapter;
private ArrayList<Contacts_ListView> ContactView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView)findViewById(R.id.listViewCountry);
new Get_Contacts().execute();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_search, menu);
MenuItem item = menu.findItem(R.id.menuSearch);
SearchView searchView = (SearchView)item.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
ContactViewAdapter.getFilter().filter(newText);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
Here is my AsyncTask. I used it as a private class inside my MainActivity
private class Get_Contacts extends AsyncTask<Void, Void, Boolean>
{
private ProgressDialog mProgressDialog;
private JSONObject jsonObjectResult = null;
private String error;
private String THE_URL ;
public Get_Contacts(){
THE_URL = Contact_URL ;
WITH_INPUT = false ;
} ;
#Override
protected void onPreExecute()
{
super.onPreExecute();
ContactView = new ArrayList<Contacts_ListView>();
}
#Override
protected Boolean doInBackground(Void... params)
{
List<NameValuePair> pairs = new ArrayList<NameValuePair>();
pairs = null;
jsonObjectResult = jsonParser.makeHttpRequest(THE_URL, pairs);
if (jsonObjectResult == null)
{
error = "ERROR";
return false;
}
try
{
if (jsonObjectResult.getInt("success") == 1)
{
JSONArray jsonArray = jsonObjectResult.getJSONArray("posts");
saving_loop = jsonArray.length() ;
JSONObject news ;
for (int i = 0; i < jsonArray.length(); i++)
{
news = jsonArray.getJSONObject(i);
Contacts_ListView listviewcontacts = new Contacts_ListView
(
news.getString("Contact_Name")
);
ContactView.add(listviewcontacts);
}
return true;
}
else
error = jsonObjectResult.getString("message");
}
catch (Exception ex)
{
}
return false;
}
#Override
protected void onPostExecute(Boolean aBoolean)
{
super.onPostExecute(aBoolean);
if (aBoolean)
{
ContactViewAdapter = new Contacts_ListViewAdapter_No_Checkbox(MainActivity.this,
ContactView);
mListView.setAdapter(ContactViewAdapter);
}
else
Toast.makeText(MainActivity.this, error, Toast.LENGTH_LONG).show();
}
}
}
The application works and it doesn't give me any errors. When I try to search. It doesn't search
Here is my Adapter
public class Contacts_ListViewAdapter_No_Checkbox extends BaseAdapter {
private Context mContext;
private List<Contacts_ListView> mData;
private MyFilter filter ;
private ArrayList<Contacts_ListView> originalList ;
public Contacts_ListViewAdapter_No_Checkbox (Context mContext, ArrayList<Contacts_ListView> mData) {
//super(mContext, R.layout.contacts_shape_nocheckbox, mData);
this.mContext = mContext;
this.mData = mData;
this.originalList = new ArrayList<Contacts_ListView>();
this.originalList.addAll(mData);
}
#Override
public int getCount() {
return mData.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public Object getItem(int position) {
return mData.get(position);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
LayoutInflater mInflater = (LayoutInflater)
mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.contacts_shape_nocheckbox, null);
}
TextView Contact_Name = (TextView) convertView.findViewById(R.id.Contact_Name_1);
Contact_Name.setText(mData.get(position).getContactName());
return convertView;
}
public Filter getFilter() {
if (filter == null){
filter = new MyFilter();
}
return filter;
}
private class MyFilter extends Filter
{
#Override
protected FilterResults performFiltering(CharSequence constraint) {
constraint = constraint.toString();
FilterResults result = new FilterResults();
if(constraint != null && constraint.toString().length() > 0)
{
ArrayList<Contacts_ListView> filteredItems = new ArrayList<Contacts_ListView>();
for(int i = 0, l = originalList.size(); i < l; i++)
{
Contacts_ListView nameList = originalList.get(i);
if(nameList.toString().contains(constraint))
filteredItems.add(nameList);
}
result.count = filteredItems.size();
result.values = filteredItems;
}
else
{
synchronized(this)
{
result.values = originalList;
result.count = originalList.size();
}
}
return result;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence contraint, FilterResults results) {
mData = (ArrayList<Contacts_ListView>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}

Filter not work because you are using a custom object. If you pass a String or int value to array adapter its know how to filter it. But if you pass custom object default filter implementation have to no idea how to deal with that. use custom adapter instead of arrayadapter
What you need to do
Extends BaseAdapter insted of ArrayAdater
Make custom Filter in Adapter
3.Return filter result
Filter myFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
ArrayList<Contacts_ListView> tempList=new ArrayList<Contacts_ListView>();
//constraint is the result from text you want to filter against.
//objects is your data set you will filter from
if(constraint != null && objects!=null) {
int length=objects.size();
int i=0;
while(i<length){
Contacts_ListView item=objects.get(i);
//do whatever you wanna do here
//adding result set output array
tempList.add(item);
i++;
}
//following two lines is very important
//as publish result can only take FilterResults objects
filterResults.values = tempList;
filterResults.count = tempList.size();
}
return filterResults;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence contraint, FilterResults results) {
objects = (ArrayList<Contacts_ListView>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
Override method
#Override
public Filter getFilter() {
return myFilter;
}
Updated change your code to below code
Contacts_ListView nameList = originalList.get(i);
if(nameList.getContactName().toString().contains(constraint))
filteredItems.add(nameList);

Related

Filter ListView from custom base adapter

I am trying to implement the search in the Custom ListView. I am able to search in my list. But the problem with my adapter is once the query string is not available in the list even if i backspace my string and write the correct string it's not able to search it. And my other question is how can I refresh the list with my old list which was present before the search.
Here is my code:
public class ChartListAdapter extends BaseAdapter implements Filterable {
ArrayList<ChartModel> list;
Context context;
public ChartListAdapter(ArrayList<ChartModel> list, Context context) {
this.list = list;
this.context = context;
}
#Override
public int getCount() {
if(list != null) {
return list.size();
} else {
return 0;
}
}
#Override
public Object getItem(int i) {
return list.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
if(view == null) {
view = View.inflate(context, R.layout.chart_card, null);
}
TextView chart_name = view.findViewById(R.id.chart_name);
SwitchCompat switchCompat = view.findViewById(R.id.chart_selected);
switchCompat.setTag(list.get(i).getChart_id());
chart_name.setText(list.get(i).getChart_name());
switchCompat.setChecked(list.get(i).getCard_selected());
switchCompat.setOnCheckedChangeListener((compoundButton, b) -> {
String getTag = compoundButton.getTag().toString();
Toast.makeText(context, getTag + " is selected :" + b, Toast.LENGTH_LONG).show();
});
return view;
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if(constraint == null || constraint.length() == 0){
filterResults.count = list.size();
filterResults.values = list;
}else{
ArrayList<ChartModel> resultsModel = new ArrayList<>();
String searchStr = constraint.toString().toLowerCase();
for(ChartModel itemsModel:list){
if(itemsModel.getChart_id().contains(searchStr)){
resultsModel.add(itemsModel);
}
filterResults.count = resultsModel.size();
filterResults.values = resultsModel;
}
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
list = (ArrayList<ChartModel>) results.values;
notifyDataSetChanged();
}
};
}
}
Any suggestion will be of great help. Thank you for your time.
Change your adapter class like this
public class ChartListAdapter extends BaseAdapter implements Filterable {
ArrayList<ChartModel> list;
ArrayList<ChartModel> filteredList;
Context context;
public ChartListAdapter(ArrayList<ChartModel> list, Context context) {
this.list = list;
this.filteredList = list;
this.context = context;
}
#Override
public int getCount() {
if(filteredList != null) {
return filteredList.size();
} else {
return 0;
}
}
#Override
public Object getItem(int i) {
return filteredList.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
if(view == null) {
view = View.inflate(context, R.layout.chart_card, null);
}
TextView chart_name = view.findViewById(R.id.chart_name);
SwitchCompat switchCompat = view.findViewById(R.id.chart_selected);
switchCompat.setTag(filteredList.get(i).getChart_id());
chart_name.setText(filteredList.get(i).getChart_name());
switchCompat.setChecked(filteredList.get(i).getCard_selected());
switchCompat.setOnCheckedChangeListener((compoundButton, b) -> {
String getTag = compoundButton.getTag().toString();
Toast.makeText(context, getTag + " is selected :" + b, Toast.LENGTH_LONG).show();
});
return view;
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if(constraint == null || constraint.length() == 0){
filteredList = list;
}else{
ArrayList<ChartModel> resultsModel = new ArrayList<>();
String searchStr = constraint.toString().toLowerCase();
for(ChartModel itemsModel:list){
if(itemsModel.getChart_id().contains(searchStr)){
resultsModel.add(itemsModel);
}
filteredList = resultsModel;
}
}
filterResults.values = filteredList;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredList = (ArrayList<ChartModel>) results.values;
notifyDataSetChanged();
}
};
}
}

Implementing Search Function to search in ListView by specific TextView

[Auction List Image][1] I am trying to implement a search function to search through the ListView by a specific TextView which is the ItemName TextView as shown in the image such as "Adidas Shoes" & "Nike Shoes" .That TextView is id as txtName. Currently, with these codes, there is no error, but the search function is not doing anything. How do I implement the search to actually search by looking through the txtName TextView?
Adapter:
public class AuctionListAdapter extends BaseAdapter implements Filterable {
ValueFilter valueFilter;
private Context context;
private int layout;
private ArrayList<Model> auctionList;
public AuctionListAdapter(Context context, int layout, ArrayList<Model> auctionList) {
this.context = context;
this.layout = layout;
this.auctionList = auctionList;
}
#Override
public int getCount() {
return auctionList.size();
}
#Override
public Object getItem(int position) {
return auctionList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public Filter getFilter() {
if (valueFilter == null) {
valueFilter = new ValueFilter();
}
return valueFilter;
}
private class ValueFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<Model> filterList = new ArrayList<Model>();
for (int i = 0; i < auctionList.size(); i++) {
if ((auctionList.get(i).getName().toUpperCase())
.contains(constraint.toString().toUpperCase())) {
Model model = new Model(auctionList.get(i).getId(),auctionList.get(i).getName(),
auctionList.get(i).getDescription(),auctionList.get(i).getPrice(),auctionList.get(i).getDuration()
,auctionList.get(i).getImage());
filterList.add(model);
}
}
results.count = filterList.size();
results.values = filterList;
} else {
results.count = auctionList.size();
results.values = auctionList;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
auctionList = (ArrayList<Model>) results.values;
notifyDataSetChanged();
}
}
private class ViewHolder{
ImageView imageView;
TextView txtName,txtDescription,txtPrice,txtDuration;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder = new ViewHolder();
if(row == null){
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(layout,null);
holder.txtName=row.findViewById(R.id.txtName);
holder.txtDescription=row.findViewById(R.id.txtDescription);
holder.txtPrice=row.findViewById(R.id.txtPrice);
holder.txtDuration=row.findViewById(R.id.txtDuration);
holder.imageView=row.findViewById(R.id.imgIcon);
row.setTag(holder);
}
else{
holder = (ViewHolder)row.getTag();
}
Model model = auctionList.get(position);
holder.txtName.setText(model.getName());
holder.txtDescription.setText(model.getDescription());
holder.txtPrice.setText(model.getPrice());
holder.txtDuration.setText(model.getDuration());
byte[] auctionImage = model.getImage();
Bitmap bitmap = BitmapFactory.decodeByteArray(auctionImage,0,auctionImage.length);
holder.imageView.setImageBitmap(bitmap);
return row;
}
}
AuctionList.java:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.searchmenu,menu);
MenuItem myActionMenuItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView)myActionMenuItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String text) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
mAdapter.getFilter().filter(newText);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
Create a private class inside your adapter
/**
* Custom filter for Brand list
* Filter content in brand list according to the search text
*/
private class BrandFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint!=null && constraint.length()>0) {
ArrayList<User> tempList = new ArrayList<User>();
// search content in Brand list
for (User user : brandList) {
if (mList.getBrandName().toLowerCase().contains(constraint.toString().toLowerCase())) {
tempList.add(user);
}
}
filterResults.count = tempList.size();
filterResults.values = tempList;
} else {
filterResults.count = friendList.size();
filterResults.values = friendList;
}
return filterResults;
}
/**
* Notify about filtered list to ui
* #param constraint text
* #param results filtered result
*/
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredList = (ArrayList<User>) results.values;
notifyDataSetChanged();
}
}
Implement Filterable to your adapter , and write the following code to your Override function getfilter.
if (brandFilter == null) {
Filter = new BrandFilter();
}
return friendFilter;
Just call this method inside your activity , on onQueryTextChange
mAdapetr.getFilter().filter(newText);
For temp list :
private ArrayList<Model> filteredList;
and in your constructor
this.filteredList = auctionList
while publishing result , /**
* Notify about filtered list to ui
* #param constraint text
* #param results filtered result
*/
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredList = (ArrayList<Model>) results.values;
notifyDataSetChanged();
}

Android Listview search filter (list empty after first search)

I am doing a search filter using filterable. I manage to get the search result when I search by keyword but the listview is empty after the first search. I want it to show all the data when the user input is null.
This is the code I edited. Now I cannot get any search result. Any idea which part still wrong?
public class ProductListAdapter extends BaseAdapter implements Filterable {
private Context context;
private int layout;
private ArrayList<Booth> productList= new ArrayList<>();
private ArrayList<Booth> tempList = new ArrayList<>();
private ValueFilter mFilter = new ValueFilter();
public ProductListAdapter(Context context, int layout, ArrayList<Booth> productList) {
this.context = context;
this.layout = layout;
this.productList = productList;
this.tempList = productList;
}
#Override
public int getCount() {
return tempList.size();
}
public void addItems(ArrayList<Booth> items) {
productList.addAll(items);
tempList.addAll(items);
notifyDataSetChanged();
}
#Override
public Object getItem(int position) {
return tempList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(
int position, View view, ViewGroup viewGroup) {
Typeface face_02 = Typeface.createFromAsset(context.getAssets(), "customfont/grb.otf");
ViewHolder holder = new ViewHolder();
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(layout, null);
holder.Boothname = (TextView) view.findViewById(R.id.Boothname);
holder.Rating = (TextView) view.findViewById(R.id.Rating);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
Booth product = productList.get(position);
holder.Boothname.setText(product.getBoothName());
holder.Rating.setText(product.getRating());
holder.Rating.setTypeface(face_02);
holder.Boothname.setTypeface(face_02);
return view;
}
#Override
public Filter getFilter() {
return mFilter;
}
private class ValueFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<Booth> filterList = new ArrayList<Booth>();
constraint = constraint.toString().toLowerCase();
for (int i = 0; i < productList.size(); i++) {
if ((productList.get(i).getBoothName().toLowerCase())
.contains(constraint.toString().toLowerCase())) {
Booth boothdata = new Booth(productList.get(i)
.getBoothName(), productList.get(i)
.getRating());
filterList.add(boothdata);
}
}
results.count = filterList.size();
results.values = filterList;
} else {
results.count = productList.size();
results.values = productList;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
tempList = (ArrayList<Booth>) results.values;
notifyDataSetChanged();
}
}
class ViewHolder {
TextView Boothname, Rating;
}
}
This is happened because you are updating your original list when user search anything.You have to use tempList which is hold temporary data and used to show search result,it is also used to shows list initially.And ProductList contains original list and it is used to compare with the search string.
Initialize variable
private List<Booth> productList=new ArrayList<>(); //you have already done this,this contains original list
private List<Booth> tempList=new ArrayList<>(); //add this one is to show search result
Method for the add data should be like this:
public void addItems(List<Booth> items) {
productList.addAll(items);
tempList.addAll(items);
notifyDataSetChanged();
}
Method for the remove data should be like this:
public void removeItems(){
productList.clear();
tempList.clear();
}
getItem and getCount method should be like this:
#Override
public int getCount() {
return tempList.size();
}
#Override
public Booth getItem(int position) {
return tempList.get(position);
}
ValueFilter should be like this:
private class ValueFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
//filter list as a local variable
ArrayList<Booth> filterList = new ArrayList<Booth>();
constraint = constraint.toString().toLowerCase();
for (int i = 0; i < productList.size(); i++) {
if ((productList.get(i).getBoothName().toLowerCase())
.startsWith(constraint.toString().toLowerCase())) {
Booth boothdata = new Booth(productList.get(i)
.getBoothName(), productList .get(i)
.getRating());
filterList.add(boothdata);
}
}
results.count = filterList.size();
results.values = filterList;
Log.e("VALUES", results.values.toString());
} else {
results.count = productList.size();
results.values = productList;
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
tempList = (ArrayList<Booth>) results.values;
notifyDataSetChanged();
}
}
yes, you got this error. Why? Because after searchings, from times to times, your productList loses its product. So, how to resolve it? You should make filter data for filtering only and you will search in the filter data instead of your productList as below:
filterList = new List<Product>()// do clone here when you set new data to your list.
// then in the performFiltering(), use filterList instead.
for (int i = 0; i < filterList.size(); i++) {
if ((filterList.get(i).getBoothName().toLowerCase())
.startsWith(constraint.toString().toLowerCase())) {
Booth boothdata = new Booth(filterList.get(i)
.getBoothName(), filterList.get(i)
.getRating());
filterList.add(boothdata);
}
}
This is what you should do.
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
productList = (ArrayList<Booth>) results.values; // if you use templist here, there's no change in getView
notifyDataSetChanged();
}

How to create custom BaseAdapter for AutoCompleteTextView

I've been having difficulty creating a custom ArrayAdapter for AutoCompleteTextView such errors that would come up despite following code found on the internet would be:
Dropdown would not appear.
Custom Objects and their details would not appear.
So for those who are having or had the same problem as me, I recommend using BaseAdapter for AutoCompleteTextView instead.
The following is my working code using ArrayAdapter.
Let's assume the reponse data from web service looks like the following:
[
{
"id": "1",
"name": "Information Technology"
},
{
"id": "2",
"name": "Human Resources"
},
{
"id": "3",
"name": "Marketing and PR"
},
{
"id": "4",
"name": "Research and Developement"
}
]
Then in your Android client:
Department class:
public class Department {
public int id;
public String name;
}
Custom Adapter class:
public class DepartmentArrayAdapter extends ArrayAdapter<Department> {
private final Context mContext;
private final List<Department> mDepartments;
private final List<Department> mDepartmentsAll;
private final int mLayoutResourceId;
public DepartmentArrayAdapter(Context context, int resource, List<Department> departments) {
super(context, resource, departments);
this.mContext = context;
this.mLayoutResourceId = resource;
this.mDepartments = new ArrayList<>(departments);
this.mDepartmentsAll = new ArrayList<>(departments);
}
public int getCount() {
return mDepartments.size();
}
public Department getItem(int position) {
return mDepartments.get(position);
}
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
try {
if (convertView == null) {
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(mLayoutResourceId, parent, false);
}
Department department = getItem(position);
TextView name = (TextView) convertView.findViewById(R.id.textView);
name.setText(department.name);
} catch (Exception e) {
e.printStackTrace();
}
return convertView;
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
public String convertResultToString(Object resultValue) {
return ((Department) resultValue).name;
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
List<Department> departmentsSuggestion = new ArrayList<>();
if (constraint != null) {
for (Department department : mDepartmentsAll) {
if (department.name.toLowerCase().startsWith(constraint.toString().toLowerCase())) {
departmentsSuggestion.add(department);
}
}
filterResults.values = departmentsSuggestion;
filterResults.count = departmentsSuggestion.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mDepartments.clear();
if (results != null && results.count > 0) {
// avoids unchecked cast warning when using mDepartments.addAll((ArrayList<Department>) results.values);
for (Object object : (List<?>) results.values) {
if (object instanceof Department) {
mDepartments.add((Department) object);
}
}
notifyDataSetChanged();
} else if (constraint == null) {
// no filter, add entire original list back in
mDepartments.addAll(mDepartmentsAll);
notifyDataSetInvalidated();
}
}
};
}
}
Main Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView);
mAutoCompleteTextView.setThreshold(1);
new DepartmentRequest().execute();
}
private class DepartmentRequest extends AsyncTask<Void, Void, JSONArray> {
#Override
protected JSONArray doInBackground(Void... voids) {
OkHttpJsonArrayRequest request = new OkHttpJsonArrayRequest();
try {
return request.get("http://...");
} catch (IOException | JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(JSONArray jsonArray) {
super.onPostExecute(jsonArray);
if (jsonArray != null && jsonArray.length() > 0) {
Gson gson = new Gson();
Department[] departments = gson.fromJson(jsonArray.toString(), Department[].class);
mDepartmentList = Arrays.asList(departments);
mDepartmentArrayAdapter = new DepartmentArrayAdapter(mContext, R.layout.simple_text_view, mDepartmentList);
mAutoCompleteTextView.setAdapter(mDepartmentArrayAdapter);
}
}
}
private class OkHttpJsonArrayRequest {
OkHttpClient client = new OkHttpClient();
// HTTP GET REQUEST
JSONArray get(String url) throws IOException, JSONException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return new JSONArray(response.body().string());
}
}
Here's the screenshot:
Hope this helps!
Custom BaseAdapter Class
public class ObjectAdapter extends BaseAdapter implements Filterable {
private Context context;
private ArrayList<Object> originalList;
private ArrayList<Object> suggestions = new ArrayList<>();
private Filter filter = new CustomFilter();
/**
* #param context Context
* #param originalList Original list used to compare in constraints.
*/
public ObjectAdapter(Context context, ArrayList<Object> originalList) {
this.context = context;
this.originalList = originalList;
}
#Override
public int getCount() {
return suggestions.size(); // Return the size of the suggestions list.
}
#Override
public Object getItem(int position) {
return suggestions.get(position).getCountryName();
}
#Override
public long getItemId(int position) {
return 0;
}
/**
* This is where you inflate the layout and also where you set what you want to display.
* Here we also implement a View Holder in order to recycle the views.
*/
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.adapter_autotext,
parent,
false);
holder = new ViewHolder();
holder.autoText = (TextView) convertView.findViewById(R.id.autoText);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.autoText.setText(suggestions.get(position).getCountryName());
return convertView;
}
#Override
public Filter getFilter() {
return filter;
}
private static class ViewHolder {
TextView autoText;
}
/**
* Our Custom Filter Class.
*/
private class CustomFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
suggestions.clear();
if (originalList != null && constraint != null) { // Check if the Original List and Constraint aren't null.
for (int i = 0; i < originalList.size(); i++) {
if (originalList.get(i).getCountryName().toLowerCase().contains(constraint)) { // Compare item in original list if it contains constraints.
suggestions.add(originalList.get(i)); // If TRUE add item in Suggestions.
}
}
}
FilterResults results = new FilterResults(); // Create new Filter Results and return this to publishResults;
results.values = suggestions;
results.count = suggestions.size();
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
Main Activity Class
public class MainActivity extends AppCompatActivity{
private SGetCountryListAdapter countryAdapter;
private ArrayList<SGetCountryList> countryList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
country = (AutoCompleteTextView) findViewById(R.id.country);
countryAdapter = new SGetCountryListAdapter(getApplicationContext(),
ConnectionParser.SGetCountryList);
country.setAdapter(countryAdapter);
country.setThreshold(1);
}
}
Drop down layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/autoText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:textColor="#color/black" />
</LinearLayout>
My Original List has data taken from web service so let's just assume that it already has data. Of course you can customize the dropdown even more by adding more views, just don't forget to update the adapter in order to incorporate the new views.

No results with custom ArrayAdapter Filter

I'm using the ArrayAdapter on a AutoCompleteTextView. results.values has the expected value but I get no list on the UI.
public class CustomArrayAdapter extends ArrayAdapter<String> implements Filterable {
private final Object mLock = new Object();
private CustomFilter mFilter;
public ArrayList<String> mItems;
public ArrayList<String> mFiltered;
public CustomArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
mItems = new ArrayList<String>();
mFiltered = new ArrayList<String>();
}
public Filter getFilter() {
if (mFilter == null) {
mFilter = new CustomFilter();
}
return mFilter;
}
#Override
public void add(String s) {
mItems.add(s);
}
private class CustomFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (mItems == null) {
synchronized (mLock) {
mItems = new ArrayList<String>();
}
}
if (constraint == null || constraint.length() == 0) {
synchronized (mLock) {
results.values = mItems;
results.count = mItems.size();
}
} else {
final ArrayList<String> newItems = new ArrayList<String>();
for (int i = 0; i < mItems.size(); i++) {
final String item = mItems.get(i);
if(item.contains(constraint)) {
newItems.add(item);
}
}
results.values = newItems;
results.count = newItems.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
mFiltered.clear();
mFiltered.addAll((ArrayList<String>) results.values);
notifyDataSetChanged();
}
}
}
Looks like overriding a couple more functions did the job.
Full source of working version:
public class CustomArrayAdapter extends ArrayAdapter<String> implements Filterable {
private List<String> mOrigionalValues;
private List<String> mObjects;
private Filter mFilter;
public CustomArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
mOrigionalValues = new ArrayList<String>();
mObjects = new ArrayList<String>();
}
public void add(String object) {
mOrigionalValues.add(object);
this.notifyDataSetChanged();
}
#Override
public int getCount() {
return mObjects.size();
}
#Override
public String getItem(int position) {
return mObjects.get(position);
}
public Filter getFilter() {
if (mFilter == null) {
mFilter = new CustomFilter();
}
return mFilter;
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
private class CustomFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if(constraint == null || constraint.length() == 0) {
ArrayList<String> list = new ArrayList<String>(mOrigionalValues);
results.values = list;
results.count = list.size();
} else {
ArrayList<String> newValues = new ArrayList<String>();
for(int i = 0; i < mOrigionalValues.size(); i++) {
String item = mOrigionalValues.get(i);
if(item.contains(constraint)) {
newValues.add(item);
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
mObjects = (List<String>) results.values;
Log.d("CustomArrayAdapter", String.valueOf(results.values));
Log.d("CustomArrayAdapter", String.valueOf(results.count));
notifyDataSetChanged();
}
}
}
You need overwrite getCount method in CustomArrayAdapter:
#Override
public int getCount() {
return mFiltered.size();
}
And modify your publishResults method code:
protected void publishResults(CharSequence constraint,FilterResults results) {
mFiltered = (List<String>) results.values;
notifyDataSetChanged();
}
There are some days I have been researching on the net about how to do research in arraylist with hashmap and luckily I came across this post.
I made my adaptation to arraylist > and it worked. And now I'm sharing with you, you will know there is someone like the same question using ArrayList and HashMap. Thank you Pim Reijersen!
public class CategoriaAdapterModel extends BaseAdapter implements Filterable {
private Activity context;
private ArrayList<HashMap<String, String>> mDataShown;
private ArrayList<HashMap<String, String>> mAllData;
private Filter mFilter;
private LayoutInflater inflater;
DownloadImagemUtil downloader;
public CategoriaAdapterModel(Activity context,
ArrayList<HashMap<String, String>> data) {
this.context = context;
this.mAllData = data;
this.mDataShown = data;
downloader = new DownloadImagemUtil(context);
}
public void add(HashMap<String, String> object) {
mAllData.add(object);
this.notifyDataSetChanged();
}
public int getCount() {
return mDataShown.size();
}
public Object getItem(int position) {
return mDataShown.get(position);
}
public long getItemId(int position) {
return position;
}
public Filter getFilter() {
if (mFilter == null) {
mFilter = new CustomFilter();
}
return mFilter;
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
private class CustomFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0) {
ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>(
mAllData);
results.values = list;
results.count = list.size();
} else {
ArrayList<HashMap<String, String>> newValues = new ArrayList<HashMap<String, String>>();
for (int i = 0; i < mAllData.size(); i++) {
HashMap<String, String> item = mAllData.get(i);
if (item.get(JsonFragmentCategoriaCONN.TAG_NOME)
.toLowerCase()
.contains(constraint.toString().toLowerCase())) {
newValues.add(item);
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
mDataShown = (ArrayList<HashMap<String, String>>) results.values;
Log.d("CustomArrayAdapter", String.valueOf(results.values));
Log.d("CustomArrayAdapter", String.valueOf(results.count));
notifyDataSetChanged();
}
}

Categories

Resources