Android: Autocomplete Textview Similar to the Facebook App

Android: Autocomplete TextView Similar To The Facebook App

First make your EditText into a MultiAutoCompleteTextView. A MultiAutoCompleteTextView allows you to replace certain parts of the text, for example text after '@'.

The you can do something like this:

final MultiAutoCompleteTextView inputEditText = (MultiAutoCompleteTextView) dialog.findViewById(R.id.MyEditText);

String[] COUNTRIES = new String[] { "Belgium", "France", "Italy", "Germany", "Spain" };
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, COUNTRIES);
inputEditText.setAdapter(adapter);
inputEditText.setThreshold(1); //Set number of characters before the dropdown should be shown

//Create a new Tokenizer which will get text after '@' and terminate on ' '
inputEditText.setTokenizer(new 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;
}
});

One "problem" with this is that the popup will appear under the EditText view. To move it up and place it under the text that is currently written you can do something like this:

inputEditText.addTextChangedListener(new TextWatcher() {

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Layout layout = inputEditText.getLayout();
int pos = inputEditText.getSelectionStart();
int line = layout.getLineForOffset(pos);
int baseline = layout.getLineBaseline(line);

int bottom = inputEditText.getHeight();

inputEditText.setDropDownVerticalOffset(baseline - bottom);

}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}

@Override
public void afterTextChanged(Editable s) {
}
});

Note: This does not currently take care of the dropdown position in the case that there are more lines in the edittext than the edittext can show.

Android AutoCompleteTextView with '@' mentions filtering like twitter and facebook

I ended up using the spyglass library from linkedin which does exactly what I was looking for. It provides a MentionsEditText (that can be customised). I also used a ListPopupWindow to show the suggestions in a list (like an AutoCompleteTextView).

Here is the link...

https://github.com/linkedin/Spyglass

Custom AutoCompletevView like facebook comments field in android

You have to make custom autocompleteview by extending class.. and code mentioned in your question to be changed.

public class CustomAutoComplete extends AutoCompleteTextView {
private String previous = "";
private String seperator = "@";
boolean isState = false;

public CustomAutoComplete(final Context context, final AttributeSet attrs,
final int defStyle) {
super(context, attrs, defStyle);
this.setThreshold(1);

}

public CustomAutoComplete(final Context context, final AttributeSet attrs) {
super(context, attrs);
this.setThreshold(1);
}

public CustomAutoComplete(final Context context) {
super(context);
this.setThreshold(1);
}

/**
* This method filters out the existing text till the separator and launched
* the filtering process again
*/
@Override
protected void performFiltering(final CharSequence text, final int keyCode) {
String filterText = text.toString().trim();
String lastchar = filterText.substring(filterText.length() - 1,
filterText.length());
if (filterText.length() == 1) {
if (lastchar.equals(seperator)) {
isState = true;
} else {
isState = false;
}
}
previous = filterText.substring(0,
filterText.lastIndexOf(getSeperator()) + 1);

filterText = filterText.substring(filterText
.lastIndexOf(getSeperator()) + 1);

if ((lastchar.equals(seperator)) || isState) {
super.performFiltering(filterText, keyCode);

isState = true;

}
}

/**
* After a selection, capture the new value and append to the existing text
*/
@Override
protected void replaceText(final CharSequence text) {
isState = false;
super.replaceText(previous + text);// + getSeperator());

}

public String getSeperator() {
return seperator;
}

public void setSeperator(final String seperator) {
this.seperator = seperator;
}

}

Hope this will help you...

How do I get MultiAutoCompleteTextView tokenizer similar to Facebook app?

Found the solution....

Add this textwatcher to the multiautocompletetextview

private TextWatcher textWather = new TextWatcher() {
int noOfCharAdded=0;int noOfCharDeleted=0;
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
startIdx=start;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
noOfCharAdded=after;
noOfCharDeleted=count;
}
@Override
public void afterTextChanged(Editable s) {
Editable buffer = s;
int start = multiContentText.getSelectionStart()<0?0:multiContentText.getSelectionStart();
int end = multiContentText.getSelectionEnd()<0?0:multiContentText.getSelectionEnd();
if(noOfCharAdded==0 && noOfCharDeleted==1){ //if space is deleted
if (start == end && delPrevText) {
ImageSpan link[] = buffer.getSpans(start, end,ImageSpan.class);
if (link.length > 0) {
buffer.replace(buffer.getSpanStart(link[0]),buffer.getSpanEnd(link[0]),"");
buffer.removeSpan(link[0]);
}
}
delPrevText=true;
multiContentText.setSelection(multiContentText.getText().length());
}
else if(noOfCharAdded==0 && noOfCharDeleted>1){//if the whole word is deleted
if(buffer.length()>0){
if(start<buffer.length()){
delPrevText=false;
if(buffer.charAt(start)==' '){
buffer.replace(start,start+1,"");
}
}
}
}

}
};

search friends like facebook

Try this Simple Code: (Without Using AutoCompleteTextView)

XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".SOF_AutoList" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<EditText
android:id="@+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Name" >

<requestFocus />
</EditText>
</LinearLayout>

<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>

</LinearLayout>

Java Activity Class:

public class SOF_AutoList extends Activity
{
private ListView listview;
private EditText edttxt;
private ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sof__auto_list);

ArrayList<String> data = new ArrayList<String>();
for(int i=0;i<10;i++)
{
if(i==0 || i==1 || i==3)
{
data.add("Apple "+(i+1));
}
else if(i==4 || i==5)
{
data.add("Banana "+(i+1));
}
else
{
data.add("CArrot "+(i+1));
}
}

listview = (ListView)findViewById(R.id.listView1);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1,data);
listview.setAdapter(adapter);

edttxt = (EditText)findViewById(R.id.editText1);
edttxt.addTextChangedListener(new TextWatcher()
{

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
adapter.getFilter().filter(s);
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub

}

@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub

}
});
}

}

Android AutoCompleteTextView with Style ExposedDropDownMenu

You can use the color state list resource to change the border color for focused, hovered, or unfocused mode.

Create a color resource directory under res, and add an XML file, named border_stroke.xml. The path of this XML would be res/color/border_stroke.xml

Now, place a selector in border_stroke.xml with color values of all modes

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/black" android:state_focused="true" />
<item android:color="@color/blue" android:state_hovered="true" />
<item android:color="@color/green" android:state_enabled="false" />
<item android:color="@color/pink" /> <!--unfocused-->
</selector>

Set this border_stroke as color value of boxStrokeColor attribute

<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:boxStrokeColor="@color/border_stroke"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
...
>

Android - Using AutoCompleteTextView to detect a word next to `@`

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


Related Topics



Leave a reply



Submit