4

I recently found a bug with Material Design TexInputLayout and the way it makes the endIcon visible.

Consider you have setup everything right and have end icon enabled like:

inputLayout.endIconMode == END_ICON_CLEAR_TEXT

The problem is that if you define a focusListener like:

inputLayout.editText?.setOnFocusChangeListener { view, hasFocus -> ...}

and navigate to a screen which has this textInputLayout in it with some already filled text in like following pic

1

You'll notice that the endIcon is not showing, but if you tap on where it's supposed to be, it will work.

Even making sure it should be displayed by making it visible inputLayout.isEndIconVisible = doesn't help. Through the debugging you can see you are hitting the public void setEndIconVisible(boolean visible) with true value but still it doesn't make the icon visible.

I found a solution which I have posted as the answer.

Amir
  • 1,290
  • 1
  • 13
  • 20

6 Answers6

7

The issue is that ClearTextEndIconDelegate has a default OnFocusChangeListener which when you click on the editText it runs an animation which through it the alpha value of the private/internal endIconView(which holds the endIconDrawable) changes from 0 to 1. When you override and set your own OnFocusChangeListener you actually discard this process and setting the inputLayout.isEndIconVisible = true enables the view but you can't see it still. I didn't find any way to access to the parent view and change the alpha. Actually you can by doing something like

(((inputLayout.getChildAt(0) as FrameLayout).getChildAt(2) as LinearLayout).getChildAt(1) as FrameLayout).getChildAt(0).alpha = 1f

Take a look at image below you'll get how I ended up the above:

enter image description here

But this is not a great solution also if the hierarchy of the view changes it won't work anymore.

Ultimate Solution

What I came with is the invoking the original OnFocusChangeListener within my OnFocusChangeListener something like :

val originalListener = inputLayout.editText?.onFocusChangeListener
        inputLayout.editText?.setOnFocusChangeListener { view, hasFocus ->
            originalListener?.onFocusChange(view, hasFocus)

            // do your thing here
        }

Amir
  • 1,290
  • 1
  • 13
  • 20
0

For this case, it will be better to set custom mode for end icon

    textInputLayout.endIconMode = TextInputLayout.END_ICON_CUSTOM // may be set in xml 
    textInputLayout.setEndIconDrawable(R.drawable.your_icon)
    textInputLayout.setEndIconOnClickListener {
        textInputEditText.text?.clear()
    }

And then add your custom OnFocusChangeListener:

    inputLayout.editText?.setOnFocusChangeListener { view, hasFocus ->
        textInputLayout.isEndIconVisible = hasFocus

     // add your code here
    }
Olena Y
  • 233
  • 2
  • 8
0

For me, none of the solution worked and the end icon was invisible because the alpha is set to 0. So I decided to manually set drawable end in the TextInputEditText.

// First, set the endIconMode to None and set the click listener to clear the text
testInputLayout.endIconMode = TextInputLayout.END_ICON_NONE
testInputLayout.setEndIconOnClickListener {
    binding.customTextInput.editText?.text?.clear()
}

// Inside the custom focusChangeListener, show/hide the drawable end
textInputLayout.editText?.setOnFocusChangeListener { _, hasFocus ->
    // This is required so that the clear text click action can be handled
    binding.customTextInput.isEndIconVisible = hasFocus

    if (hasFocus) {
        // Display Drawable end
        textInputLayout.editText?.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(context, R.drawable.ic_clear), null)
    } else {
        // Hide Drawable end
        textInputLayout.editText?.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
    }
    // Do what you want
}
Ikuemon
  • 1
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 20 '22 at 12:59
0

TextInputLayout's textwatcher checks if the view has focus and if there is any text in its EditText and sets the visibility of the end icon. Probably, it sets the end icon visibility to Visibility.GONE since it does not have the focus even if there is any text in its underlying EditText. So the TextInputLayout needs to have the focus as well. So the below code worked for me

inputLayout.requestFocus()
inputLayout.edittext.setText(YOUR_TEXT)
inputLayout.edittext.setSelection(YOUR_TEXT_LENGTH)
0

Extending to Amir's answer

Running on a Pixel 5 API 32 device and targetSdkVersion to 31. The children of TextInputEditText are shown as below:

enter image description here

So we might use following code to set this view's alpha by:

id_of_text_input_layout.findViewById<View>(R.id.text_input_end_icon)?.alpha = 1f
Mia
  • 1,226
  • 1
  • 19
  • 29
0

After trying the solutions from this thread and finding they don't work in my case (the "clear text icon" from com.google.android.material.textfield.TextInputLayout wasn't always being displayed, not even with alpha 0), I ended up implementing the "clear text icon" from scratch, ie:

  1. add an ImageView with my "clear text icon" to TextInputLayout's parent ViewGroup
  2. attach an onClickListener to that ImageView and place the text-clearing logic there
  3. attach onTextChanged and onFocusChange listeners to my EditText to trigger ImageView's visibility changes.
  4. make the ImageView visible by animating its alpha from 0 to 1 and setting its visibility to View.VISIBLE at the end. To make it invisible, do the reverse, ie. animate its alpha from 1 to 0 and set its visibility to View.GONE at the end. Weirdly enough, when just toggling the visibility between GONE and VISIBLE, that ImageView wasn't always being displayed.
  5. when the ImageView is shown, add endPadding to TextInputLayout, so that text in the EditText doesn't show under the ImageView
marcinP
  • 106
  • 1
  • 4
  • Would be great if you can make it a component and share it here for future seekers – Amir Feb 04 '23 at 11:43