Установка onClickListener для Drawable справа от EditText [duplicate]

На этот вопрос уже есть ответ здесь:

Обработка событий щелчка на отрисовке внутри EditText 32 ответа

В моем приложении у меня естьEditText с иконкой поиска на правой стороне. Я использовал код, приведенный ниже.

 

Я хочу установитьonClickListener для изображения значка поиска, назначенного на правыйEditText, Как это возможно?

 Tobrun30 окт. 2012 г., 09:54
 JPM27 сент. 2016 г., 20:38
Это лучший ответstackoverflow.com/a/37032927/346309
 AZ_16 дек. 2014 г., 04:37
Самое простое решение с использованием Android APIstackoverflow.com/a/26269435/185022 :-)

Ответы на вопрос(6)

Простое решение, используйте методы, которые уже дал Android, а не изобретайте wheeeeeeeeeel :-)

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            final int DRAWABLE_LEFT = 0;
            final int DRAWABLE_TOP = 1;
            final int DRAWABLE_RIGHT = 2;
            final int DRAWABLE_BOTTOM = 3;

            if(event.getAction() == MotionEvent.ACTION_UP) {
                if(event.getRawX() >= (editComment.getRight() - editComment.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
                    // your action here

                 return true;
                }
            }
            return false;
        }
    });
 RoCk Vangeance30 мая 2016 г., 05:51
Это решение работает, но я не могу ввести пароль на поле.
 Sotti17 дек. 2017 г., 13:34
Это смешение абсолютных позицийgetRawX» с относительными позициямибыть правым", Если вы установили правое или левое поле для текста редактирования, вы 'Посмотрим, как это сломается, когда щелчок срабатывает по неправильным координатам. Как хорошо, что это не для повторного использования.
 Botond Kopacz15 авг. 2017 г., 20:17
Какое простое решение, удивительно!
 Rizwan Sohaib16 авг. 2016 г., 16:40
Это отлично сработало для меня .. нене пробовал ориентацию вещь ..
 cnbandicoot16 янв. 2017 г., 12:15
ACTION_UP не работает для меня я использовалACTION_DOWN вместо
 Reprator05 окт. 2016 г., 08:11
@ Можете ли вы отредактировать свой ответ для нескольких языков, так как это нет работа.
 SHUJAT MUNAWAR01 апр. 2018 г., 18:21
Как я могу использовать его в режиме горизонтальной прокрутки?
 Shoaib Chikate26 июл. 2015 г., 19:46
Для меня это работает для (event.getRawX () + editComment.getPaddingLeft ()) <= (editComment.getCompoundDrawables () [DRAWABLE_LEFT] .getBounds (). width () + editComment.getLeft ()) где для редактирования текста я применил drawable paddng
 Salman Khan11 сент. 2015 г., 14:45
@AZ_ У меня есть другой текст редактирования ниже, и всякий раз, когда моя деятельность начинается, второй текст редактирования получает фокус, а не первый, который имеет DRAWABLE_RIGHT. Что я должен сделать, чтобы сфокусироваться на первом?
 IldiX23 апр. 2019 г., 09:31
Если я использую ACTION_UP, это приводит к открытию диалогового окна буфера обмена (CUT / PASTE) при щелчке мышью. Я изменил его на ACTION_DOWN, и теперь он выглядит хорошо. Хорошее решение, кстати.
 AZ_17 нояб. 2014 г., 02:32
@ user2273146 если ваша длина равна 4, то ваш индекс должен быть 3. потому что длина начинается с 1, длины 0 нет, но если длина равна 1, то индекс равен 0
 user227314616 нояб. 2014 г., 07:47
Ошибка: java.lang.ArrayIndexOutOfBoundsException: length = 4; Индекс = 2130837593
 kwh18 янв. 2015 г., 17:38
Работал на меня. Вот код для нажатия левой иконки ... if (event.getRawX () <= (editComment.getCompoundDrawables () [DRAWABLE_LEFT] .getBounds (). width ()))
 Monish Kamble05 авг. 2017 г., 08:28
Отлично .. Вы потрясающий .. Это должен быть принятый ответ ..
 nanangarsyad26 дек. 2017 г., 10:05
