Search code examples
androidandroid-recyclerviewandroid-roomsearchviewandroid-search

The Search View is not giving any result in my Fragment containing RecyclerView. After I click on the Search icon the screen is just blank


I have a fragment with RecyclerView and Room Database and I want to add a search view. I have successfully added the search icon and also added the code in the Fragment as well as Adapter. But the problem is that when I click on the Search icon, the screen is blank. Also, when I type anything it doesn't give me any result. If I close the Search View and click on back button, the RecyclerView in Fragment is no more visible. I have checked the solution online and it uses similar code. So, I can't understand what is the mistake in my code. can anyone help me please?

My Fragment Code '''

package com.nitin.roomrecyclerview;

import androidx.appcompat.widget.SearchView;
import androidx.core.view.MenuItemCompat;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;

import android.content.Intent;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.provider.ContactsContract;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.ArrayList;
import java.util.List;

public class FragmentStatus extends Fragment implements MyViewHolder.OnStatusListener, SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener  {

    private FragmentStatusViewModel mViewModel;
    private RecyclerView recyclerView;
    private RecyclerView.LayoutManager layoutManager;
    private MyAdapter mAdapter;
    FloatingActionButton floatingActionButton;
    Bundle bundletest;
    Bundle bundletest1;

    Status status;
    private List<Status> statuses = new ArrayList<>();


    public static FragmentStatus newInstance() {
        return new FragmentStatus();
    }



    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Inflate the menu; this adds items to the action bar if it is present.

        inflater.inflate(R.menu.main, menu);
        MenuItem menuItem = menu.findItem(R.id.search);

        SearchView searchView = (SearchView) menuItem.getActionView();
        searchView.setOnQueryTextListener(this);

        super.onCreateOptionsMenu(menu, inflater);
    }


    @Override
    public boolean onQueryTextSubmit(String query) {

        return false;
    }



    @Override
    public boolean onQueryTextChange(String newText) {


        if (newText == null || newText.trim().isEmpty()) {

            mAdapter.setfilter(statuses);
            return false;

        } else {

            newText = newText.toLowerCase();
            List<Status> newList = new ArrayList<>();
            for (Status status : statuses) {

                if (status.getTitle().toLowerCase().contains(newText)){

                    newList.add(status);

                }

            }
            Toast.makeText(getActivity(), "newtext" + newText, Toast.LENGTH_SHORT).show();
            mAdapter.setfilter(newList);
            return true;
        }
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {

        switch (item.getItemId()){

            case R.id.deleteallstatus:

                FragmentStatusViewModel mViewModel = new ViewModelProvider(this).get(FragmentStatusViewModel.class);
                mViewModel.deleteAllStatus();
                Toast.makeText(getActivity(), "All Status Deleted", Toast.LENGTH_SHORT).show();
                return true;

            case R.id.action_settings:

                Toast.makeText(getActivity(), "Setting Selected", Toast.LENGTH_SHORT).show();
                return true;

            default:

                return super.onOptionsItemSelected(item);

        }


    }

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);

    }


    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
     //  setHasOptionsMenu(true);
        return inflater.inflate(R.layout.fragment_status_fragment, container, false);

    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        recyclerView = (getActivity()).findViewById(R.id.statusRecyclerView);
        layoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setHasFixedSize(true);

        floatingActionButton = getActivity().findViewById(R.id.button_add_status);
        floatingActionButton.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_fragmentStatus_to_updateFragment, null));

        //status = new Status(title,description);
        mAdapter = new MyAdapter(statuses, this);
        recyclerView.setAdapter(mAdapter);
        mViewModel = new ViewModelProvider(this).get(FragmentStatusViewModel.class);
        mViewModel.getAllStatus().observe(getViewLifecycleOwner(), new Observer<List<Status>>() {
            @Override
            public void onChanged(List<Status> statuses) {

                mAdapter.setStatuses(statuses);

            }


        });



        if(getArguments() != null && getArguments().containsKey("ID") == true && bundletest != getArguments()){
            int id = getArguments().getInt("ID", -1);
            if(id == -1){

                Toast.makeText(getActivity(), "Status can't be updated", Toast.LENGTH_LONG).show();

            }
            String title = getArguments().getString("title1");
            String description = getArguments().getString("description1");


            Status status = new Status(title,description);
            mViewModel.update(status);
            status.setId(id);
            bundletest = getArguments();
            Toast.makeText(getActivity(), "Status updated" + id, Toast.LENGTH_LONG).show();

        }else if (getArguments() != null && !getArguments().containsKey("ID") && bundletest1 != getArguments()){

            String title = getArguments().getString("title");
            String description = getArguments().getString("description");


            Status status = new Status(title,description);
            mViewModel.insert(status);
            bundletest1 = getArguments();
            Toast.makeText(getActivity(), "Status saved", Toast.LENGTH_LONG).show();
        }else {

            Toast.makeText(getActivity(), "Statuses displayed!", Toast.LENGTH_SHORT).show();

        }

        new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT |
                ItemTouchHelper.RIGHT) {
            @Override
            public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
                return false;
            }

            @Override
            public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {

                mViewModel.delete(mAdapter.getStatusAt(viewHolder.getAdapterPosition()));
                Toast.makeText(getActivity(), "Note Deleted", Toast.LENGTH_LONG).show();

            }
        }).attachToRecyclerView(recyclerView);

    }


    @Override
    public void onStatusClick(Status status) {

        Toast.makeText(getActivity(), "the id is " + status.getId(), Toast.LENGTH_SHORT).show();
        Bundle bundle = new Bundle();
        bundle.putInt("ID", status.getId());
        bundle.putString("description", status.getDescription());
        bundle.putString("title", status.getTitle());

        Navigation.findNavController(getActivity().findViewById(R.id.recyclerLayout)).navigate(R.id.action_fragmentStatus_to_editStatusFragment, bundle);

    }


    @Override
    public boolean onMenuItemActionExpand(MenuItem item) {
        return true;
    }

    @Override
    public boolean onMenuItemActionCollapse(MenuItem item) {
        mAdapter.setfilter(statuses);
        return true;
    }
}

'''

