Android: Autocomplete TextView Similar To The Facebook App - android

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://stackoverflow.com/a/12363961/450534 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.

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.

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

Related

How to change text color while typing special word

on MultpuAutocompletTexView while Typing I want to make some special word that is start with # want to make that word alone with some colour, how can I do this any help.
so when ever I type with # that word should be in colour text.
like this image
Use TextWatcher with Spanable text, and every time you need to check the last enter word, means the 0 index of last word is #, if YES then apply Spanable for EditText.
please have a look on below code.
define this variable on public level
int beforeChangeSize = 0, afterChangeSize = 0, cusrsorPos = 0, posOflastSpace = 0;
String lastcursorSubString = "";
#Override
public void afterTextChanged(Editable editable) {
if (afterChangeSize > beforeChangeSize) {
cusrsorPos = 0;
posOflastSpace = 0;
lastcursorSubString = "";
cusrsorPos = txt_search.getSelectionStart();
String sudString = txt_search.getText().toString().substring(0, cusrsorPos);
posOflastSpace = sudString.lastIndexOf(" ");
posOflastSpace = (posOflastSpace == -1) ? 0 : posOflastSpace;
lastcursorSubString = sudString.substring(posOflastSpace, cusrsorPos).trim();
if ((lastcursorSubString.length() > 1 &&(lastcursorSubString.charAt(0) == '#') {
textlable.setText(""+lastcursorSubString);
// txt_search.getText().replace(posOflastSpace+1, cusrsorPos, Html.fromHtml("<font color=#FE642E>" + lastcursorSubString + "</font>"));
// txt_search.showDropDown();
editable.setSpan(new ForegroundColorSpan(Color.RED),
posOflastSpace+1,
cusrsorPos,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
you should use combination of textWatcher and spannable text
use text watcher to see what user is typing and use spannable text to give special color or format to part of your text in textView or EditText
good tutorial for spannable text :
https://medium.com/google-developers/spantastic-text-styling-with-spans-17b0c16b4568
and documentation for text watcher here :
https://developer.android.com/reference/android/widget/TextView.html#addTextChangedListener(android.text.TextWatcher)
You can add your own TextChangedListener and implement onTextChanged method
myAutoTxtView.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence text, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence text, int start, int before, int count) {
if (text.charAt(start) == '#') {
//change color
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
this code to change color - use it in on text change listener like above (its kotlin you need to modify it to Java if you want to)
//get text
val str = editText.text.toString()
//get last word
val splitStr = str.trim { it <= ' ' }.split("\\s+".toRegex()).dropLastWhile {
it.isEmpty() }.toTypedArray()
val ColorWord = splitStr.last()
//get the sentence without the last word
val textButLast = str.substring(0, str.lastIndexOf(" "))
//change the last word color
val LastWord = "<font color='#EE0000'>$ColorWord</font>"
//put the last word with the sentence again
editText.setText(Html.fromHtml(textButLast + LastWord))

Prevent whitespace in a string after one is entered

I made a code where user can't enter first space in a string.
User is allowed to enter white space after min 2 characters.
I need to redefine my method so user enters white space once, and only once after the two or more characters. After that it should be prevented. How do I do that?
case UPDATE_NAME:
if (firstName.getText().toString().startsWith(" "))
firstName.setText(firstName.getText().toString().trim());
if (firstName.getText().toString().contains(" "))
firstName.setText(firstName.getText().toString().replace(" ", " "));
int indexOfSpace = firstName.getText().toString().lastIndexOf(" ");
if (indexOfSpace > 0) {
String beforeSpace = firstName.getText().toString().substring(0, indexOfSpace);
String[] splitted = beforeSpace.split(" ");
if (splitted != null && splitted.length > 0) {
if (splitted[splitted.length - 1].length() < 2)
firstName.setText(firstName.getText().toString().trim());
}
}
Use a regex pattern. I made one that should match your requirements.
\S{2}\S*\s\S*\n
Explanation:
\S{2} two non whitespace
\S* n non whitespace
\s a whitespace
\S* n non whitespace
\n newline (i only added that for regexr, you may not need it)
Alternate way:
Iterate over String.charAt(int), return false if there is a whitespace in the first two chars, count all whitespaces, return false if n > 1.
This method should meet your requirements:
private static boolean isValidFirstName(String firstName) {
if (firstName != null && !firstName.startsWith(" ")) {
int numberOfSpaces = firstName.length() - firstName.replace(" ", "").length();
if (firstName.length() < 2 || numberOfSpaces <= 1) {
return true;
}
}
return false;
}
What you need to do is use a TextWatcher
public class CustomWatcher implements TextWatcher {
private String myText;
private int count = 0;
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after){
myText= s;
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
//check if there is a space in the first 2 characters, if so, sets the string to the previous before the space
if(s.length() < 3 && s.contains(" "))
s= myText;
//if the length is higher than 2, and the count is higher than 0 (1 space added already), puts the string back if a space is entered
else if(s.contains(" ") && count > 0)
s= myText;
//If none of the above is verified and you enter a space, increase count so the previous if statement can do its job
else if(s.contains(" "))
count++;
}
}
And then, set it to your EditText
mTargetEditText.addTextChangedListener(new CustomWatcher());
You can control your editText(I assume) with a TextWatcher, you would only need to check inside afterTextChanged() if length is <2 and else if the string contains the char " ".

Manage the Phone Number inside the editText

I have doubt to manage the phone number in android. I want to looks like when user enter the number inside the EditText then formate entering looks like 999 999 9999 and after complete the entering thf format should be looks like (999) 999-9999. How can achieve this thing. I did my coding something but when user click on cross key of keyboad to back the text the it is not working perfect. Any help please!
Code:
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
String phone = edit_profilephone.getText().toString();
if(phone.length() == 3)
{
edit_profilephone.setText(phone + " ");
edit_profilephone.setSelection(4);
}
else if(phone.length() == 7)
{
edit_profilephone.setText(phone + " ");
edit_profilephone.setSelection(8);
}
else if (phone.length() == 12)
{
int maxLength = 14;
InputFilter[] fArray = new InputFilter[1];
fArray[0] = new InputFilter.LengthFilter(maxLength);
edit_profilephone.setFilters(fArray);
StringBuilder buileString = new StringBuilder();
String splitnumber[] = phone.split("\\s+");
for (int i=0; i<splitnumber.length; i++)
{
if (i == 0)
{
buileString.append("(" + splitnumber[i] + ")");
}
else if (i == 1)
{
buileString.append(" " + splitnumber[i]);
}
else
{
buileString.append("-" + splitnumber[i]);
}
}
edit_profilephone.setText(buileString.toString());
}
}
you can also go through with
EditText inputField = (EditText) findViewById(R.id.inputfield);
inputField.addTextChangedListener(new PhoneNumberFormattingTextWatcher());
For more Idea...
You can use PhoneNumberUtils.formatNumber() methods.
Or you can use a PhoneNumberFormattingTextWatcher. I've never used this before, but it seems to do all the work you want to do.
Also don't forget to put the text type in XML document for the edit text, it might help:) Good luck! Like this:
EditText
android:id="#+id/editTextId"
android:inputType="phone"
android:digits="0123456789+"
/>

Android, EditText events, Prevent some parts of the text can be deleted / changed

I try to add an event handle to a EditText object (a text area the use can edit) in my Android App to control what the use can edit or not.
Say I have this text in my EditText:
* Hello
* World
* On You...
I will attach a controller that allows the user to only edit the Hello, World or On You, and if the user try to edit or remove the * and the first space after * the system will stop the edit.
On Java SE I can use Document.remove(int, int) for getting event while an user try to remove or replace a part of the text and then stop the edit.
Is there a similar API for android EditText?
I have tried using TextWatcher but from what I know this is not going to help me,
I know method public void onTextChanged(CharSequence s, int start, int before, int count) give some notes about the which text user remove but this seem unreliable.
And this give me not a way for this matter to stop the edit of use.
EDIT:
Can I use a Spanner for prevent edit to be do for a part of the text? As a readonly spanner?
Someone knows a good way to fix my problems?
I think I has final find a working solustion, but has to be try more deeply to know if this exist some buggs or errors.
public abstract class TextListener implements InputFilter {
public abstract CharSequence removeStr(CharSequence removeChars, int startPos);
public abstract CharSequence insertStr(CharSequence newChars, int startPos);
public abstract CharSequence updateStr(CharSequence oldChars, int startPos, CharSequence newChars);
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
CharSequence returnStr = source;
String curStr = dest.subSequence(dstart, dend).toString();
String newStr = source.toString();
int length = end - start;
int dlength = dend - dstart;
if (dlength > 0 && length == 0) {
// Case: Remove chars, Simple
returnStr = TextListener.this.removeStr(dest.subSequence(dstart, dend), dstart);
} else if (length > 0 && dlength == 0) {
// Case: Insert chars, Simple
returnStr = TextListener.this.insertStr(source.subSequence(start, end), dstart);
} else if (curStr.length() > newStr.length()) {
// Case: Remove string or replace
if (curStr.startsWith(newStr)) {
// Case: Insert chars, by append
returnStr = TextUtils.concat(curStr.subSequence(0, newStr.length()), TextListener.this.removeStr(curStr.subSequence(newStr.length(), curStr.length()), dstart + curStr.length()));
} else {
// Case Replace chars.
returnStr = TextListener.this.updateStr(curStr, dstart, newStr);
}
} else if (curStr.length() < newStr.length()) {
// Case: Append String or rrepace.
if (newStr.startsWith(curStr)) {
// Addend, Insert
returnStr = TextUtils.concat(curStr, TextListener.this.insertStr(newStr.subSequence(curStr.length(), newStr.length()), dstart + curStr.length()));
} else {
returnStr = TextListener.this.updateStr(curStr, dstart, newStr);
}
} else {
// No update os str...
}
// If the return value is same as the source values, return the source value.
return TextUtils.equals(source, returnStr) ? source : returnStr;
}
}
From this code I can easy prevent edit on select part of the text by lookup were in the text I try to edit.

android how an EditText work as AutoComplete

I want my EditText should work as AutoComplete, for that I write in XML file
android:inputType="textAutoComplete|textAutoCorrect"
but it's not working.
I am working with API v2.2 and my Activity extends MapActivity, there I put a simple EditText and a button named "Search". so if we type the location name in EditText and press search button means it should go to that location in map.
So I want that EditText to work as a AutoComplete.
How can I do that?
Just use an AutoCompleteTextView instead of normal EditText.
hello-autocomplete will be helpful.
EDIT: The above link looks like has expired. The new page is here: https://developer.android.com/training/keyboard-input/style#AutoComplete
First convert your EditText->AutoCompleteTextView
Then link your XML file to the AutoCompleteTextView using a ArrayAdapter
Assume that the XML string-array you created is named as list_of_countries then it can be linked to your AutoCompleteTextView as follows:
String[] countries = getResources().getStringArray(R.array.list_of_countries);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,countries);
actv.setAdapter(adapter);
I use this code:
1) On AndroidManifest.xml
<uses-permission android:name="android.permission.GET_ACCOUNTS"></uses-permission>
2) On xml layout you must use AutoCompleteTextView instead of EditText.
<AutoCompleteTextView
android:id="#+id/autoCompleteTextView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:text="AutoCompleteTextView" />
3) Use this on Activity file
private ArrayAdapter<String> getEmailAddressAdapter(Context context) {
Account[] accounts = AccountManager.get(context).getAccounts();
String[] addresses = new String[accounts.length];
for (int i = 0; i < accounts.length; i++) {
addresses[i] = accounts[i].name;
}
return new ArrayAdapter<String>(context, android.R.layout.simple_dropdown_item_1line, addresses);
}
4) On onCreate activity:
AutoCompleteTextView autoCompleteTextView1 = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
autoCompleteTextView1.setAdapter(getEmailAddressAdapter(this));
Default ArrayAdapter filters only by the first characters. In case you want to see also words which contain the searching keyword, you need to use a custom ArrayAdapter and override its getView and getFilter methods. Take a look at a complete solution I provided in another StackOverflow question: https://stackoverflow.com/a/37298258/1808829
Some code fragment:
public class AutoSuggestAdapter extends ArrayAdapter
{
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
// handle view here
}
#Override
public Filter getFilter()
{
// implement filtering here
}
}
This code for change settings of MultiAutoCompleteTextView
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,codeKeyWords);
MultiAutoCompleteTextView autoCompleteTextView1 = (MultiAutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
autoCompleteTextView1.setAdapter(adapter);
autoCompleteTextView1.setThreshold(1);
autoCompleteTextView1.setTokenizer(new this.CommaTokenizer());
And below that code for make spliting words by space char and \n charactes.. (Why we need this code? Because Normal multiAutoComplete.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer()); like that and it make spliting the words by ',' character, But our code help you to make that spliting by these characters ' ' and '\n' )
/**
* This simple Tokenizer can be used for lists where the items are
* separated by a comma and one or more spaces.
*/
public static class CommaTokenizer 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) == '\n') {
i++;
}
return i;
}
public int findTokenEnd(CharSequence text, int cursor) {
int i = cursor;
int len = text.length();
while (i < len) {
if (text.charAt(i) == '\n') {
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 + "\n");
TextUtils.copySpansFrom((Spanned) text, 0, text.length(),
Object.class, sp, 0);
return sp;
} else {
return text + " ";
}
}
}

Categories

Resources