I have a MultiAutoCompleteTextView. It works fine. But I want to show suggestion dropdown only when user type # on it (like tagging user in facebook app). I have no idea how to do it. Here is my code :
mChatbox = (MultiAutoCompleteTextView) findViewById(R.id.chatbox);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line, userList);
mChatBox.setAdapter(adapter);
mChatBox.setTokenizer(new SpaceTokenizer());
public class SpaceTokenizer implements MultiAutoCompleteTextView.Tokenizer {
public int findTokenStart(CharSequence text, int cursor) {
int i = cursor;
while (i > 0 && text.charAt(i - 1) != ' ') {
i--;
}
while (i < cursor && text.charAt(i) == ' ') {
i++;
}
return i;
}
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;
}
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 + " ";
}
}
}
Create a custom Text view extending MultiAutoCompleteTextView -> override enoughToFilter() -> set the threshold to 0 (the bold variable in the below given code) :
public boolean enoughToFilter() {
Editable text = getText();
int end = getSelectionEnd();
if (end < 0 || mTokenizer == null) {
return false;
}
int start = mTokenizer.findTokenStart(text, end);
if (end - start >= mThreshold && start != -1) {
return true;
} else {
return false;
}
}
Using this code you'll see the auto suggested list on press of #
If you want to detect your string starts with '#' for mention (tag) someone or '#' for hashTag, then do query or filter with it, you could follow this code belows:
#Override
public void onTextChanged(CharSequence s, int start, int before, final int count) {
if (s.length() > 0) {
// Todo: query mentions
Matcher mentionMatcher = Pattern.compile("#([A-Za-z0-9_-]+)").matcher(s.toString());
// while matching
while (mentionMatcher.find()) {
yourSearchText = s.toString().substring(mentionMatcher.start() + 1, mentionMatcher.end());
// do query with yourSearchText below
}
}
}
It references from 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.
I got a solution by myself. I create custom view which extends MultiAutoCompleteTextView and override performFiltering in it. Check if first char is "#", then filter the next chars after it. Otherwise, replace chars with "*" to avoid filtering. Here is my code.
#Override
protected void performFiltering(CharSequence text, int start, int end, int keyCode) {
if (text.charAt(start) == '#') {
start = start + 1;
} else {
text = text.subSequence(0, start);
for (int i = start; i < end; i++) {
text = text + "*";
}
}
super.performFiltering(text, start, end, keyCode);
}
Related
My problem is that when I suggest sentences in MultiAutoCompleteTextView, when I press spacebar, the suggestions disappear.
Example:
Suggested words:
THE ROCK THE BALL THERMAL
If I write "THE", all sentences are displayed, but if I write "THE " (with blank space) the suggestions are dismissed.
I want that if you write "THE ", the elements "THE ROCK" and "THE BALL" are displayed in suggested words.
Thanks.
You should implement MultiAutoCompleteTextView.Tokenizer and create a spaceTokenizer as below. Then set multiAutoCompleteTextView.setTokenizer(new SpaceTokenizer());
public class SpaceTokenizer implements MultiAutoCompleteTextView.Tokenizer {
public int findTokenStart(CharSequence text, int cursor) {
int i = cursor;
while (i > 0 && text.charAt(i - 1) != ' ') {
i--;
}
while (i < cursor && text.charAt(i) == ' ') {
i++;
}
return i;
}
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;
}
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 + " ";
}
}
}
}
Have a look at this post:
https://groups.google.com/forum/#!topic/android-developers/OrsN2xRpDmA
I just ran into a similar problem and wrote a simple multi word derivation. It defaults to a "," separator but you can set it whatever you like using the "setSeparator" method.
or
this stack-overflow answer might be helpful cause it experiences the same problem:
AutoCompleteTextView backed by CursorLoader
I know how to use EditText in android and how to use AutoComplete EditText in android. But AutoComplete EditText is used like dropdown list where user type a character and suggestions will be displayed and user clicks on one of the suggestions. If there is no suggestion then it won't display any text.
My requirement is like, Consider there is an EditText. User can type anything they want, but when the word starts from special character like for example "#" then the api will hit and display suggestions.
Complete Example:
"My Name is James Bond and I am #And"
In above example when user type this sentence at the end "#And" it will show the auto suggestion from hitting the API(should display Android) and user can select this suggested word from list.
Is there any way to achieve this??
Please Do help me.
Thank You.
Android provides MultiAutoCompleteTextView. Use this widget instead of EditText and override its tokenizer.
MultiAutoCompleteTextView myautocomplete = (MultiAutoCompleteTextView) findViewById(R.id.multy);
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, array_for_autocomplete);
myautocomplete.setAdapter(adapter);
myautocomplete.setTokenizer(new MultiAutoCompleteTextView.Tokenizer() {
#Override
public int findTokenStart(CharSequence text, int cursor) {
int i = cursor;
while (i > 0 && text.charAt(i - 1) != '#') {
i--;
}
while (i < cursor && text.charAt(i) == ' ') {
i++;
}
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;
}
#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 + ", ";
}
}
}
});
Documentation : http://developer.android.com/reference/android/widget/MultiAutoCompleteTextView.html
What i want to do
i want to mention both people and group in a chat activity.when the user types # i want populate the list which contains no of user and channels
so that he can mention both people and channels
What i have done
i took help from this question Android: Autocomplete TextView Similar To The Facebook App
here i have included my code
1.Arraylist which has users
ArrayList<People> users = new ArrayList<User>();
for (People user : SocketSingleton.userMap.values()) {
if (user.getId() != loggedUserId) {
users.add(user);
}
}
2.Arraylist which has groups list
ArrayList<Group> groups = new ArrayList<Group>();
for (Group channel : SocketSingleton.listgroups.values()) {
groups.add(channel);
}
3.Adapters for view
final UserAdapter Adapter = new UserAdapter(getActivity(), R.layout.all_user_list_item, users);
final GroupAdapter Adapter1 = new GroupAdapter(getActivity(), R.layout.all_groups_list_item, Groups);
4.MultiAutocompletetextview
textinput = (MultiAutoCompleteTextView) view.findViewById(R.id.message_input);
textinput.setAdapter(Adapter);
textinput.setThreshold(0);
textinput.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;
}
});
textinput.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Layout layout = textinput.getLayout();
int pos = textinput.getSelectionStart();
int line = layout.getLineForOffset(pos);
int baseline = layout.getLineBaseline(line);
int bottom = textinput.getHeight();
textinput.setDropDownVerticalOffset(baseline - bottom);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
textinput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int id, KeyEvent event) {
if (id == R.id.send || id == EditorInfo.IME_NULL) {
messageSend();
return true;
}
return false;
}
});
Problem i have
with this code i can able to mention only people. i can only set either adapter1 or adapter2 for Autocomplete tectview. So it is only displaying either users or groups.
i want to display all list in single adapter so that the user can mention peoples and groups
i am new to this please help me to find a way
There is no built in support for multiple data types with MultiAutoCompleteTextView. However there are several open source libraries that allow you to do just that.
I've had the same requirement in the project I'm working on and here is our open source solution, feel free to check it out:
https://github.com/Teamwork/android-multiautocomplete
You can achieve that by doing this:
MultiAutoComplete autoComplete = new MultiAutoComplete.Builder()
...
.addTypeAdapter(typeAdapter1)
.addTypeAdapter(typeAdapter2)
.build();
You can also specify the type of filter and handle ('#' or '#' or any other) you want to use for each type adapter.
i integrated MultiAutoCompleteTextView in to my dictionary app so now after integrating it.
i got a problem like this as show in second screen shot...
so now i don't want that ","
as show in second screen shots after !
i am getting "," like this
!,
plz help me
thank q
String[] str={"!","\"","#","$","$1","%","'","+",",","/"};
MultiAutoCompleteTextView mt=(MultiAutoCompleteTextView)findViewById(R.id.searchEditText);
mt.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
ArrayAdapter<String> adp=new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,str);
mt.setThreshold(1);
mt.setAdapter(adp);
The comma is coming from CommaTokenizer() called in this line mt.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
To remove the comma you need to implement your own Tokenizer. This is an example:
public class SpaceTokenizer implements Tokenizer {
public int findTokenStart(CharSequence text, int cursor) {
int i = cursor;
while (i > 0 && text.charAt(i - 1) != ' ') {
i--;
}
while (i < cursor && text.charAt(i) == ' ') {
i++;
}
return i;
}
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;
}
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 + " ";
}
}
}
}
PS: I copied the code from this answer
I am using a MultiAutoCompleteTextView which shows suggestions for user input. It only works when the items are separated by one or more spaces, but doesn't when a new line (i.e. button "enter" is pressed) is the delimiter.
The code so far (I think I got it from stackoverflow some time ago):
public class SpaceTokenizer implements Tokenizer {
#Override
public int findTokenStart(CharSequence text, int cursor) {
int i = cursor;
while (i > 0 && text.charAt(i - 1) != ' ') {
i--;
}
while (i < cursor && text.charAt(i) == ' ') {
i++;
}
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;
}
#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 + " ";
}
}
}
}
I tried to implement something like "... || text.charAt(i) == '\n' ..." where I thought appropriate, but that didn't work.
So I would be very thankful for suggestions!
The answer to my question can be found here:
Android and the CommaTokenizer