I've extended EditText and want to add some functionality depending on the given InputType
. Fx. if the InputType is a password
type then I want to check for that and change the right
compound drawable.
Problem is that if I do that inside the init{}
fun, then I get the default InputType 131073
, which is not the right one.
Question is: Where in the EditText "lifecycle" can I get the right InputType indication?
open class EditText @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
AppCompatEditText(context, attrs, defStyleAttr), View.OnTouchListener, View.OnFocusChangeListener, TextWatcherAdapter.TextWatcherListener {
private var icon: Drawable? = null
private var listener: Listener? = null
private var touchListener: OnTouchListener? = null
private var focusChangeListener: OnFocusChangeListener? = null
init {
icon = compoundDrawables[2]
if (icon == null) {
//////// NOT getting the right InputType !!!
if (isPasswordInputType()) {
icon = resources.getDrawable(R.drawable.ic_password_hide, null)
} else {
icon = resources.getDrawable(R.drawable.ic_delete_ring, null)
}
}
icon?.setBounds(0, 0, icon!!.intrinsicWidth, icon!!.intrinsicHeight)
setClearIconVisible(false)
super.setOnTouchListener(this)
super.setOnFocusChangeListener(this)
addTextChangedListener(TextWatcherAdapter(this, this))
}
override fun onTouch(v: View, event: MotionEvent): Boolean {
if (compoundDrawables[2] != null) {
val left = width - icon!!.intrinsicWidth - paddingRight * 2
val right = width
val top = 0
val bottom = height
// If tapped on icon
if (Rect(left, top, right, bottom).contains(event.x.toInt(), event.y.toInt())) {
if (event.action == MotionEvent.ACTION_UP) {
//////// IS showing the right InputType !!!
if (isPasswordInputType()) {
if (transformationMethod == HideReturnsTransformationMethod.getInstance()) {
transformationMethod = PasswordTransformationMethod.getInstance()
icon = resources.getDrawable(R.drawable.ic_password_show, null)
} else if (transformationMethod == PasswordTransformationMethod.getInstance()) {
transformationMethod = HideReturnsTransformationMethod.getInstance()
icon = resources.getDrawable(R.drawable.ic_password_hide, null)
}
icon?.setBounds(0, 0, icon!!.intrinsicWidth, icon!!.intrinsicHeight)
setPasswordIconVisible(true)
} else {
setText("")
}
if (listener != null) {
listener!!.didClearText()
}
}
return true
}
}
return if (touchListener != null) {
touchListener!!.onTouch(v, event)
} else false
}
override fun onFocusChange(v: View, hasFocus: Boolean) {
if (isPasswordInputType()) {
setClearIconVisible(true)
} else {
if (hasFocus) {
setClearIconVisible(isNotEmpty(text!!))
} else {
setClearIconVisible(false)
}
if (focusChangeListener != null) {
focusChangeListener!!.onFocusChange(v, hasFocus)
}
}
}
override fun onTextChanged(view: EditText, text: String) {
if (isFocused) {
setClearIconVisible(isNotEmpty(text))
}
}
interface Listener {
fun didClearText()
}
fun setListener(listener: Listener) {
this.listener = listener
}
override fun setOnTouchListener(l: View.OnTouchListener) {
this.touchListener = l
}
override fun setOnFocusChangeListener(f: View.OnFocusChangeListener) {
this.focusChangeListener = f
}
fun setDefaultFocusChangeListener() {
this.onFocusChangeListener = OnFocusChangeListener { v, hasFocus ->
if (hasFocus) {
elevation = resources.getDimensionPixelSize(R.dimen.edit_box_elevation_focused).toFloat()
} else {
elevation = resources.getDimensionPixelSize(R.dimen.edit_box_elevation).toFloat()
}
}
}
private fun isNotEmpty(text: Editable): Boolean {
return isNotEmpty(text.toString())
}
private fun isNotEmpty(text: String?): Boolean {
return text != null && text.isNotEmpty()
}
private fun setClearIconVisible(visible: Boolean) {
val wasVisible = compoundDrawables[2] != null
if (visible != wasVisible) {
val d = if (visible) icon else null
setCompoundDrawables(compoundDrawables[0], compoundDrawables[1], d, compoundDrawables[3])
}
}
private fun setPasswordIconVisible(visible: Boolean) {
val d = if (visible) icon else null
setCompoundDrawables(compoundDrawables[0], compoundDrawables[1], d, compoundDrawables[3])
}
private fun isPasswordInputType(): Boolean {
return (inputType == InputType.TYPE_NUMBER_VARIATION_PASSWORD ||
inputType == InputType.TYPE_TEXT_VARIATION_PASSWORD ||
inputType == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD ||
inputType == InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD ||
inputType == InputType.TYPE_CLASS_TEXT + InputType.TYPE_NUMBER_VARIATION_PASSWORD ||
inputType == InputType.TYPE_CLASS_TEXT + InputType.TYPE_TEXT_VARIATION_PASSWORD ||
inputType == InputType.TYPE_CLASS_TEXT + InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD ||
inputType == InputType.TYPE_CLASS_TEXT + InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD)
}
}
OK, found the answer, so instead of deleting the question, I'll post the answer here:
I moved the code that differentiates on InputType to the onAttachedToWindow
event. In this lifecycle event the actual InputType is already present to work with:
...
override fun onAttachedToWindow() {
super.onAttachedToWindow()
icon = compoundDrawables[2]
if (icon == null) {
icon = if (isPasswordInputType()) {
resources.getDrawable(R.drawable.ic_password_show, null)
} else {
resources.getDrawable(R.drawable.ic_delete_ring, null)
}
}
icon?.setBounds(0, 0, icon!!.intrinsicWidth, icon!!.intrinsicHeight)
setClearIconVisible(false)
}
...