长久以来,我一直困惑于这个问题。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 );
}
}
这是正确的工作(基本测试
但是,如果我开始删除 "5公里 "的文字,就会出现这样的情况。setSpan
当不再检测到图案时,不会刷新到正常状态。
所以我在想,也许 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 );
}
}
但还是不能正常工作
我认为你应该尝试 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
}
我想我现在更明白了。
如果我说的不对请指正,不要急着降级。
我很困惑,以为 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 );
}
希望对大家有所帮助。