Search code examples
javaandroidlisteneractionlistenerautocompletetextview

How to listen if AutoCompleteTextView full suggestion word is typed


I want my fragment to listen if that full suggestion word of the AutoCompleteAdapter list is typed.

For example, my list contains these elements:

{"Alireza Noorali", "Armin Yaghini", "Hassan Mirfendereski"}

The user is typing Alireza Nooral in AutoCompleteTextView, I want to dismissDropDown() and do something else when user typed the last character of suggestion which is i to be Alireza Noorali.

I implemented a Custom Adapter and in its getFilter method put a listener:

@NonNull
@Override
public Filter getFilter() {
    return nameFilter;
}

/*
 * Custom Filter implementation for custom suggestions we provide.
 */
private Filter nameFilter = new Filter() {
    @Override
    protected FilterResults performFiltering(CharSequence inputChars) {

        if (inputChars != null) {

            try {
                suggestions.clear();
            } catch (Exception e) {
                e.printStackTrace();
            }

            for (String acTvItem : tempItems) {
                if (acTvItem.toLowerCase().contains(inputChars.toString().toLowerCase())) {
                    suggestions.add(acTvItem);
                }

                if (listener != null && acTvItem.equalsIgnoreCase(inputChars.toString()) && results.count == 1) {
                    listener.onCompleteInputListener(key);
                }
            }

            FilterResults filterResults = new FilterResults();
            filterResults.values = suggestions;
            filterResults.count = suggestions.size();
            return filterResults;
        } else {
            return new FilterResults();
        }
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        List<String> filterList = (ArrayList<String>) results.values;
        if (results.count > 0) {
            clear();
            if (filterList != null && !filterList.isEmpty()) {
                for (String acTvItem : filterList) {
                    add(acTvItem);
                    notifyDataSetChanged();
                }
            }
        }
    }
};


/*  ---------- Interface ----------  */

public interface CompleteInputListener {
    void onCompleteInputListener(String key);
}

In my fragment I implemented listener method:

private AcTvAdapter.CompleteInputListener completeInputListener() {
    return new AcTvAdapter.CompleteInputListener() {
        @Override
        public void onCompleteInputListener(String key) {

            // hideSoftKeyboard & dismissDropDown & something else
        }
    };
}

But when I do the initially said scenario, I get this warning:

W/Filter: An exception occured during performFiltering()!
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7809)
    at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1338)
    at android.view.ViewGroup.invalidateChild(ViewGroup.java:5446)
    at android.view.View.invalidateInternal(View.java:14749)
    at android.view.View.invalidate(View.java:14713)
    at android.view.View.setFlags(View.java:12542)
    at android.view.View.setVisibility(View.java:8611)
    at ir.noorali.myapp.MyFrag.getCountry(MyFrag.java:662)
    at ir.noorali.myapp.MyFrag$12.onCompleteInputListener(MyFrag.java:995)
    at ir.noorali.myapp.adapters.AcTvAdapter$1.performFiltering(AcTvAdapter.java:120)
    at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.os.HandlerThread.run(HandlerThread.java:61)

I Know the reason is the declaration of ActionListener:

Java ActionListener is an invisible GUI object that gets its method called when the user performs a certain action. Common actions include pressing the push button, toggling the toggle button, checking the checkbox, selecting an item in combo box and the like.

but I have no idea about how to achieve my purpose. Is there any alternative solution?


Solution

  • As @pskink said in comments, I called onCompleteInputListener on publishResults and the problem solved. This is my new code:

    @NonNull
    @Override
    public Filter getFilter() {
        return nameFilter;
    }
    
    /*
     * Custom Filter implementation for custom suggestions we provide.
     */
    private Filter nameFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence inputChars) {
    
            if (inputChars != null) {
    
                try {
                    suggestions.clear();
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                for (String acTvItem : tempItems) {
                    if (acTvItem.toLowerCase().contains(inputChars.toString().toLowerCase())) {
                        suggestions.add(acTvItem);
                    }
                }
    
                FilterResults filterResults = new FilterResults();
                filterResults.values = suggestions;
                filterResults.count = suggestions.size();
                return filterResults;
            } else {
                return new FilterResults();
            }
        }
    
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            List<String> filterList = (ArrayList<String>) results.values;
            if (results.count > 0) {
                clear();
                if (filterList != null && !filterList.isEmpty()) {
    
                    for (String acTvItem : filterList) {
    
                    if (listener != null && acTvItem.equalsIgnoreCase(inputChars.toString()) && results.count == 1) {
                        listener.onCompleteInputListener(key);
                    }
    
                        add(acTvItem);
                        notifyDataSetChanged();
                    }
                }
            }
        }
    };
    
    
    /*  ---------- Interface ----------  */
    
    public interface CompleteInputListener {
        void onCompleteInputListener(String key);
    }
    

    Now it works without any warning!