Android - Override user edittext input and add characters towards a specific text? - android

So I'm currently trying to achieve the following: I have one big piece of text not stored in my app yet. I will have one big EditText and what I want to do is when a user touches any key on the keyboard, a part of my text (like 2 or 3 characters at the time) should appear in the EditText. Then when a user touches a key again, another 2 or 3 characters of the text should appear inside the EditText. I've thought a lot about it but I can't seem to find the right approach to do it. Where to store my Text and how to code so that the app overrides whatever the user inputs and adds 2 or 3 characters in the EditText according to my text that I need to store somewhere.
Any ideas?

Take a look at
http://developer.android.com/reference/android/text/TextWatcher.html
Implement a TextWatcher and check the user input in onTextChanged() to determine the user input. Mark the input the user has made with a Span (which can be any custom object, it is just used to tag the text area), so you can later look it up with Editable#getSpans() in afterTextChanged(), where you can replace the whole span with your override text.
Code idea (untested):
onTextChanged(CharSequence s, int start, int before, int count){
((Spannable)s).setSpan(new MyMarkObject(), start, start+count, Spannable.SPAN_MARK_MARK)
}
afterTextChanged(Editable s)
{
MyMarkObject[] markers = s.getSpans(0, s.length(), MyMarkObject.class);
for (MyMarkObject marker: markers){
int start = s.getSpanStart(marker);
int end = s.getSpanEnd(marker);
s.replace(start, end, getYourDesiredReplacementTextFor(s.subSequence(start,end));
}
}

Related

Why TextWatcher needed

So, after going through some docs regarding TextWatcher, I'm still not too sure why it's actually needed. Any help with real example (no code) will be great. Thanks.
TextWatcher is needed to know if a field text has been changed.
Presume you have a mobile number, and you need to check the length of it. As a standard mobile number should contain 10 digits. You have an error field at the side which will go away once the edittext length will be greater than 10. How will you know that now the length is greater than 10?
To overcome this we have textwatcher method which watch over the edittext field. Generally we will check length of edittext in AfterTextChanged callback and it will work in realtime. After that you can make your logics behind what to do after the length is greater than 10.
This is just an example. There are certain many more ways in which you can use textwatcher.
TextWatcher :
TextWatcher is used to keep watch on the EditText content while user inputs the data. It allows you to keep track on each character when entered on EditText. A Text Watcher is really helpful for scenarios like login/register screen validation.
The TextWatcher have Three method is below :
Method 1 : afterTextChanged(Editable s)
=> This method is called to notify you that, somewhere within s, the text has been changed.
Method 2 : beforeTextChanged(CharSequence s, int start, int count, int after)
=> This method is called to notify you that, within s, the count characters beginning at start are about to be replaced by new text with length after.
Method 3 : onTextChanged(CharSequence s, int start, int before, int count)
=> This method is called to notify you that, within s, the count characters beginning at start have just replaced old text that had length before.

Is there any way to detect the type of softInput Keyboard visible

I had 6 EditText in a row to enter mac address, so after validating the user input in the macAddress EditText, if the no. of entries in one EditText becomes 2, i would call the focus on next edit box, as shown below.
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
//myMacArray is an array for storing macaddress editTexts ID
//mIndex represents the the index for for each EditText
if((myMacArray [mIndex]).getText().length() == 2)
if(mIndex < 5)
myMacArray [mIndex+1].requestFocus();//requesting focus to
//next editText
}
Now, if i the user is using the soft Qwerty keypad then its working fine....but in case of 3X4 keypad if the user wants to enter "1b"(inputing "b" in 3x4 keypad will require to press the 2nd button twice) in any macAddress' editText , it wont work as the focus is now shifted to next editBox just after the first user click.
Please let me know if there is a way to detect the type of keypad opened by user or some other way to deal with this
You can "force" the type of keyboard you want to come up by specifying the
android:inputType="<...>"
attribute in your edittext. If your users are going to be typing letters and numbers there is no reason to let them use a phone pad.
https://developer.android.com/training/keyboard-input/style.html
https://developer.android.com/reference/android/widget/TextView.html#attr_android:inputType

