Android - 使用 AutoCompleteTextView 检测“@”旁边的单词
Android - Using AutoCompleteTextView to detect a word next to `@`
首先,我真的是 AutoCompleteTextView
的新手,从标题可以推断,我想将它用于我目前正在开发的社交媒体应用程序中的 Tag
人。
首先,我创建了一个名为 TagList
的 class 来包含名为 TagModel
的模型 class 列表:
public class TagModel {
public String user_avatar;
public String user_name;
@Override
public String toString() {
return user_name;
}
}
这是整个适配器 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;
}
}
我添加了单个虚拟数据来测试 AutoComplete
是否有效,嗯,它有效,但现在我在过滤方面不知所措 @(someone's name)
因为无论我输入什么,它都会显示我在列表中的虚拟数据。
我实际上需要在这里完成两件事,
获取过滤器以仅过滤@(某人的姓名)并将查询放入API.
当用户按下 space 时停止自动完成。
任何人都可以指出我正确的方向吗?我很乐意提供解释我的问题所需的任何代码..
更新: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) {
}
});
你有两件事要做:
- 检测包含@someone.
的字符串
- 使用不带'@'字符的字符串作为某人进行查询
现在,您可以像 link Multiautocompletetextview, Show autocomplete drop down only when user presses a key after '@' key (like mention in FB app)
请向下滚动找到@Phuong Sala 的答案。如果你想多人联机,那就用MultiAutoCompleteTextView吧。
如果有帮助请告诉我
最后,我用了一个SO里找到的Tokenizer
,但是忘了是从哪里找到的,sorry!
代码如下:
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;
}
});
首先,我真的是 AutoCompleteTextView
的新手,从标题可以推断,我想将它用于我目前正在开发的社交媒体应用程序中的 Tag
人。
首先,我创建了一个名为 TagList
的 class 来包含名为 TagModel
的模型 class 列表:
public class TagModel {
public String user_avatar;
public String user_name;
@Override
public String toString() {
return user_name;
}
}
这是整个适配器 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;
}
}
我添加了单个虚拟数据来测试 AutoComplete
是否有效,嗯,它有效,但现在我在过滤方面不知所措 @(someone's name)
因为无论我输入什么,它都会显示我在列表中的虚拟数据。
我实际上需要在这里完成两件事,
获取过滤器以仅过滤@(某人的姓名)并将查询放入API.
当用户按下 space 时停止自动完成。
任何人都可以指出我正确的方向吗?我很乐意提供解释我的问题所需的任何代码..
更新: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) {
}
});
你有两件事要做:
- 检测包含@someone. 的字符串
- 使用不带'@'字符的字符串作为某人进行查询
现在,您可以像 link Multiautocompletetextview, Show autocomplete drop down only when user presses a key after '@' key (like mention in FB app)
请向下滚动找到@Phuong Sala 的答案。如果你想多人联机,那就用MultiAutoCompleteTextView吧。
如果有帮助请告诉我
最后,我用了一个SO里找到的Tokenizer
,但是忘了是从哪里找到的,sorry!
代码如下:
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;
}
});