На последней версии Android Studio (A.S 3.0 вверх), если вы звонитеsetOnTouchListener изView класс без подкласса весь класс выполучу такое предупреждение (stackoverflow.com/q/47107105/3947487). Единственное решение, которое могло бы исправить это предупреждение прямо сейчас, - это создать подклассы всего класса и вызватьview.performClick() внутриonTouch() метод
 dd61904 мар. 2015 г., 11:58
getRawX () не работает для меня, поэтому я использовал getX (), и это сработало!
 AZ_15 сент. 2015 г., 06:48
@SalmanKhandeveloper.android.com/reference/android/view/... или использовать обработчик с некоторой задержкой для запроса фокуса, если это нет работает.
 Rohitashv jain23 июн. 2016 г., 14:25
Soultion работал, но когда вы изменили ориентацию, его не удалось
 CoolMind17 апр. 2017 г., 16:12
Это решение работает также для TextView. Пожалуйста изменитеeditComment.getRight() - editComment.getCompoundDrawables() вv.getRight() - ((EditText) v).getCompoundDrawables(), Если кто-то обрабатываетonClick на текст, изменитьMotionEvent.ACTION_UP кMotionEvent.ACTION_DOWN
 AZ_05 мар. 2015 г., 09:59
@ dd619 Подскажите пожалуйста версию ОС Android, модель мобильного телефона, используете ли вы стоковые ПЗУ с рутированным рутом !! getRawX () должен работать. Читайте это такжеstackoverflow.com/questions/20636163/...

что это довольно старо, но недавно мне пришлось сделать что-то очень похожее, и я нашел гораздо более простое решение.

Это сводится к следующим шагам:

Создайте макет XML, содержащий EditText и ImageПодкласс FrameLayout и раздувать макет XMLДобавьте код для прослушивателя щелчков и любое другое поведение, которое вы хотите ... не беспокоясь о позициях щелчка или любом другом беспорядочном коде.

Смотрите этот пост для полного примера:Обработка событий щелчка на отрисовке внутри EditText

Создайте изображение кнопки с вашим значком и установите его цвет фона прозрачным.Поместите кнопку изображения на EditTextРеализоватьonclic»k слушатель кнопки, чтобы выполнить вашу функцию
 Nizzy30 апр. 2013 г., 23:34
Вам нужно понять вопрос! Он / она нене спрашиваю альтернативного решения.
 Sotti17 дек. 2017 г., 13:34
Проблема этого подхода заключается в том, что он разваливается, как только вы начинаете изменять размер текста в EditText. Вы можете подумать, чтопросто на разработчикасторона, но этоЭто не так, как устройства имеют размер текста в настройках. Вы можете избежать этого, используя dp вместо sp в EditText, но это только ухудшает ситуацию. Другие проблемы, такие как обработка многострочных EditTexts
 Hardik456030 окт. 2012 г., 10:07
Что делать, если размер editText увеличивается? Что делать, если у меня есть много editText, который требует этого, что обычно происходит.

у меня нет доступа к нужному изображению, если только вы неonTouch событие. Я предлагаю использоватьRelativeLayout, с однимeditText и одинimageViewи установитьOnClickListener поверх изображения, как показано ниже:

<relativelayout android:id="@+id/rlSearch" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:drawable/edit_text" android:padding="5dip">

        <edittext android:id="@+id/txtSearch" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centervertical="true" android:layout_toleftof="@+id/imgSearch" android:background="#00000000" android:ems="10">

        <imageview android:id="@+id/imgSearch" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentright="true" android:layout_centervertical="true" android:src="@drawable/btnsearch">
    </imageview></edittext></relativelayout>
 Sotti17 дек. 2017 г., 13:33
Проблема этого подхода заключается в том, что он разваливается, как только вы начинаете изменять размер текста в EditText. Вы можете подумать, чтопросто на разработчикасторона, но этоЭто не так, как устройства имеют размер текста в настройках. Вы можете избежать этого, используя dp вместо sp в EditText, но это только ухудшает ситуацию. Другие проблемы, такие как обработка многострочных EditTexts

но я попробовал другой способ сделать его проще.

Идея заключается в использовании положитьImageButton справа отEditText и с отрицательным запасом к нему, так чтоEditText течет вImageButton сделать его похожим на кнопку в.EditText

    <linearlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">
        <edittext android:id="@+id/editText" android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:hint="Enter Pin" android:singleline="true" android:textsize="25sp" android:paddingright="60dp">
        <imagebutton android:id="@+id/pastePin" android:layout_marginleft="-60dp" style="?android:buttonBarButtonStyle" android:paddingbottom="5dp" android:src="@drawable/ic_action_paste" android:layout_width="wrap_content" android:layout_height="wrap_content">
    </imagebutton></edittext></linearlayout>

