material-components-android
material-components-android copied to clipboard
[TextInputLayout] End Clear Icon visibility not backward compatible
Description:
I have TextInputLayout+TextInputEditText combo; TextInputLayout styled to @style/Widget.MaterialComponents.TextInputLayout.OutlinedBox and app:endIconMode="clear_text", while TextInputEditText has:
android:background="@null"
android:cursorVisible="false"
android:inputType="textNoSuggestions"
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="false"
The control is setup so that users can't directly entry text, the editText has a click listener that opens a drop-down or date-picker, that populates the editText once user have selected something. The end clear button should be visible to allow for clearing the data. This worked in material-1.3.0, the clear button is showing up even if the field is not focusable, but not longer shows up in material-1.4.0-x. There's a certain weirdness in 1.4.0-x as well, in that if the focusable=false then the clear button doesn't exist, but if focusable=true then it's clickable but alpha=0f, so not really visible to the human eye, even if it participates in the measure pass.
Expected behavior:
Would like the clear button to be visible and useable when the TextInputEditText is customised to work like a dropdown button. Would prefer not to use an actual button for this because the UX is weird, especially if user wants to clear the data, clear button is the obvious UX.
Android API version: 29
Material Library version: Reproducible on material-1.4.0-rc01 and material-1.4.0-beta01, worked as normal in material-1.3.0.
Device: tested and shows up on API 25 onwards
Can confirm that this is still an issue with material-1.4.0.
Is it possible to make focus dependent behavior configurable?
We're facing the same issue.
It seems that it's related to the https://github.com/material-components/material-components-android/issues/2024 and https://github.com/material-components/material-components-android/pull/2025.
A reflect workaround: define two top level functions firstly
with 'com.google.android.material:material:1.10.0:
/**
* top level function to get end icon view
*/
fun getEndIconView(textInputLayout: TextInputLayout): CheckableImageButton? {
return try {
val field = TextInputLayout::class.java.getDeclaredField("endLayout")
field.isAccessible = true
val endLayout = field.get(textInputLayout)
val field2 = endLayout::class.java.getDeclaredField("endIconView")
field2.isAccessible = true
val endIconView = field2.get(endLayout) as CheckableImageButton
endIconView
} catch (e: Exception) {
logE(e)
null
}
}
/**
* top level function to force show end icon view
*/
fun TextInputLayout.forceShowEndIconView() {
this.post {
if (!this.isEndIconVisible) {
this.isEndIconVisible = true
this.getEndIconViewByReflect()?.apply {
// or improve this by using the animation same as the ClearTextEndIconDelegate.java instead
alpha = 1f
scaleX = 1f
scaleY = 1f
}
}
}
}
with 'com.google.android.material:material:1.6.0-rc01':
/**
* top level function to get end icon view
*/
fun TextInputLayout.getEndIconViewByReflect(): CheckableImageButton? {
return try {
val field = TextInputLayout::class.java.getDeclaredField("endIconView")
field.isAccessible = true
val endIconView = field.get(this) as CheckableImageButton
endIconView
} catch (e: Exception) {
e.printStackTrace()
null
}
}
/**
* top level function to force show end icon view
*/
fun TextInputLayout.forceShowEndIconView() {
this.post {
if (!this.isEndIconVisible) {
this.isEndIconVisible = true
this.getEndIconViewByReflect()?.apply {
// or improve this by using the animation same as the ClearTextEndIconDelegate.java instead
alpha = 1f
scaleX = 1f
scaleY = 1f
}
}
}
}
And then using it in code:
fun setTextByCodeFunction() {
...
textInputLayout.text = "xxx"
// after set text, force show end icon
textInputLayout.forceShowEndIconView()
...
}
Can we also get an option to make the endIcon visible regardless of the focus?