设置inputType后EditText自定义onDraw绘制失效,如何保留数字键盘解决?
问题原因
当你给EditText设置android:inputType="number"属性时,会触发两个影响绘制的逻辑:
- AppCompat系列控件会自动加载主题中默认的
editTextBackground作为控件背景,这个默认背景是不透明的状态Drawable,会直接覆盖你在onDraw中绘制的内容;当你不设置inputType时,EditText默认处于非纯输入状态,背景为透明,所以可以看到自定义绘制的内容。 - 你在
onDraw方法中调用setBackgroundColor()的操作不符合绘制规范:该方法会触发控件重绘,反复调用会导致绘制时序混乱,在输入类控件开启硬件加速优化的场景下,自定义绘制的内容会被系统的输入渲染逻辑打断,导致无法正常显示。
解决方法
1. 先修正绘制逻辑
不要在onDraw中做初始化和设置背景的操作,把背景设置、Paint初始化移到构造方法中,避免重复创建对象和绘制时序混乱:
class Test : AppCompatEditText { // Paint对象全局初始化,避免onDraw反复创建 private val customPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.BLUE style = Paint.Style.FILL } constructor(context: Context) : super(context) { init(context) } constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { init(context) } constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { init(context) } private fun init(context: Context) { // 背景设置移到构造方法中 setBackgroundColor(Color.GREEN) // 可选:如果关闭硬件加速优化,可解决部分机型层级覆盖问题 // setLayerType(LAYER_TYPE_SOFTWARE, null) } override fun onDraw(canvas: Canvas) { // 先绘制自定义图形,即可显示在文字下方 canvas.drawRect(0f, 0f, 150f, 50f, customPaint) super.onDraw(canvas) } }
2. 保留数字键盘的方案
不需要用digits属性替换inputType,两种方案均可同时保留数字键盘和自定义绘制效果:
- 方案一:在XML中添加
android:background="@null"属性,去掉系统默认的不透明输入框背景,避免覆盖自定义绘制内容:
<com.slaviboy.galaxy.Test android:id="@+id/ssss" android:layout_width="150dp" android:layout_height="50dp" android:gravity="center" android:text="TEST" android:imeOptions="actionDone" android:inputType="number" android:background="@null" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
- 方案二:如果需要保留系统默认的输入框样式,直接在构造方法中添加
setLayerType(LAYER_TYPE_SOFTWARE, null)关闭硬件加速的离屏渲染优化即可,不会影响数字键盘的弹出样式。
内容的提问来源于stack exchange,提问作者slaviboy
相关产品推荐
相关产品推荐

