假设我们有一个简单的EditText,我希望将光标(插入符号)更改为其他颜色,在我们使用反射来访问私有字段之前,但是随着Android (29)的引入,我们现在可以使用textCursorDrawable
来设置闪烁光标的可绘制性。
以下是EditText的xml代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Test"
android:textSize="30sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
现在,我们可以使用一个WrapDrawable来包装一个ColorDrawable,这个值将被设置为EditText的textCursorDrawable
值,以便我们改变光标的颜色。
下面是WrapDrawable的代码:
class WrapDrawable(color: Int) : Drawable() {
private var drawable = ColorDrawable(color)
@ColorInt
var color: Int = color
set(value) {
field = value
drawable = ColorDrawable(value)
}
override fun setBounds(left: Int, top: Int, right: Int, bottom: Int) {
super.setBounds(left, top, right, bottom)
drawable.setBounds(left, top, right, bottom)
}
override fun getConstantState(): ConstantState? {
return drawable.constantState
}
override fun setAlpha(alpha: Int) {
drawable.alpha = alpha
}
override fun setColorFilter(colorFilter: ColorFilter?) {
drawable.colorFilter = colorFilter
}
override fun getOpacity(): Int {
return drawable.alpha
}
override fun draw(canvas: Canvas) {
drawable.draw(canvas)
}
override fun getIntrinsicWidth(): Int {
return drawable.bounds.width()
}
override fun getIntrinsicHeight(): Int {
return drawable.bounds.height()
}
}
在下面的代码中,我们将光标的颜色更改两次--一次更改为Color.RED
,第二次更改为Color.BLUE
,现在我们应该有一个蓝色光标。但是问题是,一旦设置了textCursorDrawable,即使我们尝试取消它,我们也不能改变它。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val text = findViewById<EditText>(R.id.editText)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// set the cursor color to RED
text.textCursorDrawable = WrapDrawable(Color.RED).apply {
setBounds(0, 0, 5, text.lineHeight)
}
// set the cursor color to BLUE !!! NOT WORKING !!!
text.textCursorDrawable = WrapDrawable(Color.BLUE).apply {
setBounds(0, 0, 5, text.lineHeight)
}
}
}
}
因此,我的问题是,如何重新分配textCursorDrawable
值多次?
通过更新已经存在的textCursorDrawable值并使用颜色变量更改ColorDrawable,我找到了一个解决办法。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val text = findViewById<EditText>(R.id.editText)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// set the cursor color to RED
text.textCursorDrawable = WrapDrawable(Color.RED).apply {
setBounds(0, 0, 5, text.lineHeight)
}
// set the cursor color to BLUE
text.textCursorDrawable?.let {
if (it is WrapDrawable) {
it.color = Color.BLUE
it.setBounds(0, 0, 5, text.lineHeight)
}
}
}
}
}
发布于 2022-09-27 12:10:49
setTextCursorDrawable()
的文档声明:
注意,应用于游标可绘制的任何更改在光标隐藏后再绘制之前都是不可见的。
我已经快速查看了TextView和EditText代码,并且还没有确定如何进行所需的更改。我不是说这件事做不到,我只是没看到而已。
相反,尝试对您的WrapDrawable做如下更改:
(text.textCursorDrawable as WrapDrawable).apply {
color = Color.BLUE
setBounds(0, 0, 5, text.lineHeight)
}
这将起作用,并将保存新WrapDrawable的实例化。
更新
不能证明是否定的,但看起来光标可绘制一旦设置就不能被替换。以下是理由。
对于API 31,在TextView代码中只有两个设置游标可绘制的位置。mCursorDrawable
的私有范围将限制外部访问。
在TextView.java中:
private Drawable mCursorDrawable;
public void setTextCursorDrawable(@Nullable Drawable textCursorDrawable) {
mCursorDrawable = textCursorDrawable;
mCursorDrawableRes = 0;
if (mEditor != null) {
mEditor.loadCursorDrawable();
}
}
@Nullable public Drawable getTextCursorDrawable() {
if (mCursorDrawable == null && mCursorDrawableRes != 0) {
mCursorDrawable = mContext.getDrawable(mCursorDrawableRes);
}
return mCursorDrawable;
}
它是文本编辑器类,游标被绘制,它回到TextView中以获得将要使用的可绘制性。
在Editor.java中:
Drawable mDrawableForCursor = null;
private void drawCursor(Canvas canvas, int cursorOffsetVertical) {
final boolean translate = cursorOffsetVertical != 0;
if (translate) canvas.translate(0, cursorOffsetVertical);
if (mDrawableForCursor != null) {
mDrawableForCursor.draw(canvas);
}
if (translate) canvas.translate(0, -cursorOffsetVertical);
}
void loadCursorDrawable() {
if (mDrawableForCursor == null) {
mDrawableForCursor = mTextView.getTextCursorDrawable();
}
}
loadCursorDrawable
是唯一设置mDrawableForCursor
的地方,一旦定义了它,就不能更改它。由于不能更改它,所以不能将其设置为null以获取可在文本视图中定义的可绘制的新游标。
因此,长和短的原因是光标可以在TextView
中更改,但不能传播到编辑器。
https://stackoverflow.com/questions/73860668
复制相似问题