【问题标题】:android on Text Change Listenerandroid on Text Change Listener
【发布时间】:2014-01-16 11:00:41
【问题描述】:

我有一个情况,有两个字段。 field1field2。我所想要的 当field1 更改时,to do 为空field2,反之亦然。所以只在最后 一个字段上有内容。

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("");
   }
  });

如果我只将addTextChangedListener 附加到field1,它工作正常,但是当 我对应用程序崩溃的两个领域都这样做。显然是因为他们试图改变 彼此无限期。一旦field1 更改,此时它会清除field2 field2 已更改,因此它将清除 field1 等等...

有人可以提出任何解决方案吗?

【问题讨论】:

  • 对于新用户,使用字符串的可观察字段进行双向数据绑定,因为这里提供的所有解决方案都可能产生starting waiting blocking gc alloc这种类型的错误,甚至可能导致崩溃和挂了..所以去数据绑定,这是安全的,现在被谷歌推荐..

标签: java android textview onchange


【解决方案1】:

您可以添加检查以仅在字段中的文本不为空时(即长度不为 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("");
   }
  });

TextWatcherhere 的文档。

也请尊重naming conventions

【讨论】:

  • 如何在所有字段更改后检测,因为它每次更改时都会检测到,当按下任何按钮时。
【解决方案2】:

Kotlin 中只需使用 KTX 扩展 功能: (它使用TextWatcher

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


导入core-KTX:

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

【讨论】:

【解决方案3】:

我知道这是旧的,但总有一天有人可能会再次遇到这个。

我有一个类似的问题,我会在 EditText 上调用 setText,而当我不想要它时会调用 onTextChanged。我的第一个解决方案是在调用 setText() 后编写一些代码来撤消侦听器造成的损害。但这不是很优雅。 经过一些研究和测试后,我发现使用 getText().clear() 清除文本的方式与 setText("") 大致相同,但是由于它没有设置文本,因此不会调用侦听器,因此解决了我的问题。我将所有 setText("") 调用都切换到 getText().clear() 并且不再需要绷带,所以也许这也可以解决您的问题。

试试这个:

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();
   }
  });

【讨论】:

    【解决方案4】:

    如果您使用 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) {}
        })
    

    【讨论】:

      【解决方案5】:
      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) {}
      })
      

      【讨论】:

        【解决方案6】:

        答案有点晚,但这是一个可重复使用的解决方案:

        /**
         * 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);
        }
        

        因此,当使用上述方法时,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) {
            }
        }
        

        【讨论】:

          【解决方案7】:

          我为此编写了自己的扩展程序,对我很有帮助。 (科特林)

          你只能这样写:

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

          我的扩展:

          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)
              }
          })}
          

          【讨论】:

          • 谢谢。但是在这种情况下我不理解 Kotlin 语法。您能否指导我了解“可编辑 ->”事物的语法,以及如何全局覆盖不影响其他活动中所有 EditTexts 的 EditText 字段?
          • 对不起@Bungles 我听不懂。你想做什么?
          • 我只是想看懂你上面的代码。
          • 我在编辑文本中添加了一个文本更改监听器。每次使用作为参数添加的“action”函数进行更改时,此侦听器都会返回一个值。
          【解决方案8】:

          我也遇到了同样的问题并不断收到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;
                  }
              }
          });
          

          最初声明 boolean skipOnChange = false;

          【讨论】:

          • "stack full" 我想你的意思是 Stack Overflow ;)
          【解决方案9】:

          你也可以使用 hasFocus() 方法:

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

          针对我正在处理的一项大学作业进行了测试,以便在用户输入温度标度时进行转换。效果很好,而且更简单。

          【讨论】:

          • 用户输入时editText.setText呢? EditText 在这种情况下具有焦点
          • 最佳解决方案。
          【解决方案10】:

          在将另一个 EditText 设置为空之前检查字符串。如果Field1 为空,那么为什么需要再次更改为(“”)?因此您可以使用 s.lenght() 或任何其他解决方案来检查您的字符串的大小

          另一种检查字符串长度的方法是:

          String sUsername = Field1.getText().toString();
          if (!sUsername.matches(""))
          {
          // do your job
          }
          

          【讨论】:

            【解决方案11】:
            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) {
            
                        }
                    });
            

            在这段代码中,noteid 基本上是被收回的参数,它们被放入缩进或通过缩进传递。

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

            下面的代码基本上是额外的代码,如果你想更清楚地理解的话。

            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.
            

            新的活动代码命名为 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) {
            
                        }
                    });
                }
            }
            

            【讨论】:

              【解决方案12】:

              我们可以在编辑文本之前删除字段的 TextWatcher,然后在编辑文本后将其添加回来。

              field1field2 的文本观察器声明为单独的变量,为它们命名:例如对于 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) {
              
                  }
              
              };
              

              然后使用其名称添加观察者: field1.addTextChangedListener(Field_1_Watcher) 代表 field1,以及 field2.addTextChangedListener(Field_2_Watcher) 代表 field2

              在更改 field2 文本之前删除 TextWatcher: field2.removeTextChangedListener(Field_2_Watcher) 更改文本: field2.setText("")

              然后将 TextWatcher 添加回来: field2.addTextChangedListener(Field_2_Watcher)

              对其他字段执行相同操作

              【讨论】:

                【解决方案13】:

                另一种可能对某人有所帮助的解决方案。编辑后有 2 个 EditText 相互更改。默认情况下,它会导致循环。

                使用变量:

                Boolean uahEdited = false;
                Boolean usdEdited = false;
                

                添加文本观察器

                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;
                        }
                    });
                

                不要批评太多。我是新手开发者

                【讨论】:

                  【解决方案14】:

                  onCreate方法中动态添加背景:

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

                  还可以从 XML 中删除背景。

                  【讨论】:

                    猜你喜欢
                    • 2014-11-22
                    • 2023-04-02
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-12-14
                    • 1970-01-01
                    • 1970-01-01
                    • 2023-02-09
                    相关资源
                    最近更新 更多