0

In my android app, I encounter a problem during the implementation of the message "no result found" for my search bar. When I type a character that already should produce no result the message doesn't appear. To make it appears I should type another character But if now I delete this second character it shows the no result message (as it should have shown from the beginning). Furthermore, if I delete this character, making the search text empty, instead to show the full list it shows nothing. Making some debugging it seems that the getItemCount used in the onQueryText produce a size that corresponds to the list before the filtering operation (it is like it is always a step behind), but I don't understand why.

This is my code:

Custom Adapter:

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> implements Filterable {

    private final Activity destinationActivity;
    private ArrayList<HashMap<String, String>> items;
    private ArrayList<HashMap<String, String>> itemsFiltered = new ArrayList<>();
    private Fragment activity;
    private Context context;

    private static final String KEY_TITOLO = "titolo";
    private static final String KEY_FOTO = "foto";
    private static final String KEY_DESCRIZIONE = "descrizione";
    private static final String KEY_INDIRIZZO = "indirizzo";
    private static final String KEY_MAPS = "maps";
    private static final String KEY_LAT = "latitudine";
    private static final String KEY_LONG = "longitudine";

    private static final String KEY_LAT_START = "latitudineinizio";
    private static final String KEY_LONG_START = "longitudineinizio";
    private static final String KEY_LAT_END = "latitudinefine";
    private static final String KEY_LONG_END = "longitudinefine";

    // Provide a suitable constructor (depends on the kind of dataset)
    public CustomAdapter(Context context,ArrayList<HashMap<String, String>> items, Fragment fragment, Activity destinationActivity) {
        this.items = items;
        this.activity = fragment;
        this.destinationActivity = destinationActivity;
        this.context = context;
        this.itemsFiltered = items;
        //inflater = (LayoutInflater) this.activity.get getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
        // set the view's size, margins, paddings and layout parameters
        return new MyViewHolder(v);
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {

        HashMap<String, String> mapPosition = itemsFiltered.get(position);
        
        holder.title.setText(mapPosition.get(KEY_TITOLO));

        Resources res = Objects.requireNonNull(activity.getActivity()).getResources();


        int resID = res.getIdentifier(mapPosition.get(KEY_FOTO), "drawable","myPackage");
        Drawable drawable = res.getDrawable(resID);
        holder.imageInList.setImageDrawable(drawable);

        holder.picture.setText(mapPosition.get(KEY_FOTO));
        holder.description.setText(mapPosition.get(KEY_DESCRIZIONE));
        holder.address.setText(mapPosition.get(KEY_INDIRIZZO));
        holder.maps.setText(mapPosition.get(KEY_MAPS));
        holder.latitude.setText(mapPosition.get(KEY_LAT));
        holder.longitude.setText(mapPosition.get(KEY_LONG));

        holder.latitudeStartingPoint.setText(mapPosition.get(KEY_LAT_START));
        holder.longitudeStartingPoint.setText(mapPosition.get(KEY_LONG_START));

        holder.latitudeEndingPoint.setText(mapPosition.get(KEY_LAT_END));
        holder.longitudeEndingPoint.setText(mapPosition.get(KEY_LONG_END));
    }

    @Override
    public int getItemCount() {
        return itemsFiltered != null ? itemsFiltered.size() : 0;
    }

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                String charString = charSequence.toString();

                ArrayList<HashMap<String, String>>   filteredList = new ArrayList<>();
                if (charString.isEmpty()) {
                    itemsFiltered = items;
                } else {

                    for (HashMap<String, String> row : items) {

                        // name match condition. this might differ depending on your requirement
                        // here we are looking for name or phone number match
                        if (row.get("titolo").toLowerCase().contains(charString.toLowerCase())) {
                            filteredList.add(row);
                        }
                    }
                }

                FilterResults results = new FilterResults();
                results.values = filteredList;
                results.count = filteredList.size();
                return results;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults results) {
                itemsFiltered = (ArrayList<HashMap<String, String>>) results.values;
                notifyDataSetChanged();
            }
        };
    }

    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        // each data item is just a string in this case
        private TextView title;
        private ImageView imageInList;
        private TextView picture;
        private TextView description;
        private TextView address;
        private TextView maps;
        private TextView latitude;
        private TextView longitude;

        private TextView latitudeStartingPoint;
        private TextView longitudeStartingPoint;
        private TextView latitudeEndingPoint;
        private TextView longitudeEndingPoint;

        MyViewHolder(View v) {
            super(v);

            title = v.findViewById(R.id.title);
            imageInList = v.findViewById((R.id.imageInList));
            picture = v.findViewById((R.id.picture));
            description = v.findViewById((R.id.description));
            address = v.findViewById((R.id.address));
            maps = v.findViewById((R.id.maps));
            latitude = v.findViewById((R.id.latitude));
            longitude = v.findViewById((R.id.longitude));

            latitudeStartingPoint = v.findViewById((R.id.latitude_starting_point));
            longitudeStartingPoint = v.findViewById((R.id.longitude_starting_point));
            latitudeEndingPoint = v.findViewById((R.id.latitude_ending_point));
            longitudeEndingPoint = v.findViewById((R.id.longitude_ending_point));

            v.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            String title = ((TextView) view.findViewById(R.id.title)).getText().toString();
            String picture = ((TextView) view.findViewById(R.id.picture)).getText().toString();
            String description = ((TextView) view.findViewById(R.id.description)).getText().toString();
            String address = ((TextView) view.findViewById(R.id.address)).getText().toString();
            String maps = ((TextView) view.findViewById(R.id.maps)).getText().toString();
            String latitude = ((TextView) view.findViewById(R.id.latitude)).getText().toString();
            String longitude = ((TextView) view.findViewById(R.id.longitude)).getText().toString();

            String latitudeStartingPoint = ((TextView) view.findViewById(R.id.latitude_starting_point)).getText().toString();
            String longitudeStartingPoint = ((TextView) view.findViewById(R.id.longitude_starting_point)).getText().toString();

            String latitudeEndingPoint = ((TextView) view.findViewById(R.id.latitude_ending_point)).getText().toString();
            String longitudeEndingPoint = ((TextView) view.findViewById(R.id.longitude_ending_point)).getText().toString();

            Intent in = new Intent(context,destinationActivity.getClass());
            in.putExtra(KEY_TITOLO, title);
            in.putExtra(KEY_FOTO, picture);
            in.putExtra(KEY_DESCRIZIONE, description);
            in.putExtra(KEY_INDIRIZZO, address);
            in.putExtra(KEY_MAPS, maps);
            in.putExtra(KEY_LAT, latitude);
            in.putExtra(KEY_LONG, longitude);
            in.putExtra(KEY_LAT_START, latitudeStartingPoint);
            in.putExtra(KEY_LONG_START, longitudeStartingPoint);
            in.putExtra(KEY_LAT_END, latitudeEndingPoint);
            in.putExtra(KEY_LONG_END, longitudeEndingPoint);
            activity.startActivity(in);
        }
    }

}

