简体   繁体   English

android 文本更改侦听器

[英]android on Text Change Listener

I have a situation, where there are two fields.我有一种情况,那里有两个领域。 field1 and field2 . field1field2 All I want to do is empty field2 when field1 is changed and vice versa.我只想在field1更改时清空field2 ,反之亦然。 So at the end only one field has content on it.所以最后只有一个字段有内容。

field1 = (EditText)findViewById(R.id.field1);
field2 = (EditText)findViewById(R.id.field2);

field1.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

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

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
      field2.setText("");
   }
  });

field2.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

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

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
     field1.setText("");
   }
  });

It works fine if I attach addTextChangedListener to field1 only, but when I do it for both fields the app crashes.如果我仅将addTextChangedListener附加到field1 ,它工作正常,但是当我对这两个字段执行此操作时,应用程序崩溃。 Obviously because they try to change each other indefinitely.显然是因为他们试图无限期地改变彼此。 Once field1 changes it clears field2 at this moment field2 is changed so it will clear field1 and so on...一旦field1发生变化,此时它会清除field2 field2已更改,因此它将清除field1等等......

Can someone suggest any solution?有人可以提出任何解决方案吗?

You can add a check to only clear when the text in the field is not empty (ie when the length is different than 0).您可以添加复选框以仅在字段中的文本不为空时(即长度不为 0 时)才清除。

field1.addTextChangedListener(new TextWatcher() {

   @Override
   public void afterTextChanged(Editable s) {}

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

   @Override    
   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
      if(s.length() != 0)
        field2.setText("");
   }
  });

field2.addTextChangedListener(new TextWatcher() {

   @Override
   public void afterTextChanged(Editable s) {}

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

   @Override
   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
      if(s.length() != 0)
         field1.setText("");
   }
  });

Documentation for TextWatcher here . 此处TextWatcher文档。

Also please respect naming conventions .也请尊重命名约定

I know this is old but someone might come across this again someday.我知道这很旧,但总有一天有人可能会再次遇到这个问题。

I had a similar problem where I would call setText on a EditText and onTextChanged would be called when I didn't want it to.我有一个类似的问题,我会在 EditText 上调用 setText ,而当我不想要它时会调用 onTextChanged 。 My first solution was to write some code after calling setText() to undo the damage done by the listener.我的第一个解决方案是在调用 setText() 之后编写一些代码来撤消侦听器造成的损害。 But that wasn't very elegant.但这不是很优雅。 After doing some research and testing I discovered that using getText().clear() clears the text in much the same way as setText(""), but since it isn't setting the text the listener isn't called, so that solved my problem.在做了一些研究和测试之后,我发现使用 getText().clear() 清除文本的方式与 setText("") 大致相同,但由于它没有设置文本,因此不会调用侦听器,因此解决了我的问题。 I switched all my setText("") calls to getText().clear() and I didn't need the bandages anymore, so maybe that will solve your problem too.我将我所有的 setText("") 调用切换到 getText().clear() 并且我不再需要绷带了,所以也许这也能解决你的问题。

Try this:试试这个:

Field1 = (EditText)findViewById(R.id.field1);
Field2 = (EditText)findViewById(R.id.field2);

Field1.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

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

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
      Field2.getText().clear();
   }
  });

Field2.addTextChangedListener(new TextWatcher() {

   public void afterTextChanged(Editable s) {}

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

   public void onTextChanged(CharSequence s, int start,
     int before, int count) {
     Field1.getText().clear();
   }
  });

