Search code examples
androidandroid-arrayadapterlistadaptertextwatcher

Single EditText that updates few ListViews via Adapter/TextWatcher


I have a view where I have single EditText and screen separated on two parts (2 ListViews). I want to input data to EditText and update both ListViews in different way, using this data. For example to 1st ListView go the words that start with my input. To 2nd ListView go the words that contains my input.

I made two different custom ListAdapters that implement needed functionality. Then I add them to my EditText object and bugs begin. If I use only one of adapters everything's ok.

SO how can I use both adapters for single EditText to make this update 2 ListViews in different way.

Here is my code.

ListView lv;
ListView lv2;
ArrayAdapter<String> adapterForSearch;
ArrayAdapter<String> adapterForTurkishSearch;


@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.dictionary_screen);
    mContext = this;

    List<Map<String,?>> dictionaryTopics = new LinkedList<>();


    dictionaryTopics.add(createItem("Я ТЫ МЫ ВЫ", formWordCouplesSet(words.getMeU())));
    dictionaryTopics.add(createItem("Animals", formWordCouplesSet(words.getAnimals())));


    // create our list and custom adapter
    SeparatedListAdapter adapter = new SeparatedListAdapter(this);

    adapter.addSection("Turkish Dictionary", new SimpleAdapter(this, dictionaryTopics, R.layout.list_complex,
            new String[]{ITEM_TITLE, ITEM_CAPTION}, new int[]{R.id.list_complex_title, R.id.list_complex_caption}));

    list = (ListView) findViewById(R.id.dictionary_topics);
    list.setAdapter(adapter);
    list.setClickable(true);

    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {


            for(int index=0; index<((ViewGroup)view).getChildCount(); ++index) {
                View nextChild = ((ViewGroup)view).getChildAt(index);
                if (index >0) {
                    if (checkVisibility(nextChild))
                    {
                        nextChild.setVisibility(View.GONE); dimCounter--; checkDimCounter();
                    }
                    else {
                        nextChild.setVisibility(View.VISIBLE); dimCounter++; checkDimCounter();
                    }
                }
            }
        }
    });

    //Search Implementation

    inputSearch = (EditText) findViewById(R.id.inputSearch);

    lv = (ListView) findViewById(R.id.list_view);
    lv2 = (ListView) findViewById(R.id.list_view2);

    adapterForSearch = new MyAdapter<>(this, R.layout.list_item2, R.id.product_name, wordCombos);
    adapterForTurkishSearch = new MyTurkishAdapter<>(this, R.layout.list_item2, R.id.product_name, wordCombos);



    TextWatcher watcher1;

    watcher1 = new TextWatcher() {


        @Override
        public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
            // When user changed the Text

            if (cs.length() == 0)
            {
                    lv.setAdapter(null);
            }
            else {

                    lv.setAdapter(adapterForSearch);
                    adapterForSearch.getFilter().filter(cs);
            }
        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                                      int arg3) {
        }
        @Override
        public void afterTextChanged(Editable arg0) {
        }
    };


    TextWatcher watcher2;

    watcher2 = new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
            // When user changed the Text

            if (cs.length() == 0)
            {

                    lv2.setAdapter(null);

            }
            else {

                    lv2.setAdapter(adapterForTurkishSearch);
                    adapterForTurkishSearch.getFilter().filter(cs);
            }
        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                                      int arg3) {
        }

        @Override
        public void afterTextChanged(Editable arg0) {
        }
    };

    inputSearch.addTextChangedListener(watcher1);
    inputSearch.addTextChangedListener(watcher2);

}

Solution

  • An EditText only allows for one registered TextChangedListener therefore the last one, "watcher2" will be the one that ends up being used since it was the last set. You should find a way to merge the code you have in both onTextChanged() blocks into one TextWatcher and only set that one. https://developer.android.com/reference/android/widget/TextView.html#addTextChangedListener(android.text.TextWatcher)

    You also may want to consider changing the way you are setting the adapters which could pontentially mean you will have to change some logic in your custom adapters but since you didnt post the code for them i cant tell you for sure. The adapters for the list views should ideally be set somewhere outside of the TextWatcher. Then in your onTextChanged() code you should do adpater.notifyDataSetChanged();to update the listview after you run the code to filter your list views which should be done inside onTextChanged() not in the adapter.