Android - 使用AutoCompleteTextView检测`@`旁边的单词

时间:2016-05-04 06:42:57

标签: android autocompletetextview

首先,我在AutoCompleteTextView中真的很新,并且从标题中可以推断,我想将它用于我目前正在开发的社交媒体应用中的Tag人。

首先,我创建了一个名为TagList的类,其中包含一个名为TagModel的模型类列表:

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

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

这是整个适配器类:

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;

    }
}

我添加了单个虚拟数据来测试AutoComplete是否有效,好吧,它可以工作但是现在我在过滤@(someone's name)时失去了因为无论我输入什么,它都会显示我的假人列表中的数据。

我实际上需要完成两件事,

  1. 让过滤器仅过滤@(某人的名字)并将查询放入API。

  2. 当用户按空格时停止自动填充。

  3. 有人能指出我正确的方向吗?我很乐意提出解释我的问题所需的任何代码..

    更新:AutoCompleteTextView上的错误TextWatcher,尝试在@之后和" "之前获取任何文字。

    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) {
    
            }
        });
    

2 个答案:

答案 0 :(得分:0)

您有两件事要做:

  1. 检测包含@ 某人的字符串。
  2. 使用不带字符的字符串&#39; @&#39;作为某人进行查询。
  3. 现在,你可以点击链接Multiautocompletetextview, Show autocomplete drop down only when user presses a key after '@' key (like mention in FB app)

    请向下滚动查找@Phuong Sala的答案。如果您想与很多人进行多重标记,请使用MultiAutoCompleteTextView。

    如果有帮助请告诉我

答案 1 :(得分:0)

最后,我在SO中找到了Tokenizer,但我忘了找到它的地方,抱歉!

以下是代码:

    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;
        }
    });