Class where I am using the search bar:

public class TouristicPointFragment extends Fragment {

    private SearchView searchView;
    private CustomAdapter mAdapter;
    private RecyclerView recyclerView;
    private TextView textView;

    private SearchView getSearchView() {
        return searchView;
    }

    private void setSearchView(SearchView searchView) {
        this.searchView = searchView;
    }

    public TouristicPointFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);

        View view = inflater.inflate(R.layout.fragment_turisticpoint, container, false);
        ArrayList<HashMap<String, String>> hashMapArrayList;

        recyclerView = view.findViewById(R.id.my_recycler_view);
        textView = view.findViewById(R.id.noResultsFoundView);
        recyclerView.setHasFixedSize(true);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
        recyclerView.setLayoutManager(layoutManager);

        hashMapArrayList = XMLParser.getData("turisticpoint",getContext());

        Activity singlePlaceActivity = new SinglePlaceActivity();

        mAdapter = new CustomAdapter(getContext(), hashMapArrayList, this, singlePlaceActivity);
        recyclerView.setAdapter(mAdapter);
        return view;
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.search_menu, menu);
        MenuItem item = menu.findItem(R.id.action_search);
        // MenuItemCompat.setShowAsAction(item, //MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | //MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
        //  MenuItemCompat.setActionView(item, searchView);
        // These lines are deprecated in API 26 use instead
        //item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM);
        setSearchView(new SearchView(Objects.requireNonNull(((MainActivity) Objects.requireNonNull(getContext())).getSupportActionBar()).getThemedContext()));
        item.setActionView(getSearchView());

        getSearchView().setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                mAdapter.getFilter().filter(query);
                return false;
            }
            @Override
            public boolean onQueryTextChange(String query) {
                mAdapter.getFilter().filter(query);
               
                
                if((mAdapter.getItemCount == 0)&&(!query.equals(""))){
                    recyclerView.setVisibility(View.GONE);
                    textView.setVisibility(View.VISIBLE);
                    textView.setText(String.format("%s '%s'", getResources().getString(R.string.no_result), query));
                }else{
                    recyclerView.setVisibility(View.VISIBLE);
                    textView.setVisibility(View.GONE);
                }
                return false;
            }
        });
        getSearchView().setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {

              }
          }
        );
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_search) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    // close search view on back button pressed
    boolean collapseSearch() {

        boolean searchViewOpen = false;

        SearchView searchView = getSearchView();

        if(searchView!=null){
            String searchViewContent = searchView.getQuery().toString();
            if (!searchViewContent.equals("")||(!searchView.isIconified())) {

                searchView.setQuery("", false);
                //Collapse the action view
                searchView.onActionViewCollapsed();
                //Collapse the search widget
                //searchView.collapseActionView();
                searchView.setIconified(true);
                searchViewOpen = true;
            }
        }

        return searchViewOpen;
    }

}

Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/noResultsFoundView"
        android:textSize="16dp"
        android:layout_marginTop="30px"
        android:textAlignment="center"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/no_result"
        android:visibility="gone"
        android:gravity="center_horizontal" />

    <androidx.recyclerview.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/my_recycler_view"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

