TextWatcher afterTextChanged()'s Editable.replace() does not replace text in EditText properly - android

In the Android app, I have an EditText which should replace certain strings with values from app data.
for e.g. if user types $username it should get replaced with the name of whichever user is currently logged in.
The Editable parameter in afterTextChanged() method of TextWatcher applied on EditText replaces the $username with correct value but the problem is that after the $username is replaced with actual username if I press any character after that it is appended with username followed by pressed character.
e.g.
Say current logged in username is Joe
a. if the input is Hi this is #username
b. afterTextChanged() changes it to Hi this is Joe
c. Now if I press any other character(say I press g OR space) then text in EditText changes to Hi this is Joeusernameg OR Hi this is Joeusername
How do I get output as in step b?
etTemplateMessage.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
final String strUserNameCode = "$username";
String text = s.toString();
if(text.contains(strUserNameCode)){
int startIndex = text.indexOf(strUserNameCode);
int endIndex = startIndex + strUserNameCode.length();
Editable profileName = new SpannableStringBuilder(FileUtil.getUTF8String(settingDTO.getProfileName()));
s.replace(startIndex, endIndex, profileName);
}
}
});

on your afterTextChange method you should set text to the edit text. And String has replace(CharSequence old, CharSequence new) method you can also use it.
like this,
PublishSubject publishSubject = PublishSubject.create();
publishSubject.debounce(200, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(query -> onTextChanged(query.toString()));
void onTextChanged(String text){
final String strUserNameCode = "$username";
etTemplateMessage.setText(text.replace(strUserNameCode, FileUtil.getUTF8String(settingDTO.getProfileName())));
}
and on your aftertextChange method call publishSubject.onNext( s.toString())
Note that you can achieve this with RxJava.

Related

Handle Change of TextView according to EditText with Empty value

I am using TextChangedListener on a EditText called "deviseValue" and make operations with it to show other values in sellValue and buyValue which are two TextViews, as follows :
deviseValue.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
#Override
public void afterTextChanged(Editable s) {
Double dDeviseValue = Double.valueOf(deviseValue.getText().toString());
Double sellResult = dDeviseValue*dSellValue;
Double buyResult = dDeviseValue*dBuyValue;
sellValue.setText(sellResult.toString());
buyValue.setText(buyResult.toString());
}
});
Everything works fine, BUT, when I remove all value of deviseValue (i.e : EMPTY) .. my app crashes !!
How to handle this situation so when user remove all value, deviseValue become automatically > 1. ?
App crashed because you try to convert a string value from a edittext to the double value. But when you cleared your edittext deviseValue.getText().toString() is ""(empty). That's why you got NumberFormatException.
Try to check deviseValue.getText().toString() before convert it to the double.
For example:
String dDeviseText = etEmail.getText().toString();
Double dDeviseValue = Double.valueOf(dDeviseText.isEmpty() ? "1" : dDeviseText);
And you should prevent input not a numbers characters for this edittext.

How to open a dialog window on press of # key in Android?

This the code that I've written but I am getting the full string and the function is only triggered if the first character is #. I want it to check for every instance of # and whenever the # key is pressed i want to open the dialog. I tried using the onKeyDown() but couldn't make it work.
override fun afterTextChanged(editable: Editable?) {
viewModel.onDoubtTextChanged(editable.toString())
if (editable.toString() == "#") {
openUserSuggestionDialog(doubtDescription.users as ArrayList<User>,viewModel)
}
editable contains the value which is being inputted into the TextView
Add a on TextChange Listener to your editText
editable.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//get the last String entered
String lala = editable.getText().toString();
String subChar = lala.substring(lala.length() - 1);
if(subChar.equals("#"))
openUserSuggestionDialog(doubtDescription.users as ArrayList<User>,viewModel)
}

android addTextChangedListener not fully deleting the text in Firebase when backspace