In Kotlin simply use KTX extension function: (It uses TextWatcher )Kotlin 中只需使用KTX 扩展功能:(它使用TextWatcher

yourEditText.doOnTextChanged { text, start, count, after -> 
        // action which will be invoked when the text is changing
    }


import core-KTX :进口core-KTX :

implementation "androidx.core:core-ktx:1.2.0"

If you are using Kotlin for Android development then you can add TextChangedListener() using this code:如果您使用 Kotlin 进行 Android 开发,那么您可以使用以下代码添加TextChangedListener()

myTextField.addTextChangedListener(object : TextWatcher{
        override fun afterTextChanged(s: Editable?) {}

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
    })

I have also faced the same problem and keep on getting stackOverflow exceptions, and I come with the following solution.我也遇到了同样的问题并不断收到stackOverflow异常,我提供了以下解决方案。

edt_amnt_sent.addTextChangedListener(new TextWatcher() {    
    @Override
    public void afterTextChanged(Editable s) {
        if (skipOnChange)
            return;

        skipOnChange = true;
        try {
            //method
        } catch (NumberFormatException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            skipOnChange = false;
        }
    }
});

edt_amnt_receive.addTextChangedListener(new TextWatcher() {

    @Override
    public void afterTextChanged(Editable s) {

        if (skipOnChange)
            return;

        skipOnChange = true;
        try {
            //method
        } catch (NumberFormatException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            skipOnChange = false;
        }
    }
});

declared initially boolean skipOnChange = false;最初声明 boolean skipOnChange = false;

A bit late of a answer, but here is a reusable solution:答案有点晚,但这是一个可重用的解决方案:

/**
 * An extension of TextWatcher which stops further callbacks being called as 
 * a result of a change happening within the callbacks themselves.
 */
public abstract class EditableTextWatcher implements TextWatcher {

    private boolean editing;

    @Override
    public final void beforeTextChanged(CharSequence s, int start, 
                                                    int count, int after) {
        if (editing)
            return;

        editing = true;
        try {
            beforeTextChange(s, start, count, after);
        } finally {
            editing = false;
        }
    }

    protected abstract void beforeTextChange(CharSequence s, int start, 
                                                     int count, int after);

    @Override
    public final void onTextChanged(CharSequence s, int start, 
                                                int before, int count) {
        if (editing)
            return;

        editing = true;
        try {
            onTextChange(s, start, before, count);
        } finally {
            editing = false;
        }
    }

    protected abstract void onTextChange(CharSequence s, int start, 
                                            int before, int count);

    @Override
    public final void afterTextChanged(Editable s) {
        if (editing)
            return;

        editing = true;
        try {
            afterTextChange(s);
        } finally {
            editing = false;
        }
    }

    public boolean isEditing() {
        return editing;
    }

    protected abstract void afterTextChange(Editable s);
}

So when the above is used, any setText() calls happening within the TextWatcher will not result in the TextWatcher being called again:因此,当使用上述内容时,TextWatcher 中发生的任何setText()调用都不会导致再次调用 TextWatcher:

/**
 * A setText() call in any of the callbacks below will not result in TextWatcher being 
 * called again.
 */
public class MyTextWatcher extends EditableTextWatcher {

    @Override
    protected void beforeTextChange(CharSequence s, int start, int count, int after) {
    }

    @Override
    protected void onTextChange(CharSequence s, int start, int before, int count) {
    }

    @Override
    protected void afterTextChange(Editable s) {
    }
}

I wrote my own extension for this, very helpful for me.我为此编写了自己的扩展程序,对我很有帮助。 (Kotlin) (科特林)

You can write only like that :你只能这样写:

editText.customAfterTextChanged { editable -> 
    //You have accessed the editable object. 
}

My extension :我的扩展:

fun EditText.customAfterTextChanged(action: (Editable?)-> Unit){
    this.addTextChangedListener(object : TextWatcher {
       override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
       override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
       override fun afterTextChanged(editable: Editable?) {
        action(editable)
    }
})}

You can also use the hasFocus() method:您还可以使用 hasFocus() 方法:

public void onTextChanged(CharSequence s, int start,
     int before, int count) {
     if (Field2.hasfocus()){
         Field1.setText("");
     }
   }

Tested this for a college assignment I was working on to convert temperature scales as the user typed them in. Worked perfectly, and it's way simpler.我在大学作业中对此进行了测试,以在用户输入时转换温标。工作完美,而且更简单。

var filenameText = findViewById(R.id.filename) as EditText
filenameText.addTextChangedListener(object : TextWatcher {
    override fun afterTextChanged(s: Editable?) {
        filename = filenameText.text.toString()
        Log.i("FileName: ", filename)
    }
    
    override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
})

check String before set another EditText to empty.在将另一个EditText设置为空之前检查 String。 if Field1 is empty then why need to change again to ( "" )?如果Field1为空,那么为什么需要再次更改为 ( "" )? so you can check the size of Your String with s.lenght() or any other solution因此您可以使用s.lenght()或任何其他解决方案检查您的字符串的大小

another way that you can check lenght of String is:您可以检查字符串长度的另一种方法是:

String sUsername = Field1.getText().toString();
if (!sUsername.matches(""))
{
// do your job
}
editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }
            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if (noteid != -1) {
                    MainActivity.notes.set(noteid, String.valueOf(charSequence));
                    MainActivity.arrayAdapter.notifyDataSetChanged();
                }
            }
            @Override
            public void afterTextChanged(Editable editable) {

            }
        });

in this code noteid is basically arguments taken back which is being putted into the indent or passed through the indent.在这段代码中,noteid 基本上是取回的参数,这些参数被放入缩进或通过缩进传递。

  Intent intent = getIntent();
         noteid = intent.getIntExtra("noteid", -1);

the code on the downside is basically the extra code ,if you want to understand more clearly.缺点的代码基本上是额外的代码,如果你想更清楚地理解。

how to make the menu or insert the menu in our code , 
    create the  menu folder this the folder created by going into the raw
    ->rightclick->
    directory->name the folder as you wish->
    then click on the directory formed->
    then click on new file and then name for file as you wish ie the folder name file
    and now type the 2 lines code in it and see the magic.

new activity code named as NoteEditor.java for editing purpose,my app is basicley the note app.用于编辑目的的名为 NoteEditor.java 的新活动代码,我的应用程序基本上是笔记应用程序。

