How to search a list of Objects that are displayed in a RecyclerView?











up vote
0
down vote

favorite
1












I am currently trying to implement a SearchView, but the displayed search results change only for the first Search, everything else I enter into SearchView is ignored.



Here is my Code for Searching in my MainActivity.java:



testList = Arrays.asList(new TestItem("aw"), new TestItem("aa"), new TestItem("w"));

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.test_menu, menu);

SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setOnQueryTextListener(this);
return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onQueryTextChange(String newText) {
List<TestItem> result = new ArrayList<>();
for(TestItem t: testList) {
if(t.getName().contains(newText) {
result.add(t);
}
}
adapter.changeList(result);
return true;
}


adapter.changeList:



public void changeList(List<TestItem> newList) {
this.list = new ArrayList<>(newList);
}


onQueryTextChange gets called after each text change, but the search result is shown only once. When entering a and Enter the RecyclerView shows aw and aa (is it normal to have to press Enter for onQueryTextChange to start?), but when I then enter aa the displayed items stay the same.










share|improve this question


























    up vote
    0
    down vote

    favorite
    1












    I am currently trying to implement a SearchView, but the displayed search results change only for the first Search, everything else I enter into SearchView is ignored.



    Here is my Code for Searching in my MainActivity.java:



    testList = Arrays.asList(new TestItem("aw"), new TestItem("aa"), new TestItem("w"));

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.test_menu, menu);

    SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
    searchView.setOnQueryTextListener(this);
    return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onQueryTextChange(String newText) {
    List<TestItem> result = new ArrayList<>();
    for(TestItem t: testList) {
    if(t.getName().contains(newText) {
    result.add(t);
    }
    }
    adapter.changeList(result);
    return true;
    }


    adapter.changeList:



    public void changeList(List<TestItem> newList) {
    this.list = new ArrayList<>(newList);
    }


    onQueryTextChange gets called after each text change, but the search result is shown only once. When entering a and Enter the RecyclerView shows aw and aa (is it normal to have to press Enter for onQueryTextChange to start?), but when I then enter aa the displayed items stay the same.










    share|improve this question
























      up vote
      0
      down vote

      favorite
      1









      up vote
      0
      down vote

      favorite
      1






      1





      I am currently trying to implement a SearchView, but the displayed search results change only for the first Search, everything else I enter into SearchView is ignored.



      Here is my Code for Searching in my MainActivity.java:



      testList = Arrays.asList(new TestItem("aw"), new TestItem("aa"), new TestItem("w"));

      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.test_menu, menu);

      SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
      searchView.setOnQueryTextListener(this);
      return super.onCreateOptionsMenu(menu);
      }

      @Override
      public boolean onQueryTextChange(String newText) {
      List<TestItem> result = new ArrayList<>();
      for(TestItem t: testList) {
      if(t.getName().contains(newText) {
      result.add(t);
      }
      }
      adapter.changeList(result);
      return true;
      }


      adapter.changeList:



      public void changeList(List<TestItem> newList) {
      this.list = new ArrayList<>(newList);
      }


      onQueryTextChange gets called after each text change, but the search result is shown only once. When entering a and Enter the RecyclerView shows aw and aa (is it normal to have to press Enter for onQueryTextChange to start?), but when I then enter aa the displayed items stay the same.










      share|improve this question













      I am currently trying to implement a SearchView, but the displayed search results change only for the first Search, everything else I enter into SearchView is ignored.



      Here is my Code for Searching in my MainActivity.java:



      testList = Arrays.asList(new TestItem("aw"), new TestItem("aa"), new TestItem("w"));

      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.test_menu, menu);

      SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
      searchView.setOnQueryTextListener(this);
      return super.onCreateOptionsMenu(menu);
      }

      @Override
      public boolean onQueryTextChange(String newText) {
      List<TestItem> result = new ArrayList<>();
      for(TestItem t: testList) {
      if(t.getName().contains(newText) {
      result.add(t);
      }
      }
      adapter.changeList(result);
      return true;
      }


      adapter.changeList:



      public void changeList(List<TestItem> newList) {
      this.list = new ArrayList<>(newList);
      }


      onQueryTextChange gets called after each text change, but the search result is shown only once. When entering a and Enter the RecyclerView shows aw and aa (is it normal to have to press Enter for onQueryTextChange to start?), but when I then enter aa the displayed items stay the same.







      android android-recyclerview searchview






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jul 7 '17 at 17:59









      sininen

      156210




      156210
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          I think your implementation is not correct. You don't need to press the enter for search result. For implementation you can keep a intact copy of your array list.Then make another temporary list form that list when query text is changed. So when you are filtering, you are searching the actual list not the filtered list.



          1.pass search keyword to the list adapter



          public boolean onQueryTextChange(String newText) {

          adapter.getFilter().filter(newText);
          return true;
          }


          2. In adapter implement Filterable and override method



          @Override
          public Filter getFilter() {
          if (frameFilter == null) {
          frameFilter = new FrameFilter();
          }

          return frameFilter;
          }


          3. Filtering class can be something like this: 'categoryMain' is my intact list and 'categoryTemp' is my temporary list



          private class FrameFilter extends Filter {

          @Override
          protected FilterResults performFiltering(CharSequence constraint) {

          FilterResults filterResults = new FilterResults();
          if (constraint != null && constraint.length() > 0) {
          ArrayList<Category> tempList = new ArrayList<>();

          // search content in friend list
          Log.i("key",constraint.toString());
          for (Category category : categoriesMain) {
          if (category.getCategory_name().toLowerCase().contains(constraint.toString().toLowerCase())) {
          tempList.add(category);
          }
          }
          filterResults.count = tempList.size();
          filterResults.values = tempList;
          } else {

          filterResults.count = categoriesMain.size();
          filterResults.values = categoriesMain.clone();
          }
          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) {

          categoriesTemp = (ArrayList<Category>) results.values;
          notifyDataSetChanged();
          }
          }





          share|improve this answer























          • Thank you very much for your help. Your solution works for me if I replace filterResults.values = categoriesMain.clone(); with filterResults.values = categoriesMain.
            – sininen
            Jul 8 '17 at 13:07











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f44977042%2fhow-to-search-a-list-of-objects-that-are-displayed-in-a-recyclerview%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          1
          down vote



          accepted










          I think your implementation is not correct. You don't need to press the enter for search result. For implementation you can keep a intact copy of your array list.Then make another temporary list form that list when query text is changed. So when you are filtering, you are searching the actual list not the filtered list.



          1.pass search keyword to the list adapter



          public boolean onQueryTextChange(String newText) {

          adapter.getFilter().filter(newText);
          return true;
          }


          2. In adapter implement Filterable and override method



          @Override
          public Filter getFilter() {
          if (frameFilter == null) {
          frameFilter = new FrameFilter();
          }

          return frameFilter;
          }


          3. Filtering class can be something like this: 'categoryMain' is my intact list and 'categoryTemp' is my temporary list



          private class FrameFilter extends Filter {

          @Override
          protected FilterResults performFiltering(CharSequence constraint) {

          FilterResults filterResults = new FilterResults();
          if (constraint != null && constraint.length() > 0) {
          ArrayList<Category> tempList = new ArrayList<>();

          // search content in friend list
          Log.i("key",constraint.toString());
          for (Category category : categoriesMain) {
          if (category.getCategory_name().toLowerCase().contains(constraint.toString().toLowerCase())) {
          tempList.add(category);
          }
          }
          filterResults.count = tempList.size();
          filterResults.values = tempList;
          } else {

          filterResults.count = categoriesMain.size();
          filterResults.values = categoriesMain.clone();
          }
          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) {

          categoriesTemp = (ArrayList<Category>) results.values;
          notifyDataSetChanged();
          }
          }





          share|improve this answer























          • Thank you very much for your help. Your solution works for me if I replace filterResults.values = categoriesMain.clone(); with filterResults.values = categoriesMain.
            – sininen
            Jul 8 '17 at 13:07















          up vote
          1
          down vote



          accepted










          I think your implementation is not correct. You don't need to press the enter for search result. For implementation you can keep a intact copy of your array list.Then make another temporary list form that list when query text is changed. So when you are filtering, you are searching the actual list not the filtered list.



          1.pass search keyword to the list adapter



          public boolean onQueryTextChange(String newText) {

          adapter.getFilter().filter(newText);
          return true;
          }


          2. In adapter implement Filterable and override method



          @Override
          public Filter getFilter() {
          if (frameFilter == null) {
          frameFilter = new FrameFilter();
          }

          return frameFilter;
          }


          3. Filtering class can be something like this: 'categoryMain' is my intact list and 'categoryTemp' is my temporary list



          private class FrameFilter extends Filter {

          @Override
          protected FilterResults performFiltering(CharSequence constraint) {

          FilterResults filterResults = new FilterResults();
          if (constraint != null && constraint.length() > 0) {
          ArrayList<Category> tempList = new ArrayList<>();

          // search content in friend list
          Log.i("key",constraint.toString());
          for (Category category : categoriesMain) {
          if (category.getCategory_name().toLowerCase().contains(constraint.toString().toLowerCase())) {
          tempList.add(category);
          }
          }
          filterResults.count = tempList.size();
          filterResults.values = tempList;
          } else {

          filterResults.count = categoriesMain.size();
          filterResults.values = categoriesMain.clone();
          }
          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) {

          categoriesTemp = (ArrayList<Category>) results.values;
          notifyDataSetChanged();
          }
          }





          share|improve this answer























          • Thank you very much for your help. Your solution works for me if I replace filterResults.values = categoriesMain.clone(); with filterResults.values = categoriesMain.
            – sininen
            Jul 8 '17 at 13:07













          up vote
          1
          down vote



          accepted







          up vote
          1
          down vote



          accepted






          I think your implementation is not correct. You don't need to press the enter for search result. For implementation you can keep a intact copy of your array list.Then make another temporary list form that list when query text is changed. So when you are filtering, you are searching the actual list not the filtered list.



          1.pass search keyword to the list adapter



          public boolean onQueryTextChange(String newText) {

          adapter.getFilter().filter(newText);
          return true;
          }


          2. In adapter implement Filterable and override method



          @Override
          public Filter getFilter() {
          if (frameFilter == null) {
          frameFilter = new FrameFilter();
          }

          return frameFilter;
          }


          3. Filtering class can be something like this: 'categoryMain' is my intact list and 'categoryTemp' is my temporary list



          private class FrameFilter extends Filter {

          @Override
          protected FilterResults performFiltering(CharSequence constraint) {

          FilterResults filterResults = new FilterResults();
          if (constraint != null && constraint.length() > 0) {
          ArrayList<Category> tempList = new ArrayList<>();

          // search content in friend list
          Log.i("key",constraint.toString());
          for (Category category : categoriesMain) {
          if (category.getCategory_name().toLowerCase().contains(constraint.toString().toLowerCase())) {
          tempList.add(category);
          }
          }
          filterResults.count = tempList.size();
          filterResults.values = tempList;
          } else {

          filterResults.count = categoriesMain.size();
          filterResults.values = categoriesMain.clone();
          }
          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) {

          categoriesTemp = (ArrayList<Category>) results.values;
          notifyDataSetChanged();
          }
          }





          share|improve this answer














          I think your implementation is not correct. You don't need to press the enter for search result. For implementation you can keep a intact copy of your array list.Then make another temporary list form that list when query text is changed. So when you are filtering, you are searching the actual list not the filtered list.



          1.pass search keyword to the list adapter



          public boolean onQueryTextChange(String newText) {

          adapter.getFilter().filter(newText);
          return true;
          }


          2. In adapter implement Filterable and override method



          @Override
          public Filter getFilter() {
          if (frameFilter == null) {
          frameFilter = new FrameFilter();
          }

          return frameFilter;
          }


          3. Filtering class can be something like this: 'categoryMain' is my intact list and 'categoryTemp' is my temporary list



          private class FrameFilter extends Filter {

          @Override
          protected FilterResults performFiltering(CharSequence constraint) {

          FilterResults filterResults = new FilterResults();
          if (constraint != null && constraint.length() > 0) {
          ArrayList<Category> tempList = new ArrayList<>();

          // search content in friend list
          Log.i("key",constraint.toString());
          for (Category category : categoriesMain) {
          if (category.getCategory_name().toLowerCase().contains(constraint.toString().toLowerCase())) {
          tempList.add(category);
          }
          }
          filterResults.count = tempList.size();
          filterResults.values = tempList;
          } else {

          filterResults.count = categoriesMain.size();
          filterResults.values = categoriesMain.clone();
          }
          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) {

          categoriesTemp = (ArrayList<Category>) results.values;
          notifyDataSetChanged();
          }
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 10 at 17:49

























          answered Jul 7 '17 at 18:10









          Moshiur Rahman

          15117




          15117












          • Thank you very much for your help. Your solution works for me if I replace filterResults.values = categoriesMain.clone(); with filterResults.values = categoriesMain.
            – sininen
            Jul 8 '17 at 13:07


















          • Thank you very much for your help. Your solution works for me if I replace filterResults.values = categoriesMain.clone(); with filterResults.values = categoriesMain.
            – sininen
            Jul 8 '17 at 13:07
















          Thank you very much for your help. Your solution works for me if I replace filterResults.values = categoriesMain.clone(); with filterResults.values = categoriesMain.
          – sininen
          Jul 8 '17 at 13:07




          Thank you very much for your help. Your solution works for me if I replace filterResults.values = categoriesMain.clone(); with filterResults.values = categoriesMain.
          – sininen
          Jul 8 '17 at 13:07


















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f44977042%2fhow-to-search-a-list-of-objects-that-are-displayed-in-a-recyclerview%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Florida Star v. B. J. F.

          Error while running script in elastic search , gateway timeout

          Adding quotations to stringified JSON object values