10. 监控TextView的变动

10.1 问题

应用程序需要持续监控TextView小部件(例如EditText)中文文本内容的变动情况。

10.2 解决方案

(API Level 2)
实现android.text.TextWatcher接口。textWatcher提供了3个文本更新过程中的回调方法:

public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
public void onTextChanged(CharSequence s, int start, int before, int count) { }
public void afterTextChanged(Editable s);

beforeTextChanged()和onTextChanged()方法主要用于提供提示功能,因为这两个方法实际上都无法修改CharSequence。如果要截获视图中输入的文本,当afterTextChanged()方法被调用时文本就有可能发生了变化。

10.3 实现机制

调用TextView.addTextChangedListener()方法将TextWatcher注册到TextView。注意,根据语法,可以将多个TextWatcher注册到一个TextView。

1. 字符计数器示例

TextWatcher的一个简单应用是创建EditText的字符计数器,能随着用户的输入和删除操作实时显示其中的字数。以下代码清单中的示例Activity就实现了这样一个TextWatcher,注册了一个EditText小部件并在Activity的标题上显示字符数。

字符计数器Activity

public class MyActivity extends Activity implements TextWatcher {

    EditText text;
    int textCount;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //创建EditText 小部件并添加监控器
        text = new EditText(this);
        text.addTextChangedListener(this);

        setContentView(text);
    }

    /* 实现TextWatcher的方法 */
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

    public void onTextChanged(CharSequence s, int start, int before, int end) {
        textCount = text.getText().length();
        setTitle(String.valueOf(textCount));
    }

    public void afterTextChanged(Editable s) { }

}

因为不需要修改用户正在输入的文本,所以可以调用onTextChanged()方法以获得字数,只要用户输入的文本发生变化就会回调该方法。其他的方法暂时没用,留空即可。

2. 货币符号格式化示例

SDK中有一些很方便的用于格式化文本输入的预定义TextWatcher实例;PhoneNumberFormattingTextWatcher就是其中之一。这些实例的任务就是在用户输入时将其按标准格式化,减少输入规范化数据的击键次数。
在以下代码清单中,我们创建了一个CurrencyTextWatcher,在TextView中插入货币符号和分隔点。

货币符号格式器

public class CurrencyTextWatcher implements TextWatcher {

    boolean mEditing;

    public CurrencyTextWatcher() {
        mEditing = false;
    }

    public synchronized void afterTextChanged(Editable s) {
        if(!mEditing) {
            mEditing = true;

            //strip符号
            String digits = s.toString().replaceAll("\\D", "");
            NumberFormat nf = NumberFormat.getCurrencyInstance();
            try{
                String formatted = nf.format(Double.parseDouble(digits)/100);
                s.replace(0, s.length(), formatted);
            } catch (NumberFormatException nfe) {
                s.clear();
            }

            mEditing = false;
        }
    }

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

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

注意:
在afterTextChanged()方法中修改Editable的值会导致TextWatcher方法被再次调用(因为刚刚修改了文本)。考虑到这一点,在实现自定义TextWatcher时,应该通过某个布尔变量或是其他跟踪机制来判断文本修改的来源,避免产生无限循环。
我们可以将这个自定义的文本格式化器应用于Activity中的EditText(参见以下代码清单)。

使用货币符号格式化器的Activity

public class MyActivity extends Activity {
 
   EditText text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        text = new EditText(this);
        text.addTextChangedListener(new CurrencyTextWatcher());

        setContentView(text);
    }
}

使用这个格式化器格式化用户输入,就可以很方便地在XML中定义EditText的android:inputType和android:digits约束来格式化用户的输入,从而保护字段不受输入错误的影响。特别是,为EditText加上android:digits = “0123456789”(注意末尾的小数点),不仅能保护此格式化器,对用户也有好处。

猜你喜欢

转载自blog.csdn.net/qq_41121204/article/details/83006293
10.