1

How can one detect click events on compound drawables of a TextInputEditText?

Robin Davies
  • 7,547
  • 1
  • 35
  • 50
  • note to reviewers: Please don't marks as duplicate. There's a close duplicate for EditText, but the top answer is incorrect and unusable. And if any of the many answers are correct, I can't find one. Question retargeted specifically at TextInputEditText because compound drawables are import for correct implementaton of Material Design. And hopefully, people who need this will find it. – Robin Davies Mar 10 '19 at 19:47

1 Answers1

2

Use the following overriden version of TextInputEditText, and call setOnDrawableClickedListener.

You may fare better if you set your drawable at the end of the edit text than at the start, because the current version of TextInputLayout produces fairly ugly results when the drawable is at the start.

Sample layout is given further down. (Note the use of android:drawablePadding="10dp" particularly).

Code is for androidx, but you can backport to AppCompat trivially.

package com.twoplay.netplayer.controls;

import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.google.android.material.textfield.TextInputEditText;

public class TextInputEditTextEx extends TextInputEditText {
    private OnDrawableClickedListener onDrawableClickedListener;

    public TextInputEditTextEx(Context context) {
        super(context);
        init();
    }


    public TextInputEditTextEx(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public TextInputEditTextEx(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setOnTouchListener(new OnTouchListener() {
            private Rect hitBounds = new Rect();
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                float x = event.getX();
                float y = event.getY();

                int hitDrawable = -1;

                if (x < getCompoundPaddingLeft())
                {
                    hitDrawable = 0;
                    hitBounds.set(0,0,getCompoundPaddingLeft(),getHeight());
                }
                if (x > getWidth()-getCompoundPaddingRight())
                {
                    hitDrawable = 2;
                    hitBounds.set(getCompoundPaddingRight(),0,getWidth(),getHeight());
                }
                if (hitDrawable != -1)
                {
                    int action = event.getAction();
                    if (action == MotionEvent.ACTION_UP)
                    {
                        onDrawableClicked(hitDrawable,hitBounds);
                    }
                    return true;
                }
                return false;
            }
        });
    }

    private void onDrawableClicked(int i, Rect bounds) {
        if (onDrawableClickedListener != null)
        {
            onDrawableClickedListener.onDrawableClicked(this,i,bounds);
        }
    }

    public interface OnDrawableClickedListener {
        void onDrawableClicked(View v, int drawable, Rect bounds);
    }

    public void setOnDrawableClickedListener(OnDrawableClickedListener listener)
    {
        this.onDrawableClickedListener = listener;
    }

}

Sample layout:

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/playlist_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/playlist_name" >

    <com.twoplay.netplayer.controls.TextInputEditTextEx
        android:id="@+id/playlist_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textCapWords"
        android:drawableEnd="@drawable/ic_more_horiz_black_24dp"
        android:drawablePadding="10dp" />
</com.google.android.material.textfield.TextInputLayout>
Zoe
  • 27,060
  • 21
  • 118
  • 148
Robin Davies
  • 7,547
  • 1
  • 35
  • 50