如何在 EditText 中以不同颜色标记值?
Posted
技术标签:
【中文标题】如何在 EditText 中以不同颜色标记值?【英文标题】:How to hashtag value in different colour in EditText? 【发布时间】:2019-01-01 04:53:16 【问题描述】:当我写 "#data" 时,我正在EditText
中写一些文本,它的颜色应该改变,但不会改变我该怎么做。请检查以下我使用过的EditText
<EditText
android:id="@+id/et_simple"
android:layout_
android:layout_>
</EditText>
【问题讨论】:
观看textWatcher兄弟的lib。 @salman developer.android.com/reference/android/text/TextWatcher 【参考方案1】:希望这个解决方案会有所帮助..!
我使用了这个解决方案,非常有用!就像在你的 editText 上添加 textWatcher 接口并监听 textChange 并找出单词是否以 hashTag 开头然后调用该单词的 Change The color 方法!它有一些缺陷,但这些都是可以忽略的,请看这个简单的。
Spannable mspanable;
int hashTagIsComing = 0;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText edtTxtMine = (EditText) findViewById(R.id.editText1);
mspanable = edtTxtMine.getText();
edtTxtMine.addTextChangedListener(new TextWatcher()
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
String startChar = null;
try
startChar = Character.toString(s.charAt(start));
Log.i(getClass().getSimpleName(), "CHARACTER OF NEW WORD: " + startChar);
catch(Exception ex)
startChar = "";
if (startChar.equals("#"))
changeTheColor(s.toString().substring(start), start, start + count);
hashTagIsComing++;
if(startChar.equals(" "))
hashTagIsComing = 0;
if(hashTagIsComing != 0)
changeTheColor(s.toString().substring(start), start, start + count);
hashTagIsComing++;
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after)
// TODO Auto-generated method stub
@Override
public void afterTextChanged(Editable s)
// TODO Auto-generated method stub
);
private void changeTheColor(String s, int start, int end)
mspanable.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.color)), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
【讨论】:
当您更改光标位置并开始随机添加或删除文本或主题标签时,它会开始做一些奇怪的事情,它最终会以更改的颜色结束写入所有内容,无论是否有主题标签。【参考方案2】:您可以轻松使用 CodeView 库突出显示主题标签、电子邮件或数据格式
CodeView mCodeView = findViewById(R.id.codeView);
Pattern hashTagPattern = Pattern.compile("#[a-zA-z0-9]+");
mCodeView.addSyntaxPattern(hashTagPattern, Color.BLUE);
您需要初始化它并使用colou为主题标签设置一个模式,然后您可以在运行时更改颜色,结果将是这样的
库链接:https://github.com/AmrDeveloper/codeview
【讨论】:
【参考方案3】:科特林
具有自定义属性的完整解决方案
<declare-styleable name="EditTextView">
<attr name="enableTagging" format="boolean"/>
</declare-styleable>
class EditTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatEditText(context, attrs, defStyleAttr)
private var hashtagindex = -1
private var enableTagging:Boolean = false
set(value)
field = value
invalidate()
requestLayout()
init
context.theme.obtainStyledAttributes(
attrs,
R.styleable.EditTextView, 0, 0).apply
try
enableTagging = getBoolean(R.styleable.EditTextView_enableTagging, false)
finally
recycle()
override fun onTextChanged(text: CharSequence?, start: Int, lengthBefore: Int, lengthAfter: Int)
text?.let handleTagging(text, start, lengthBefore, lengthAfter)
private fun handleTagging(text: CharSequence, start: Int, lengthBefore: Int, lengthAfter: Int)
if (!enableTagging || text.length <= start) return
if (text[start] == '#') hashtagindex = start
if (text[start] == ' ') hashtagindex = -1
// If hashtag then color the work
if (hashtagindex >= 0)
val spannableString = getText()
val foregroundSpan = ForegroundColorSpan(ContextCompat.getColor(context, R.color.colorPrimary))
spannableString?.setSpan(foregroundSpan, hashtagindex, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
这是为 EditText 启用标记的方法
<com.example.xyz.util.editbox.EditTextView
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:id="@+id/et"
android:layout_
android:layout_
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
custom:enableTagging="true"
tools:textAppearance="@style/TextAppearance.AppCompat.Moment.Date"
tools:text="Name the "/>
编辑:
如果您删除任何字符或您的编辑文本是多行的,上述机制将不起作用,以下应该起作用:
private fun handleTagging(text: CharSequence, start: Int, lengthBefore: Int, lengthAfter: Int)
if (!enableTagging || text.length <= start) return
val formattedText = text.substring(0, start).trim();
val lastWord = formattedText.split(Regex("\\s+")).last()
val tagIndex = if (lastWord.isNotEmpty() && lastWord[0] == '#') formattedText.lastIndexOf('#') else -1
if (tagIndex >= 0)
val foregroundSpan = ForegroundColorSpan(ContextCompat.getColor(context, R.color.colorPrimary))
getText()?.setSpan(foregroundSpan, tagIndex, start + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
或者如果你像我一样喜欢扩展,这可以重构为
fun CharSequence.getTagIndices(toIndex:Int = 0):Pair<Int, Int>?
val formattedText = substring(0, toIndex).trim()
val lastWord = formattedText.split(Regex("\\s+")).last().trim()
if (!lastWord.startsWith('#') || lastWord.endsWith('#')) return null
val startIndex = formattedText.lastIndexOf('#')
val endIndex = formattedText.length - 1
if (startIndex < 0 || endIndex < 0) return null
return Pair(startIndex, endIndex)
private fun handleTagging(text: CharSequence, start: Int, lengthBefore: Int, lengthAfter: Int)
if (!enableTagging || text.length <= start) return
text.getTagIndices(start + 1)?.let
val foregroundSpan = ForegroundColorSpan(ContextCompat.getColor(context, R.color.colorPrimary))
getText()?.setSpan(foregroundSpan, it.first, it.second + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
【讨论】:
EditTextView 没有获得焦点。当用户点击它时光标会闪烁,然后消失。【参考方案4】:我已经尝试了其他人提到的所有上述方法。没有任何工作正常。但它工作正常
mSpannable = binding?.captionLayout?.etInput?.text
binding?.captionLayout?.etInput?.addTextChangedListener(object : TextWatcher
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int)
override fun onTextChanged(short_text: CharSequence, start: Int, before: Int, count: Int)
val text = binding?.captionLayout?.etInput?.text.toString()
var last_index = 0
text.trim().split(Regex("\\s+")).forEach
if (it.isNotEmpty() && it[0] == '#')
//here you can style the hashtag text(I have made it bold and black)
val boldSpan = StyleSpan(Typeface
.BOLD)
val foregroundSpan = ForegroundColorSpan(ContextCompat.getColor(requireActivity(), R.color.black))
mSpannable?.setSpan(foregroundSpan, text.indexOf(it,startIndex = last_index), text.indexOf(it,startIndex = last_index)+it.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
mSpannable?.setSpan(boldSpan, text.indexOf(it,startIndex = last_index), text.indexOf(it,startIndex = last_index)+it.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
last_index+=it.length-1
override fun afterTextChanged(s: Editable?)
)
【讨论】:
以上是关于如何在 EditText 中以不同颜色标记值?的主要内容,如果未能解决你的问题,请参考以下文章