My Adapter Code
'''
package com.nitin.roomrecyclerview;

import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {

    private List<Status> statuses = new ArrayList<>();

    private MyViewHolder.OnStatusListener listener;

    public MyAdapter(List<Status> statuses, MyViewHolder.OnStatusListener listener) {
        this.statuses = statuses;
        this.listener = listener;

    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view = inflater.inflate(R.layout.status_recyclerview, parent, false);
        MyViewHolder myViewHolder = new MyViewHolder(view, listener, statuses);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {

        Status status = statuses.get(position);
        holder.title_template.setText(status.getTitle());
        holder.description_template.setText(status.getDescription());



    }

    @Override
    public int getItemCount() {
        return statuses.size();
    }

    public void setStatuses(List<Status> statuses){

        this.statuses = statuses;
        notifyDataSetChanged();

    }

    public Status getStatusAt(int position){

        return statuses.get(position);

    }


        public void setfilter(List<Status> newList){

            statuses.clear();
            statuses.addAll(newList);
            notifyDataSetChanged();

        }

}

'''

My ViewHolder Code

'''

package com.nitin.roomrecyclerview;

import android.view.View;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    public TextView title_template;
    public TextView description_template;
    private List<Status> statuses = new ArrayList<>();
    OnStatusListener listener;
    //Status status;


    public MyViewHolder(@NonNull View itemView, OnStatusListener listener, List<Status> statuses) {
        super(itemView);

        this.title_template = itemView.findViewById(R.id.title_template);
        this.description_template = itemView.findViewById(R.id.description_template);
        this.listener = listener;
        this.statuses = statuses;

        itemView.setOnClickListener(this);

    }




    @Override
    public void onClick(View v) {


        listener.onStatusClick(statuses.get(getAdapterPosition()));


            }



    interface OnStatusListener{

        void onStatusClick(Status status);

    }
}

'''

My Menu XML Code

'''

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="@string/action_settings"
        app:showAsAction="never" />

    <item
        android:id="@+id/deleteallstatus"
        android:orderInCategory="100"
        android:title="Delete all status"
        app:showAsAction="never" />

    <item
        android:id="@+id/search"
        android:orderInCategory="100"
        android:icon="@drawable/ic_search"
        app:showAsAction="ifRoom|collapseActionView"
        android:title="Search"
        app:actionViewClass="androidx.appcompat.widget.SearchView" />




</menu>

'''