Edited version:

private ArrayList<HashMap<String, String>> mOriginalList;
private ArrayList<HashMap<String, String>> mFilteredList;

public CustomAdapter(Context context,ArrayList<HashMap<String, String>> items, Fragment fragment, Activity destinationActivity) {
        this.activity = fragment;
        this.destinationActivity = destinationActivity;
        this.context = context;
        this.mFilteredList = items;
        //inflater = (LayoutInflater) this.activity.get getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }



@Override
    public int getItemCount() {
        return mFilteredList != null ? mFilteredList.size() : 0;
    }

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                String constraint = charSequence.toString().toLowerCase();

                FilterResults result = new FilterResults();

                if (mOriginalList == null) {
                    //mOriginalList = mFilteredList;
                    mOriginalList = new ArrayList<>(mFilteredList);
                }

                if (constraint.isEmpty()) {
                    result.values = mOriginalList;
                    result.count = mOriginalList.size();
                } else {
                    ArrayList < HashMap < String, String >> list = new ArrayList<>();
                    for (HashMap < String, String > item: mOriginalList) {
                        String title = item.get("titolo");
                        boolean contains = false;
                        if (title != null) {
                            contains = title.toLowerCase().contains(constraint);
                        }
                        if (contains) {
                            list.add(item);
                        }
                    }
                    result.values = list;
                    result.count = list.size();
                }
                return result;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                mFilteredList.clear();
                mFilteredList.addAll((ArrayList <HashMap<String,String >>) results.values);
                notifyDataSetChanged();
            }
        };
    }
TheOldBlackbeard
  • 395
  • 4
  • 22
  • Lists inside adapter are created in a wrong way. Take a look of my explanation here: https://stackoverflow.com/questions/60578732/filter-in-listview-did-not-filter-from-the-full-list-but-from-already-filtered/60668070#60668070 – i_A_mok Aug 11 '20 at 11:18
  • I read the discussion, and I edit my code (i posted in the question the edited version) but it didn't fix my problem. – TheOldBlackbeard Aug 15 '20 at 21:23
  • 1
    https://stackoverflow.com/questions/61570173/display-no-results-found – i_A_mok Aug 16 '20 at 13:37

0 Answers0