0

Firstly, I am really new in AutoCompleteTextView, and as can be inferred from the title, I want to use it to Tag people in the social media app I am currently developing.

First I've created a class named TagList to contain a list of model class named TagModel :

public class TagModel {
    public String user_avatar;
    public String user_name;

    @Override
    public String toString() {
        return user_name;
    }
}

And here's the whole adapter class :

public class TagAdapter extends ArrayAdapter<TagModel> implements Filterable {

    private Context context;
    private int resource;
    private TagList mDataset;

    public TagAdapter(Context context, int resource) {
        super(context, resource);
        this.context = context;
        this.resource = resource;
        this.mDataset = new TagList();
    }

    public void changeItem(TagList tagList){
        this.mDataset.tagModelList.clear();
        notifyDataSetChanged();
        this.mDataset.tagModelList.addAll(tagList.tagModelList);
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mDataset.tagModelList.size();
    }

    @Override
    public TagModel getItem(int position) {
        return this.mDataset.tagModelList.get(position);
    }

    @Override
    public Filter getFilter() {
        Filter myFilter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults filterResults = new FilterResults();
                ArrayList<TagModel> tempTagModel = new ArrayList<TagModel>();
                if(constraint != null) {
                    int length = mDataset.tagModelList.size();
                    int i = 0;
                    while(i<length){
                        TagModel item = mDataset.tagModelList.get(i);
                        //do whatever you wanna do here
                        //adding result set output array

                        tempTagModel.add(item);

                        i++;
                    }
                    //following two lines is very important
                    //as publish result can only take FilterResults objects
                    filterResults.values = tempTagModel;
                    filterResults.count = tempTagModel.size();
                }
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence contraint, Filter.FilterResults results) {
                if(results != null && results.count > 0) {
                    notifyDataSetChanged();
                }
                else {
                    notifyDataSetInvalidated();
                }
            }
        };
        return myFilter;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        try{
            if(convertView==null){
                // inflate the layout
                LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(resource, parent, false);
            }

            TagModel objectItem = mDataset.tagModelList.get(position);

            ImageView userAvatar = (ImageView) convertView.findViewById(R.id.popup_tag_avatar);

            OpenSansFont userName = (OpenSansFont) convertView.findViewById(R.id.popup_tag_name);
            userName.setText(objectItem.user_name);

        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return convertView;

    }
}

I've added single dummy data to test whether the AutoComplete works, well, it works but now I'm at loss on filtering @(someone's name) because whatever I type, it'll display my dummy data in the list.

I actually need 2 things done here,

  1. Getting filter to filter only @(someone's name) and put the query into API.

  2. Stop autocomplete when user presses space.

Can anyone point me to the right direction on this? I'll gladly put up any code needed to explain my question..

Update : A buggy TextWatcher on an AutoCompleteTextView, trying to get whatever text after @ and before " ".

tagAutoComplete.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

            if (count > 0) {
                if (before == 0) {
                    flag = false;
                    stringBuilder.replace(0, stringBuilder.length() - 1, "");
                }

                if (flag) {
                    stringBuilder.append(s.toString().charAt(count - 1));
                    FriendTagListShowAPI friendTagListShowAPI = new FriendTagListShowAPI();
                    friendTagListShowAPI.query.tag = stringBuilder.toString();
                    friendTagListShowAPI.query.user_id = userId;

                    FriendTagListShowAPIFunc friendTagListShowAPIFunc = new FriendTagListShowAPIFunc();
                    friendTagListShowAPIFunc.delegate = TestAutoComplete.this;
                    friendTagListShowAPIFunc.execute(friendTagListShowAPI);
                }

                if (before < s.length() && String.valueOf(s.charAt(before)).equals("@")) {
                    flag = true;
                }
            }
        }

        @Override
        public void afterTextChanged(Editable s) {

        }
    });
