首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Android中多次设置光标的颜色(插入符号)

如何在Android中多次设置光标的颜色(插入符号)
EN

Stack Overflow用户
提问于 2022-09-26 22:44:53
回答 1查看 40关注 0票数 0

假设我们有一个简单的EditText,我希望将光标(插入符号)更改为其他颜色,在我们使用反射来访问私有字段之前,但是随着Android (29)的引入,我们现在可以使用textCursorDrawable来设置闪烁光标的可绘制性。

以下是EditText的xml代码

代码语言:javascript
运行
复制
<?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的代码:

代码语言:javascript
运行
复制
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,即使我们尝试取消它,我们也不能改变它。

代码语言:javascript
运行
复制
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,我找到了一个解决办法。

代码语言:javascript
运行
复制
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)
                }
            }
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2022-09-27 12:10:49

setTextCursorDrawable()的文档声明:

注意,应用于游标可绘制的任何更改在光标隐藏后再绘制之前都是不可见的。

我已经快速查看了TextView和EditText代码,并且还没有确定如何进行所需的更改。我不是说这件事做不到,我只是没看到而已。

相反,尝试对您的WrapDrawable做如下更改:

代码语言:javascript
运行
复制
(text.textCursorDrawable as WrapDrawable).apply {
    color = Color.BLUE
    setBounds(0, 0, 5, text.lineHeight)
}

这将起作用,并将保存新WrapDrawable的实例化。

更新

不能证明是否定的,但看起来光标可绘制一旦设置就不能被替换。以下是理由。

对于API 31,在TextView代码中只有两个设置游标可绘制的位置。mCursorDrawable的私有范围将限制外部访问。

在TextView.java中:

代码语言:javascript
运行
复制
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中:

代码语言:javascript
运行
复制
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中更改,但不能传播到编辑器。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73860668

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档