【问题标题】:How to update the same EditText using TextWatcher?如何使用 TextWatcher 更新相同的 EditText?
【发布时间】:2012-03-18 21:09:58
【问题描述】:

在我的 Android 应用程序中,我需要实现一个 TextWatcher 接口来实现onTextChanged。我遇到的问题是,我想用一些额外的字符串更新相同的 EditText。当我尝试这样做时,程序会终止。

 final EditText ET = (EditText) findViewById(R.id.editText1);
 ET.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count)
        {
            try
            {
                 ET.setText("***"+ s.toString());
                 ET.setSelection(s.length());
            }
            catch(Exception e)
            {
                Log.v("State", e.getMessage());
            }
        }

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

        }

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

我的程序终止了,即使我尝试在我的代码中捕获异常,它仍然终止。 有谁知道为什么会发生这种情况以及我如何做到这一点?谢谢。

【问题讨论】:

  • When I try to do this the program terminates. 这基本上意味着您应该提供可以在 LogCat 中找到的堆栈跟踪。这对我们有很大帮助!

标签: java android android-edittext textwatcher android-textwatcher


【解决方案1】:

这是一个对我有用的 sn-p

etPhoneNumber.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 (!s.toString().equals(Utils.getFormattedNumber(s.toString()))) {
                s.replace(0, s.length(), Utils.getFormattedNumber(s.toString()));
            }
        }
    });

Utils.getFormattedPhoneNumber() 是您返回格式化数字的方法

【讨论】:

    【解决方案2】:

    迟到的答案,如果有人看这就是我的做法。

    • 最初设置 addTextChangedListener
    • 在其中一个回调(比如 onTextChanged())中删除 addTextChangedListener
    • 仍然对接收更新感兴趣,请重新添加。

    这里是代码。

    editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                Log.d("log", "before");
            }
    
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
    
                Log.d("log", "after");
                editText.removeTextChangedListener(this);
    
                ediText.setText("text you wanted to put");
    
                editText.addTextChangedListener(this);
    
            }
    
            @Override
            public void afterTextChanged(Editable s) {
    
    
            }
        });
    

    【讨论】:

      【解决方案3】:

      作为对Zortkun's answer 的补充(示例代码已损坏),这就是您使用afterTextChanged() 更新相同的EditText 的方式:

      editText.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 editable) {        
              if (!editable.toString().startsWith("***")) {
                  editable.insert(0, "***");
              }        
          }
      });
      

      熟悉Editable接口,了解insert()以外的其他操作。

      请注意,很容易陷入无限循环(您所做的更改再次触发afterTextChanged()),因此通常您会在 if 条件内进行更改,如上所述。

      作为afterTextChanged() javadocs 说:

      从此回调中对 s 进行进一步更改是合法的,但是 小心不要让自己陷入无限循环,因为任何 您所做的更改将导致再次调用此方法 递归。

      【讨论】:

        【解决方案4】:

        TextView 的内容在onTextChanged 事件中不可编辑

        相反,您需要处理afterTextChanged 事件才能对文本进行更改。

        更详尽的解释见:Android TextWatcher.afterTextChanged vs TextWatcher.onTextChanged


        注意:错误onTextChanged

        显然,您正在通过不断更改 afterTextChanged 事件上的 文本 导致无限循环。

        来自the ref

        public abstract void afterTextChanged (Editable s)
        调用此方法是为了通知您,在 s 中的某处,文本已被 改变了。从此对 s 进行进一步更改是合法的 回调,但注意不要让自己陷入无限循环, 因为您所做的任何更改都会导致再次调用此方法 递归地。 ...

        • 建议 1:如果可以,请检查 s 是否已经在事件触发时是您想要的。

          @Override
          public void afterTextChanged(Editable s)
          {    
              if( !s.equalsIngoreCase("smth defined previously"))
                   s = "smth defined previously";              
          }
          
        • 建议 2:如果您需要做更复杂的事情(格式化、 验证)您可以使用synchronized 方法,如this post.

        注意 2:将输入格式化为部分隐藏,并用 n 个星号直到最后一个 4 个字符(****四个)

        您可以在建议 1 中使用类似的内容:

            @Override
            public void afterTextChanged(Editable s)
            {    
               String sText = ET.getText().toString()
        
                if( !isFormatted(sText))
                     s = format(sText);              
            }
            bool isFormatted(String s)
            {
             //check if s is already formatted
            }
        
            string format(String s)
            {
              //format s & return
            }
        

        【讨论】:

        • 您好 Zorkun,我尝试在 afterTextChanged(Editable s) 事件中添加相同的代码...仍然终止...您知道任何其他替代方法吗?谢谢
        • s 在 afterTextChanged(Editable s) 中是可编辑的。但它仍然不能分配给 EditText。
        • 是的,没错。它通过不断更改 afterTextChanged 事件上的文本而导致无限循环。问题是,我想隐藏 EditText 中的第一个字母,将某些字符作为 * 并让最后 4 个字符可见...
        • 谢谢...是的,可以通过一个简单的 if 条件限制它一遍又一遍地运行...非常感谢您的时间和帮助...!!!!
        • 无法从字符串转换为可编辑。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-04-19
        • 1970-01-01
        • 1970-01-01
        • 2011-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多