Также, как показано выше, вы можете использоватьpaddingRight аналогичной ширины вEditText если ты нене хочу, чтобы текст в нем был пролетел над.ImageButton

Я угадал размер маржи с помощью android-studio 'с дизайнером макетов, и он выглядит одинаково для всех размеров экрана. Или же вы можете рассчитать ширинуImageButton и установите маржу программно.

 Sotti17 дек. 2017 г., 13:34
Проблема этого подхода заключается в том, что он разваливается, как только вы начинаете изменять размер текста в EditText. Вы можете подумать, чтопросто на разработчикасторона, но этоЭто не так, как устройства имеют размер текста в настройках. Вы можете избежать этого, используя dp вместо sp в EditText, но это только ухудшает ситуацию. Другие проблемы, такие как обработка многострочных EditTexts
 DariusL17 мар. 2016 г., 10:08
Это'Простые вещи, которые работают лучше всего.
 Anand Savjani03 мая 2016 г., 07:41
это избыточная работа для одного рисования
 Xan27 февр. 2019 г., 22:19
почему бы не использовать простой FrameLayout?
 最白目18 июл. 2017 г., 14:31
Линтер предупредит васнеэффективное дерево компоновки, используйте составное рисованиетакже больше кода, чем drawableRight = ""...
 SMR20 июн. 2017 г., 09:16
Проблемы с полями и отступами будут для разных устройств.
Решение Вопроса
public class CustomEditText extends EditText {

    private Drawable drawableRight;
    private Drawable drawableLeft;
    private Drawable drawableTop;
    private Drawable drawableBottom;

    int actionX, actionY;

    private DrawableClickListener clickListener;

    public CustomEditText (Context context, AttributeSet attrs) {
        super(context, attrs);
        // this Contructure required when you are using this view in xml
    }

    public CustomEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);        
    }

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }

    @Override
    public void setCompoundDrawables(Drawable left, Drawable top,
            Drawable right, Drawable bottom) {
        if (left != null) {
            drawableLeft = left;
        }
        if (right != null) {
            drawableRight = right;
        }
        if (top != null) {
            drawableTop = top;
        }
        if (bottom != null) {
            drawableBottom = bottom;
        }
        super.setCompoundDrawables(left, top, right, bottom);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Rect bounds;
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            actionX = (int) event.getX();
            actionY = (int) event.getY();
            if (drawableBottom != null
                    && drawableBottom.getBounds().contains(actionX, actionY)) {
                clickListener.onClick(DrawablePosition.BOTTOM);
                return super.onTouchEvent(event);
            }

            if (drawableTop != null
                    && drawableTop.getBounds().contains(actionX, actionY)) {
                clickListener.onClick(DrawablePosition.TOP);
                return super.onTouchEvent(event);
            }

            // this works for left since container shares 0,0 origin with bounds
            if (drawableLeft != null) {
                bounds = null;
                bounds = drawableLeft.getBounds();

                int x, y;
                int extraTapArea = (int) (13 * getResources().getDisplayMetrics().density  + 0.5);

                x = actionX;
                y = actionY;

                if (!bounds.contains(actionX, actionY)) {
                    /** Gives the +20 area for tapping. */
                    x = (int) (actionX - extraTapArea);
                    y = (int) (actionY - extraTapArea);

                    if (x <= 0)
                        x = actionX;
                    if (y <= 0)
                        y = actionY;

                    /** Creates square from the smallest value */
                    if (x < y) {
                        y = x;
                    }
                }

                if (bounds.contains(x, y) && clickListener != null) {
                    clickListener
                            .onClick(DrawableClickListener.DrawablePosition.LEFT);
                    event.setAction(MotionEvent.ACTION_CANCEL);
                    return false;

                }
            }

            if (drawableRight != null) {

                bounds = null;
                bounds = drawableRight.getBounds();

                int x, y;
                int extraTapArea = 13;

                /**
                 * IF USER CLICKS JUST OUT SIDE THE RECTANGLE OF THE DRAWABLE
                 * THAN ADD X AND SUBTRACT THE Y WITH SOME VALUE SO THAT AFTER
                 * CALCULATING X AND Y CO-ORDINATE LIES INTO THE DRAWBABLE
                 * BOUND. - this process help to increase the tappable area of
                 * the rectangle.
                 */
                x = (int) (actionX + extraTapArea);
                y = (int) (actionY - extraTapArea);

                /**Since this is right drawable subtract the value of x from the width 
                * of view. so that width - tappedarea will result in x co-ordinate in drawable bound. 
                */
                x = getWidth() - x;

                 /*x can be negative if user taps at x co-ordinate just near the width.
                 * e.g views width = 300 and user taps 290. Then as per previous calculation
                 * 290 + 13 = 303. So subtract X from getWidth() will result in negative value.
                 * So to avoid this add the value previous added when x goes negative.
                 */

                if(x <= 0){
                    x += extraTapArea;
                }

                 /* If result after calculating for extra tappable area is negative.
                 * assign the original value so that after subtracting
                 * extratapping area value doesn't go into negative value.
                 */               

                if (y <= 0)
                    y = actionY;                

                /**If drawble bounds contains the x and y points then move ahead.*/
                if (bounds.contains(x, y) && clickListener != null) {
                    clickListener
                            .onClick(DrawableClickListener.DrawablePosition.RIGHT);
                    event.setAction(MotionEvent.ACTION_CANCEL);
                    return false;
                }
                return super.onTouchEvent(event);
            }           

        }
        return super.onTouchEvent(event);
    }

    @Override
    protected void finalize() throws Throwable {
        drawableRight = null;
        drawableBottom = null;
        drawableLeft = null;
        drawableTop = null;
        super.finalize();
    }

    public void setDrawableClickListener(DrawableClickListener listener) {
        this.clickListener = listener;
    }

}

