Android: Autocomplete TextView Similar To The Facebook App
Asked Answered
S

2

31

I have an AutoCompleteTextView in my app. The app makes use of the Facebook SDK. I followed the code from this question on SO: https://mcmap.net/q/471584/-search-functionality-for-listview to the dot and have a functioning search (filtering) activity.

Now, how do I get an inline Autocomplete like the Facebook App after the @ symbol is typed and still hold the other text typed by the user? The activity in question is for a Status Update and can contain the user's Friends along with other text. The AutoCompleteTextView or the EditText will naturally be a multi-line one. For a status update you see.

I know for the lack of any code in this post, I risk getting downvoted or perhaps even having the question closed. But it's really a standard boiler plate list filtering code.

EDIT: The FriendCaster app for Android also does the same.

Sheritasherj answered 2/10, 2012 at 13:56 Comment(4)
techdroid.kbeanie.com/2010/04/… Something like this maybe help you to get the idea ???Diehl
There is not out of the box solution for this, one way is you can decompile the Facebook app and the see the code. There are a lot of decompilers available. But what they are basically doing is extending the EditText View and customizing it according to their needs. I think twitter does the same.Romito
@Nitin: I am not entirely sure I would like to de-compile someone else's work. Besides, even if I was to do it, at best, I would get their XML's only. Not their JAVA which I believe is what is necessary.Sheritasherj
@SkiddharD For what its worth, you will get JAVA in clear text, I know because I did it.Romito
C
35

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.

Conversazione answered 9/10, 2012 at 8:27 Comment(10)
Exactly what I needed! Worked like a charm. :-)Sheritasherj
Might I ask one more question? Regardless of whether you do answer it or don't, the bounty is yours.Sheritasherj
Ask away, can't promise I can answer though :)Conversazione
Lol... No problem. In my current scheme of things, I am pulling in data from the Facebook API. What kind of changes would I have to make to accommodate my adapter that implements a BaseAdapter?Sheritasherj
You need to make it implement Filterable. Then override getFilter(), you can look at android.googlesource.com/platform/frameworks/base/+/refs/heads/… for an example. Then in the ArrayFilter you might also want to override convertResultToString(Object resultValue).Conversazione
Oh. Just that eh? I already have that functioning. So I suppose I must connect the dots then. :-)Sheritasherj
Could you possibly take a look at this question https://mcmap.net/q/471585/-multiautocompletetextview-with-custom-adapter-displays-garbled-string/1350013? It is a follow up to this one. Thank you.Sheritasherj
MultiAutoCompleteTextView is not working with custom adapter.Can you help meUnfeigned
How can use this to show the result from the web instead of static Array?Bobstay
How could I make this work if I receive the list of countries with a prefixed #? e.g String[] COUNTRIES = new String[] { "#Belgium", "#France", "#Italy", "#Germany", "#Spain" };Hasson
K
0

https://github.com/dhaval001/linkable_text_view.git

Simple way to create link text, such as @username or #hashtag, in Android TextView and EditText with multiautocomplete textview. link facebook and instagram

Features

Match single strings or regex pattern to set links Change the color of the linked text Set the style of the linked text: BOLD, ITALIC, or BOLD_ITALIC Set the underlined of the linked text Specify click actions of a specific word OnTextChangedListener listener for LinkableEditText

Killifish answered 1/3, 2016 at 12:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.