【问题标题】:Android - Using AutoCompleteTextView to detect a word next to `@`Android - 使用 AutoCompleteTextView 检测“@”旁边的单词
【发布时间】:2016-08-29 10:54:20
【问题描述】:

首先,我是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. 当用户按下空格键时停止自动完成。

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

更新: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) {

        }
    });

【问题讨论】:

  • 您可以使用带有自动完成文本视图的 textwatcher 来检查 @ 之后的字符
  • 在问这个问题之前我做了一些研究,一开始我也是这么想的..但是..他们说AutoCompleteTextView不需要TextWatcher,只是过滤就够了,但我不知道目前如何
  • 据我所知,文本视图的过滤器用于在输入时阻止/允许某些字符,所以我认为你必须使用文本观察器
  • 哦,这就是为什么....该死,所以我读错了..以及如何获得价值? TextWatcher 获取 TextView 中的整个字符串,对吗?对onTextChanged 中的计数进行for 迭代??我知道有很多方法,但我想知道您对此有何看法,因为我可能效率低下..
  • no 不要使用 for 循环,只检查用户在 onTextChanged() 方法中输入的字符

标签: android autocompletetextview


【解决方案1】:

你有两件事要做:

  1. 检测包含@someone的字符串。
  2. 使用不带“@”字符的字符串作为某人进行查询。

所以现在,你可以做链接Multiautocompletetextview, Show autocomplete drop down only when user presses a key after '@' key (like mention in FB app)

请向下滚动以找到@Phuong Sala 的答案。如果你想和多人一起多标签,让我们使用 MultiAutoCompleteTextView。

如果有帮助请告诉我

【讨论】:

  • 哦兄弟,谢谢,但我忘了在这里回答我自己的问题,我已经解决了
【解决方案2】:

最后,我使用了在 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;
        }
    });

【讨论】:

  • 它究竟是如何工作的..?就像我在我朋友的名字之前写一些东西然后输入@那样它会检测到吗?例如:嘿@kriti
猜你喜欢
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
  • 1970-01-01
  • 2015-09-18
  • 2020-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多