package com.example.elavi.notes;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.Toast;

import static android.media.CamcorderProfile.get;
public class NoteEditorActivity extends AppCompatActivity {
    EditText editText;
    int noteid;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_note_editor);
        editText = findViewById(R.id.editText);
        Intent intent = getIntent();
         noteid = intent.getIntExtra("noteid", -1);
        if (noteid != -1) {
            String text = MainActivity.notes.get(noteid);
            editText.setText(text);

           Toast.makeText(getApplicationContext(),"The arraylist content is"+MainActivity.notes.get(noteid),Toast.LENGTH_SHORT).show();
        }
        else
        {
            Toast.makeText(getApplicationContext(),"Here we go",Toast.LENGTH_SHORT).show();
            MainActivity.notes.add("");
            noteid=MainActivity.notes.size()-1;
        }
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }
            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if (noteid != -1) {
                    MainActivity.notes.set(noteid, String.valueOf(charSequence));
                    MainActivity.arrayAdapter.notifyDataSetChanged();
                }
            }
            @Override
            public void afterTextChanged(Editable editable) {

            }
        });
    }
}

We can remove the TextWatcher for a field just before editing its text then add it back after editing the text.我们可以在编辑文本之前删除字段的 TextWatcher,然后在编辑文本后将其添加回来。

Declare Text Watchers for both field1 and field2 as separate variables to give them a name: eg for field1field1field2 的Text Watchers 声明为单独的变量以给它们一个名称:例如对于field1

private TextWatcher Field_1_Watcher = new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void afterTextChanged(Editable s) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

};

then add the watcher using its name: field1.addTextChangedListener(Field_1_Watcher) for field1 , and field2.addTextChangedListener(Field_2_Watcher) for field2然后使用其名称添加观察者: field1.addTextChangedListener(Field_1_Watcher) for field1field2.addTextChangedListener(Field_2_Watcher) for field2

Before changing the field2 text remove the TextWatcher: field2.removeTextChangedListener(Field_2_Watcher) change the text: field2.setText("")在更改field2文本之前删除 TextWatcher: field2.removeTextChangedListener(Field_2_Watcher)更改文本: field2.setText("")

then add the TextWatcher back: field2.addTextChangedListener(Field_2_Watcher)然后将 TextWatcher 添加回来: field2.addTextChangedListener(Field_2_Watcher)

Do the same for the other field对另一个领域做同样的事情

Another solution that may help someone.另一种可能对某人有所帮助的解决方案。 There are 2 EditText which change instead of each other after editing.有 2 个 EditText 在编辑后会改变而不是彼此。 By default, it led to cyclicity.默认情况下,它会导致循环。

use variable:使用变量:

Boolean uahEdited = false;
Boolean usdEdited = false;

add TextWatcher添加文本观察器

uahEdit = findViewById(R.id.uahEdit);
usdEdit = findViewById(R.id.usdEdit);

uahEdit.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            if (!usdEdited) {
                uahEdited = true;
            }
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            String tmp = uahEdit.getText().toString();

            if(!tmp.isEmpty() && uahEdited) {
                uah = Double.valueOf(tmp);
                usd = uah / 27;
                usdEdit.setText(String.valueOf(usd));
            } else if (tmp.isEmpty()) {
                usdEdit.getText().clear();
            }
        }

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

usdEdit.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            if (!uahEdited) {
                usdEdited = true;
            }
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            String tmp = usdEdit.getText().toString();

            if (!tmp.isEmpty() && usdEdited) {
                usd = Double.valueOf(tmp);
                uah = usd * 27;
                uahEdit.setText(String.valueOf(uah));
            } else if (tmp.isEmpty()) {
                uahEdit.getText().clear();
            }
        }

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

Don't criticize too much.不要批评太多。 I am a novice developer我是新手开发者

etSearch.addTextChangedListener(object : TextWatcher {
     override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
          TODO("Not yet implemented")
     }

     override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
          TODO("Not yet implemented")
     }

     override fun afterTextChanged(p0: Editable?) {
          TODO("Not yet implemented")
     }
})

you use this你用这个
I have provided latest method for textchangelistner我已经为 textchangelistner 提供了最新的方法

edMsg.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                
                if (i2 == 0){
                    ////Edit text blanked
                } 
                
                String msg = charSequence.toString();/// your text on changed in edit text
                
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });
editText.addTextChangedListener(new TextWatcher() 
{
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) 
            {
            }

            @Override
            public void onTextChanged(CharSequence chr, int i, int i1, int i2) 
            {
                //Check char sequence is empty or not
                if (chr.length() > 0)
                {
                    //Your Code Here
                }
            }

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

Add background dynamically in onCreate method:onCreate方法中动态添加背景:

getWindow().setBackgroundDrawableResource(R.drawable.background);

also remove background from XML.还从 XML 中删除背景。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM