android setSpan to editText

问题描述 投票:0回答:1

长久以来,我一直困惑于这个问题。setSpan 因为它看起来很容易,但并不总是如愿以偿地工作。

在我最后的尝试中,我试图 setSpan 到识别的模式。当用户开始输入 "5公斤托马 "时,"5公斤 "将被高亮显示。

我使用了下面的代码来实现这一点,作为下面的 TextWatcher 听者

@Override
    public void afterTextChanged(Editable s) {

        String quantity = mAutoCompleteAdapter.getQuantity();

        if (!quantity.isEmpty()) {
            int index = mAutoCompleteAdapter.getQuantityIndex();
            final StyleSpan styleSpan = new StyleSpan( Typeface.BOLD_ITALIC );
            s.setSpan( styleSpan, index, index + quantity.length(), Spanned.SPAN_MARK_MARK );
        }
    }

这是正确的工作(基本测试

enter image description here

但是,如果我开始删除 "5公里 "的文字,就会出现这样的情况。setSpan 当不再检测到图案时,不会刷新到正常状态。

enter image description here

所以我在想,也许 setSpan 是保存在内存中还是什么,我需要每次设置整个字符串跨度。所以我尝试了下一个代码。

@Override
    public void afterTextChanged(Editable s) {

        if (s.length() > 0) {

            String quantity = mAutoCompleteAdapter.getQuantity();
            int index = 0;

            if (!quantity.isEmpty()) {
                index = mAutoCompleteAdapter.getQuantityIndex();
                StyleSpan styleSpan = new StyleSpan( Typeface.BOLD_ITALIC );
                s.setSpan( styleSpan, index, index + quantity.length(), Spanned.SPAN_MARK_MARK );
            }

            StyleSpan styleSpanNormal = new StyleSpan( Typeface.NORMAL );
            s.setSpan( styleSpanNormal, index + quantity.length(), s.length(), Spanned.SPAN_MARK_MARK );
        }
    }

但还是不能正常工作

android android-edittext
1个回答
0
投票

我认为你应该尝试 textChangedListener 作为其方法 onTextChanged 将帮助您在用户输入新文本时检查文本,在文本视图中删除一些文本。

textview.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) {
               //place your code here
               //the code here will work when user is changing the text

            }

0
投票

我想我现在更明白了。

如果我说的不对请指正,不要急着降级。

我很困惑,以为 EditText.getText() 正在返回一个 String 甚至当我看到 afterTextChanged(Editable s) 使用 Editable我还以为是一个类似的对象。

直到现在我才注意到我可以用 getText()那么 setSpan 而不使用 setText我意识到,我实际上是在获取实际的对象,从而直接操纵它。

这意味着,每一个 getText() 或使用 TextWatcher 听者 setSpan 仍然存在,我需要清除它。

起初我以为 clearSpans() 将会起到作用,但它似乎也清除了所有其他的东西。所以,我先设置默认的跨度,然后再设置正确的跨度。

例如,我注意到自动完成适配器和TextWatcher的顺序并不总是相同。

//Clear old span
s.setSpan( new BackgroundColorSpan( Color.TRANSPARENT),
                0,
                s.length(),
                Spanned.SPAN_MARK_MARK );

//set new span
s.setSpan( new BackgroundColorSpan( Color.RED),
                    indexStart,
                    indexStart + mQuantity.length(),
                    Spanned.SPAN_MARK_MARK );

此外,我注意到自动完成适配器和TextWatcher的顺序并不总是一样的。当使用日志时,我注意到大多数情况下,TextWatcher在自动完成之前开火,但并不总是这样。要么是这样,要么是其中一个可以发射,而另一个呢!我不确定。

总之,因为这个顺序很重要,因为适配器会检查文本,所以我用的是 MutableLiveData<String> 追踪 mQuantity 值,并依次修改跨度

//In AutoComplete adapter
public MutableLiveData<String> getQuantity() {
    if (mQuantity == null) {
        mQuantity = new MutableLiveData<>();
    }
    return mQuantity;
}

//In handler constructor
mAutoCompleteAdapter.getQuantity().observe( (LifecycleOwner) activity, new 
Observer<String>() {
        @Override
        public void onChanged(String s) {
            mQuantity = s;
            refreshSpans();
        }
    } );

private void refreshSpans() {
    Editable s = mTextView.getText();
    clearEditTextSpan(s);

    if (!mQuantity.isEmpty()) {
        //Set span
        int indexStart = mAutoCompleteAdapter.getQuantityIndex();

        s.setSpan( new BackgroundColorSpan( Color.RED),
                indexStart,
                indexStart + mQuantity.length(),
                Spanned.SPAN_MARK_MARK );
    } 
}

private void clearEditTextSpan(Editable s) {
    s.setSpan( new BackgroundColorSpan( Color.TRANSPARENT),
            0,
            s.length(),
            Spanned.SPAN_MARK_MARK );
}

希望对大家有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.