Также создайте интерфейс с

public interface DrawableClickListener {

    public static enum DrawablePosition { TOP, BOTTOM, LEFT, RIGHT };
    public void onClick(DrawablePosition target); 
    }

Тем не менее, если вам нужна помощь, прокомментируйте

Также установите drawableClickListener для представления в файле деятельности.

editText.setDrawableClickListener(new DrawableClickListener() {


        public void onClick(DrawablePosition target) {
            switch (target) {
            case LEFT:
                //Do something here
                break;

            default:
                break;
            }
        }

    });
 arefin21 мая 2013 г., 22:53
Привет, я не нахожу CoreSystemContext.SCALE, поэтому код показывает ошибку. как я могу получить CoreSystemContext.SCALE. Пожалуйста, порекомендуйте.
 Libin Thomas19 февр. 2018 г., 08:10
@ V-J можешь прокомментировать пример рабочего кода: D
 Hardik456030 окт. 2012 г., 12:07
Пожалуйста, смотрите отредактированный ответ.
 Qadir Hussain06 янв. 2014 г., 14:15
Хорошо сработало для меня
 st0le30 окт. 2012 г., 10:02
Я бы также передал Edittext в качестве параметра для обратного вызова. Но хороший ответ, тем не менее.
 user96507130 окт. 2012 г., 11:47
Я создал собственный EditText. Если я коснусь где-нибудь в его идти к методу onTouchMovement. но никогда не идет сюда "if (bounds.contains (x, y) && clickListener! = null) {clickListener .onClick (DrawableClickListener.DrawablePosition.RIGHT); event.setAction (MotionEvent.ACTION_CANCEL); вернуть ложь; }»
 Kokusho20 янв. 2015 г., 18:29
Если вы не можете найти CoreSystemContext.SCALE, просто измените эту строку int extraTapArea = (int) (13 * getResources (). GetDisplayMetrics (). Density + 0.5);
 Hardik456022 мая 2013 г., 05:54
Это переменная плотность удерживающего устройства. вместо этого используйте getResources (). getDisplayMetrics (). density, вам может потребоваться создать статическое переменное в другом файле. Это для преобразования пикселей в дп. Простым решением было бы удалить эту переменную.
 V_J04 окт. 2016 г., 14:29
Слишком много кода. Простой setOnTouchListener будет работать с этим.
 Sankar V21 авг. 2013 г., 17:11
Пожалуйста, добавьте заявлениеplaySoundEffect(android.view.SoundEffectConstants.CLICK); послеif (event.getAction() == MotionEvent.ACTION_DOWN) { вonTouchEvent(MotionEvent event) метод, чтобы пользователь мог получить звук щелчка.

Ваш ответ на вопрос