I was facing the problem with the addTextChangedListener that was not fully delete the text in Firebase. I state an example, I get my name from Firebase and setText() on the myname. So on myname editText has show my name there. When I wanted to edit, I click on editText, so I can remove the word by backspace, but when I backspace too fast, the text in editText was fully removed (client side) and there are some word did not delete on Firebase(server side).
Which mean the removing text value are not consistent and accurate with the client side and server side. The ordinary text of my name is Tommy, so I backspace until the Tommy word gone, so that was cleared but in Firebase it still showing the first character 'T' of my name.
But when I was clearing all word on the editText, I input new word such as "Hello", the Firebase will store Hello.
Code:
//delcare myname
private MultiAutoCompleteTextView myname;
myname.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if(!myname.getText().toString().trim().isEmpty()){
DatabaseReference nameRef = FirebaseDatabase.getInstance().getReference()
.child(Config.URL_USER);
nameRef.child(uid).child("myName").setValue(userET.getText().toString());
parentActivity.updateHeaderUserName(myname.getText().toString());
}
}
});
This loops work until there is a single charcter in the edittext, so add an else loop and inside the else loops set the value as null

Edit text should allow text if a. alphabet +number b. alphabet +special character c. alphabet only

I am trying to generate a regular expression in Android which can satisfy following conditions:
Edit text can accept:
Alphabet only
Combination of Alphabet and number
Combination of Alphabet and special character
Should not accept:
a. Only Number
b. Only Special character
I tried alot but still, i didn't get any meaningful link. Please try to save my day.
I tried with regular expression (?!^\d+$)^.+$") which only valid alphanumric requirement. I am looking for such regular expression which fullfil my requirement.
It's really simple bro... just clear EditText if the text inside it doesn't have an alphabet .. as you have said ...
Should not accept a. Only Number b. Only Special character
TextWatcher mTextWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
boolean atleastOneAlpha = s.toString().matches(".*[a-zA-Z]+.*");
if (!atleastOneAlpha) {
editText.setText("");
}
}
#Override
public void afterTextChanged(Editable s) {
}
};
mTargetEditText.addTextChangedListener(mTextWatcher);

String array gets every character input instead of full word?

I have a logical error in my code below that produces the following result when an array-list personArray is printed out in my Activity_2:
Scenario:
If the user types their name as "John" in the EditText field name it will get added to the personArray array-list. Then it will get passed into my Activity_2 where it is printed out.
However, upon doing so the print out is this:
[J, Jo, Joh, John]
It's the same for my other EditText fields. I just want to add the whole word to my personArray and not every character as I typed it in.
My variables:
ArrayList<String> personArray = new ArrayList<>;
EditText name = (EditText) findViewById(R.id.name);
My Text Changed Listener inside my onCreate() in Activity_1:
name.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int i, int i1, int i2){
//it's supposed to add the user's FULL name input to personArray
//however it ends up adding EVERY character input instead
personArray.add(name.getText().toString().trim());
}
});
// repeat code for input for address, country, etc.
And my Intent inside my button click to go to my next Activity_2:
Intent intent = new Intent(Activity_1.this, Activity_2.class);
intent.putStringArrayListExtra("person", personArray);
startActvity(intent);
And getting the personArray string array in Activity_2:
final List<String> personList = getIntent().getStringArrayListExtra("person");
TextView txtPerson = (TextView) findViewById(R.id.txtPerson);
txtPerson.setText(personList);
I'm not sure where to place my personArray.add(name.getText().toString().trim());
Try to add the code in
#Override public void afterTextChanged(Editable s) {
// do stuff
}
UPDATE
Or you can get the whole input by using focus.
myEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
String editTextInput = myEditText.getText().toString();
}
}
});
You should use any character(For example comma / $ whatever ) or New Line key or Done key as the separator. Keep the hint for users that they input each new name with any character or new Line key.
So Your logic work will in onTextChanged method
#Override
public void onTextChanged(CharSequence s, int i, int i1, int i2){
if(s.equals(",") or check new Line or Done key character)
{
personArray.add(name.getText().toString().trim());
name.setText("");
}
}
Based on the docs for TextWatcher, the onTextChanged method is called whenever the text is changed. This means that this function will be called anytime the user changes the text. This includes typing in "J" "o" "h" and "n" when inputting the name "John".
This is why in your Activity_2 you're seeing the output as [J, Jo, Joh, John]. This just means the TextWatcher is doing what it's supposed to do.
Instead of watching every edit of every edit text you should instead grab the text from your form (and validate it) before launching your intent.
void validateDataAndLaunchActivity() {
String name = name.getText().toString().trim();
// get the rest of the inputs
// .. validate the input...
ArrayList<String> personArray = new ArrayList<>();
// insert items into your array and launch intent
Intent intent = new Intent(Activity_1.this, Activity_2.class);
intent.putStringArrayListExtra("person", personArray);
startActvity(intent);
}

Categories

Resources