Android:TextInputLayout ColorStateList.isStateful()在从setErro



当尝试实现errorState时,自定义TextInputLayout会导致以下异常。

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.res.ColorStateList.isStateful()' on a null object reference
at com.google.android.material.textfield.TextInputLayout.setBoxStrokeColorStateList(TextInputLayout.java:1103)
at tech.********.platform.components.MyCustomTextInput.setErrorEnabled(MyCustomTextInput.kt:81)
at com.google.android.material.textfield.TextInputLayout.<init>(TextInputLayout.java:786)
at com.google.android.material.textfield.TextInputLayout.<init>(TextInputLayout.java:422)
at tech.********.platform.components.MyCustomTextInput.<init>(MyCustomTextInput.kt:38)

切换应用程序的XML代码:errorEnabled with binding

<MyCustomTextInput>
android:id="@+id/inputPassword"
...
app:errorEnabled="@{condition ? true: false}"
<MyCustomTextInput/>

尝试实现错误斯托克颜色没有错误文本如下:

override fun setErrorEnabled(enabled: Boolean) {
if (enabled) setBoxStrokeColorStateList(errorColor)
else setBoxStrokeColorStateList(defaultColor)
super.setErrorEnabled(false)
}

完整的布局代码如下:

class MyCustomTextInput : TextInputLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
/**
* Color states for the default scenario.
*/
private var defaultColor = ColorStateList(
arrayOf(
intArrayOf(-R.attr.state_focused, R.attr.state_enabled),
intArrayOf(R.attr.state_focused, R.attr.state_enabled),
), intArrayOf(Color.parseColor("#CCCCCC"), Color.parseColor("#164A9C"))
)
/**
* Color states for the error scenario.
*/
private var errorColor = ColorStateList(
arrayOf(
intArrayOf(-R.attr.state_focused, R.attr.state_enabled),
intArrayOf(R.attr.state_focused, R.attr.state_enabled)
), intArrayOf(Color.RED, Color.RED)
)
init {
setBoxStrokeColorStateList(defaultColor) // edit text stroke
hintTextColor = defaultColor // edit text content
}
override fun setErrorIconDrawable(errorIconDrawable: Drawable?) {
super.setErrorIconDrawable(null)
}
override fun setErrorIconTintList(errorIconTintList: ColorStateList?) {
super.setErrorIconTintList(errorColor)
}
override fun setErrorEnabled(enabled: Boolean) {
if (enabled) setBoxStrokeColorStateList(errorColor)
else setBoxStrokeColorStateList(defaultColor)
super.setErrorEnabled(false)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
}
}

使用与init((中使用的相同的colorState。

重写setErrorEnabled方法时的问题:TextInputLayout从构造函数调用它们,但MyCustomTextInput(子类(中的变量未初始化,因为运行时首先执行父构造函数,然后执行子初始化器和构造函数。

请参阅下面的简单示例。Parent.java:

public class Parent {
public Parent() {
System.out.println("Parent constructor execution.");
System.out.println("Parent call to printErrorMessageLength.");
printErrorMessageLength("Parent error.");
}
public void printErrorMessageLength(String message) {
System.out.println("Parent printErrorMessageLength execution.");
System.out.println(message.length());
}
}

Test.kt:

fun main() {
Child()
}
class Child : Parent {
var childErrorMessage = "Child Error"
init {
println("Child.init, childErrorMessage = $childErrorMessage")
}
constructor() : super() {} // just for sample
override fun printErrorMessageLength(inputMessage: String?) {
println("Child printErrorMessageLength execution with inputMessage = $inputMessage")
println("${childErrorMessage.length}")
super.printErrorMessageLength(inputMessage)
}
}

主要执行结果:

Parent constructor execution.
Parent call to printErrorMessageLength.
Child printErrorMessageLength execution with inputMessage = Parent error.
Exception in thread "main" java.lang.NullPointerException
at Child.printErrorMessageLength(Test.kt:16)
at Parent.<init>(Parent.java:6)
at Child.<init>(Test.kt:12)
at TestKt.main(Test.kt:2)
at TestKt.main(Test.kt)
Process finished with exit code 1

我该怎么解决这个问题?-如果变量为空,则初始化该变量:

/**
* Color states for the default scenario.
*/
private var defaultColor = createDefaultColor()
private fun createDefaultColor(): ColorStateList = ColorStateList(
arrayOf(
intArrayOf(-R.attr.state_focused, R.attr.state_enabled),
intArrayOf(R.attr.state_focused, R.attr.state_enabled),
), intArrayOf(Color.parseColor("#CCCCCC"), Color.parseColor("#164A9C"))
)
/**
* Color states for the error scenario.
*/
private var errorColor = createErrorColor()
private fun createErrorColor(): ColorStateList = ColorStateList(
arrayOf(
intArrayOf(-R.attr.state_focused, R.attr.state_enabled),
intArrayOf(R.attr.state_focused, R.attr.state_enabled)
), intArrayOf(Color.RED, Color.RED)
)
override fun setErrorEnabled(enabled: Boolean) {
if (enabled) setBoxStrokeColorStateList(errorColor?:createErrorColor())
else setBoxStrokeColorStateList(defaultColor?:createDefaultColor())
super.setErrorEnabled(false)
}

或者你可以使用类似getDefaultColor()的方法,而不是使用变量defaultColor:

private fun getDefaultColor(): ColorStateList {
if(defaultColor == null) {
defaultColor = createDefaultColor()
}
return defaultColor
}

相关内容

  • 没有找到相关文章

最新更新