Kevin Murvie
  • 2,592
  • 1
  • 25
  • 43
  • you can use textwatcher with autocomplete textview to check the character after `@` – Vivek Mishra May 04 '16 at 06:52
  • I've done a bit of researching before asking this question, at first I thought of the same.. But.. They said `AutoCompleteTextView` doesn't need to have any `TextWatcher`, just filtering is enough, but I don't know how currently – Kevin Murvie May 04 '16 at 07:23
  • as far as I know filters for textviews are used to block/allow certain characters while typing, so I think you have to use text watcher – Vivek Mishra May 04 '16 at 07:25
  • Ohhhh so that's why.... Damn so I read it wrongly.. And how to get the value? TextWatcher get the whole string inside the TextView right?? Do a `for` iteration for count in the `onTextChanged`?? I know there is a lot of way, but I wish to know what's your take on it, because I might be inefficient.. – Kevin Murvie May 04 '16 at 07:38
  • no don't use for loop just check the character that is inputted by user in onTextChanged() method – Vivek Mishra May 04 '16 at 07:40
  • Oh yes, it has .charAt(), should've seen that! Now I am able to get whatever user input after @ and before " ", thanks! – Kevin Murvie May 04 '16 at 08:01
  • I am having trouble with getting it.. If I space, type something, then backspace to that empty space, I'll get `java.lang.IndexOutOfBoundsException: charAt: -1 < 0`.. Need some logic help over here :( – Kevin Murvie May 04 '16 at 09:41
  • can you show how you have implemented – Vivek Mishra May 04 '16 at 09:42
  • I've added it.. Full of flaws D: – Kevin Murvie May 04 '16 at 09:50
  • your code will fail when `count=0`;. So put that code in `if(count>0)` block – Vivek Mishra May 04 '16 at 09:53
  • I'm quite confused with the difference of count, before, start.. Does count stands for total count of characters, or characters in a word? Before is the amount of characters in the word before, or total amount of characters before I type in something? – Kevin Murvie May 04 '16 at 09:59
  • you have to use only onTextChanged() method . and count stands for what I think is total no of characters – Vivek Mishra May 04 '16 at 10:01
  • Edited the onTextChanged() method in my code.. It only get the string after I input 2 characters after "@", why is that so? – Kevin Murvie May 09 '16 at 03:21
  • In the end I referred to this http://stackoverflow.com/questions/24769257/custom-listview-adapter-with-filter-android, we don't need to use `TextWatcher`, but we do need to have 2 dataset, 1 for the actual dataset, and 1 is for the filtered dataset.. – Kevin Murvie May 09 '16 at 07:08

2 Answers2

0

You have 2 things to do:

  1. Detect the string that contains @someone.
  2. Use the string without the character '@' as someone to do query.

So now, you can do as the link Multiautocompletetextview, Show autocomplete drop down only when user presses a key after '@' key (like mention in FB app)

Please scroll down to find @Phuong Sala answer. If you want to multi-tag with many people, let's use MultiAutoCompleteTextView.

Let me know if it helps

Community
  • 1
  • 1
0

In the end, I used a Tokenizer as found in SO, but I forgot where I found it, sorry!

Here's the code :

    multiAutoCompleteTextView.setTokenizer(new MultiAutoCompleteTextView.Tokenizer() {

        @Override
        public CharSequence terminateToken(CharSequence text) {
            int i = text.length();

            while (i > 0 && text.charAt(i - 1) == ' ') {
                i--;
            }

            if (i > 0 && text.charAt(i - 1) == ' ') {
                return text;
            } else {
                if (text instanceof Spanned) {
                    SpannableString sp = new SpannableString(text + " ");
                    TextUtils.copySpansFrom((Spanned) text, 0, text.length(), Object.class, sp, 0);
                    return sp;
                } else {
                    return text + " ";
                }
            }
        }

        @Override
        public int findTokenStart(CharSequence text, int cursor) {
            int i = cursor;

            while (i > 0 && text.charAt(i - 1) != '@') {
                i--;
            }

            //Check if token really started with @, else we don't have a valid token
            if (i < 1 || text.charAt(i - 1) != '@') {
                return cursor;
            }

            return i;
        }

        @Override
        public int findTokenEnd(CharSequence text, int cursor) {
            int i = cursor;
            int len = text.length();

            while (i < len) {
                if (text.charAt(i) == ' ') {
                    return i;
                } else {
                    i++;
                }
            }

            return len;
        }
    });
Kevin Murvie
  • 2,592
  • 1
  • 25
  • 43
  • how exactly does it works.. ? like if i write something before my friends name and then type @ will it detect even then? for example: hey @kriti – Kriti Sep 19 '17 at 10:16