How to clear 'text-watcher' previous value in android?

I am using onTextChanged(CharSequence s, int start, int before, int count) of Text watcher which is attached to MultiAutoCompleteTextView in my activity.
When I type some text for eg. 'nik' in MultiAutoCompleteTextView , then drop down list opens with some suggested sentences, when one item is selected from the drop down eg. (nikhil kaushik;) and then I do back press too delete a character, every thing gets deleted expect initial search value 'Nik'.
How to prevent this, I don't want every thing to get deleted, only last character should be deleted from 'nikhil kaushik;'.
Request you to please help me on this.
Set empty string "" in the text view at the end of your onTextChanged method or Override afterTextChanged method of text watcher and set text view with empty string.

EditText.setText() gives index out of bounds

I'm having an error I can't seem to wrap my head around. I'm writing an app that allows the user to send text from an EditText to a TextView. If the user makes a mistake, the user can hit the space key to bring the most recent text sent from the EditText to the TextView. This works sometimes, but other times, it gives me an IndexOutOfBounds exception.
textInput is an EditText, back1,2,3 are the three most recent strings (with back1 the most recent)
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(count==1&&before==0&&s.toString().equals(" ")){
textInput.setText(back1);
}else if(s.toString().equals(back1 + " ")){
textInput.setText(back2);
}else if(s.toString().equals(back2 + " ")){
textInput.setText(back3); //causes error if back2 > back3
}
textInput.setSelection(textInput.getText().toString().length());
The above code checks if the user hit the space key, and if so, what to do with it. If the user pressed space on an empty EditText, they get the last thing they sent. If they hit space again, they get the next to last thing they sent, and so on. This is still a bit rough, but I hope you get the idea.
The OutOfBounds exception comes from taking a large item in the EditText, hitting space, and setting the EditText to a smaller string. I assumed it was because the cursor is at the end of the EditText and could no longer be there when the text got smaller, so I tried adding textInput.setSelection(0) right before the setText(). That didn't help. I also tried setting the EditText to setText(""). That didn't work either. If I comment out the lines of setText(back#), everything works fine.
An example:
A user types in "hello", "hi" and "hey" in that order.
back3 = hello, back2 = hi, and back1 = hey.
Hitting space once will set the EditText to "hey"
A second tap will crash, since the setSpan(3...4) ends beyond length 2, presumably because back 1 is larger than back2. It is supposed to set the text in the EditText to "hi"
From the TextWatcher documentation:
public abstract void onTextChanged (CharSequence s, int start, int before, int count)
Since: API Level 1
This method is called to notify you that, within s, the count characters beginning at start have just replaced old text that had length before. It is an error to attempt to make changes to s from this callback.
(My emphasis.)
You should use afterTextChanged instead if you want to change the text more in response to an existing change. Even in this case, your handler will be called re-entrantly when you change the text from afterTextChanged, so use an extra precaution to make sure you won't get into an infinite loop, such as something like this:
public void afterTextChanged (Editable s) {
static boolean is_reentrant = false;
if (!is_reentrant) {
is_reentrant = true;
try {
// do stuff
} finally {
is_reentrant = false;
}
}
}
I haven't tested this exact snippet, but something like that will make your code only run if it's not already running. You don't need to worry about thread-safety in this case, because it's only being called from inside the same thread.

Android - TextWatcher is invoked once for each character in pasted text

I've added a TextWatcher to an EditText and am listening for changes in the text via the onTextChanged(CharSequence s, int start, int before, int count) method. When I paste text that has say 10 characters, into this EditText, onTextChanged() gets called 10 times, once for each character in the text I pasted, from left to right. I want onTextChanged() to be called only once after all 10 characters have been pasted into the EditText. I'm sure this should be possible, because otherwise what's the point in having the "count" param if it's always going to be 1?
count won't always be 1: for instance, if you select and delete a block of text or if you choose an autocomplete option.
In any case, the details of whether pasting happens in one chunk or one character at a time is an implementation detail, and if you rely on either behavior it's likely your app will break in the future.
Try using afterTextChanged it will only get one call

Categories

Resources