Solution

  • As I am using LiveData...the code is as follows

    I had to implement Filterable in Adapter...and then the codes as shown below.

    In Fragment '''

    package com.nitin.roomrecyclerview;
    
    import androidx.activity.OnBackPressedCallback;
    import androidx.appcompat.widget.SearchView;
    import androidx.core.view.MenuItemCompat;
    import androidx.lifecycle.Observer;
    import androidx.lifecycle.ViewModel;
    import androidx.lifecycle.ViewModelProvider;
    import androidx.lifecycle.ViewModelProviders;
    
    import android.app.SearchManager;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    import androidx.navigation.Navigation;
    import androidx.recyclerview.widget.ItemTouchHelper;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;
    
    import android.provider.ContactsContract;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Toast;
    
    import com.google.android.material.floatingactionbutton.FloatingActionButton;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class FragmentStatus extends Fragment implements MyViewHolder.OnStatusListener {
    
        private FragmentStatusViewModel mViewModel;
        private RecyclerView recyclerView;
        private RecyclerView.LayoutManager layoutManager;
        private MyAdapter mAdapter;
        FloatingActionButton floatingActionButton;
        Bundle bundletest;
        Bundle bundletest1;
    
        private List<Status> statuses = new ArrayList<>();
    
    
        public static FragmentStatus newInstance() {
            return new FragmentStatus();
        }
    
    
    
        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            // Inflate the menu; this adds items to the action bar if it is present.
    
            inflater.inflate(R.menu.main, menu);
            MenuItem menuItem = menu.findItem(R.id.search);
    
            SearchView searchView = (SearchView) menuItem.getActionView();
            searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String query) {
    
                    return false;
                }
    
                @Override
                public boolean onQueryTextChange(String newText) {
    
                    mAdapter.getFilter().filter(newText);
                    return true;
                }
            });
    
            super.onCreateOptionsMenu(menu, inflater);
        }
    
    
    
    
        @Override
        public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    
            switch (item.getItemId()){
    
                case R.id.deleteallstatus:
    
                    FragmentStatusViewModel mViewModel = new ViewModelProvider(this).get(FragmentStatusViewModel.class);
                    mViewModel.deleteAllStatus();
                    Toast.makeText(getActivity(), "All Status Deleted", Toast.LENGTH_SHORT).show();
                    return true;
    
                case R.id.action_settings:
    
                    Toast.makeText(getActivity(), "Setting Selected", Toast.LENGTH_SHORT).show();
                    return true;
    
                default:
    
                    return super.onOptionsItemSelected(item);
    
            }
    
    
        }
    
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setHasOptionsMenu(true);
    
        }
    
    
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                                 @Nullable Bundle savedInstanceState) {
         //  setHasOptionsMenu(true);
            return inflater.inflate(R.layout.fragment_status_fragment, container, false);
    
        }
    
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
    
            recyclerView = (getActivity()).findViewById(R.id.statusRecyclerView);
            layoutManager = new LinearLayoutManager(getActivity());
            recyclerView.setLayoutManager(layoutManager);
            recyclerView.setHasFixedSize(true);
    
            floatingActionButton = getActivity().findViewById(R.id.button_add_status);
            floatingActionButton.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_fragmentStatus_to_updateFragment, null));
    
            //status = new Status(title,description);
            mAdapter = new MyAdapter(getActivity(), statuses, this);
            recyclerView.setAdapter(mAdapter);
            mViewModel = new ViewModelProvider(this).get(FragmentStatusViewModel.class);
            mViewModel.getAllStatus().observe(getViewLifecycleOwner(), new Observer<List<Status>>() {
                @Override
                public void onChanged(List<Status> statuses) {
    
                    mAdapter.setStatuses(statuses);
    
                }
    
    
            });
    
    
    
            if(getArguments() != null && getArguments().containsKey("ID") == true && bundletest != getArguments()){
                int id = getArguments().getInt("ID", -1);
                if(id == -1){
    
                    Toast.makeText(getActivity(), "Status can't be updated", Toast.LENGTH_LONG).show();
    
                }
                String title = getArguments().getString("title1");
                String description = getArguments().getString("description1");
    
    
                Status status = new Status(title,description);
                mViewModel.update(status);
                status.setId(id);
                bundletest = getArguments();
                Toast.makeText(getActivity(), "Status updated" + id, Toast.LENGTH_LONG).show();
    
            }else if (getArguments() != null && !getArguments().containsKey("ID") && bundletest1 != getArguments()){
    
                String title = getArguments().getString("title");
                String description = getArguments().getString("description");
    
    
                Status status = new Status(title,description);
                mViewModel.insert(status);
                bundletest1 = getArguments();
                Toast.makeText(getActivity(), "Status saved", Toast.LENGTH_LONG).show();
            }else {
    
                Toast.makeText(getActivity(), "Statuses displayed!", Toast.LENGTH_SHORT).show();
    
            }
    
            new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT |
                    ItemTouchHelper.RIGHT) {
                @Override
                public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
                    return false;
                }
    
                @Override
                public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
    
                    mViewModel.delete(mAdapter.getStatusAt(viewHolder.getAdapterPosition()));
                    Toast.makeText(getActivity(), "Note Deleted", Toast.LENGTH_LONG).show();
    
                }
            }).attachToRecyclerView(recyclerView);
    
        }
    
    
        @Override
        public void onStatusClick(Status status) {
    
            Toast.makeText(getActivity(), "the id is " + status.getId(), Toast.LENGTH_SHORT).show();
            Bundle bundle = new Bundle();
            bundle.putInt("ID", status.getId());
            bundle.putString("description", status.getDescription());
            bundle.putString("title", status.getTitle());
    
            Navigation.findNavController(getActivity().findViewById(R.id.recyclerLayout)).navigate(R.id.action_fragmentStatus_to_editStatusFragment, bundle);
    
        }
    
    
    }
    

    '''

    Adapter Code '''

    package com.nitin.roomrecyclerview;
    
    import android.content.Context;
    import android.content.Intent;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Filter;
    import android.widget.Filterable;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import androidx.activity.OnBackPressedCallback;
    import androidx.annotation.NonNull;
    import androidx.coordinatorlayout.widget.CoordinatorLayout;
    import androidx.navigation.Navigation;
    import androidx.recyclerview.widget.RecyclerView;
    
    import com.nitin.roomrecyclerview.ui.home.HomeFragment;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;
    import java.util.Locale;
    
    public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> implements Filterable {
    
        private static final String TAG = "TEST_1";
    
        private List<Status> statuses;
        private MyViewHolder.OnStatusListener listener;
        ArrayList<Status> arrayList = new ArrayList<>();
        Context context;
    
        public MyAdapter(Context context, List<Status> statuses, MyViewHolder.OnStatusListener listener) {
            this.statuses = statuses;
            this.listener = listener;
            this.context = context;
    
        }
    
    
        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            View view = inflater.inflate(R.layout.status_recyclerview, parent, false);
            MyViewHolder myViewHolder = new MyViewHolder(view, listener, statuses);
            return myViewHolder;
        }
    
        @Override
        public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    
            Status status = statuses.get(position);
            holder.title_template.setText(status.getTitle());
            holder.description_template.setText(status.getDescription());
    
    
        }
    
        @Override
        public int getItemCount() {
            return statuses.size();
        }
    
        public void setStatuses(List<Status> newstatuses) {
    
            this.statuses = newstatuses;
            arrayList.addAll(statuses);
            notifyDataSetChanged();
    
        }
    
        public Status getStatusAt(int position) {
    
            return statuses.get(position);
    
        }
    
    
        @Override
        public Filter getFilter() {
            return new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence constraint) {
    
                    constraint = constraint.toString().toLowerCase().trim();
                    statuses.clear();
                    if (constraint.length() == 0) {
                        statuses.addAll(arrayList);
                    } else {
                        for (Status item : arrayList) {
                            if (item.getTitle().toLowerCase(Locale.getDefault()).contains(constraint)
                                    || item.getDescription().toLowerCase(Locale.getDefault()).contains(constraint)) {
                                statuses.add(item);
                            }
                        }
                    }
    
                    FilterResults results = new FilterResults();
                    results.values = statuses;
                    results.count = statuses.size();
                    return results;
                }
    
                @Override
                protected void publishResults(CharSequence constraint, FilterResults results) {
                    if(results.count == 0){
    
                        Toast.makeText(context, "No Results found", Toast.LENGTH_LONG).show();
                        notifyDataSetChanged();
    
                    }else {
    
                        notifyDataSetChanged();
    
                    }
                }
            };
        }
    }
    

    '''