Вопрос по android, android-edittext – Установка onClickListener для Drawable справа от EditText [duplicate]

72

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

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

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

 

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

Это лучший ответstackoverflow.com/a/37032927/346309 JPM
Самое простое решение с использованием Android APIstackoverflow.com/a/26269435/185022 :-) AZ_

Ваш Ответ

6   ответов
88
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;
            }
        }

    });
Привет, я не нахожу CoreSystemContext.SCALE, поэтому код показывает ошибку. как я могу получить CoreSystemContext.SCALE. Пожалуйста, порекомендуйте. arefin
Это переменная плотность удерживающего устройства. вместо этого используйте getResources (). getDisplayMetrics (). density, вам может потребоваться создать статическое переменное в другом файле. Это для преобразования пикселей в дп. Простым решением было бы удалить эту переменную. Hardik4560
Я бы также передал Edittext в качестве параметра для обратного вызова. Но хороший ответ, тем не менее. st0le
Хорошо сработало для меня Qadir Hussain
6

у меня нет доступа к нужному изображению, если только вы не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>
Проблема этого подхода заключается в том, что он разваливается, как только вы начинаете изменять размер текста в EditText. Вы можете подумать, чтопросто на разработчикасторона, но этоЭто не так, как устройства имеют размер текста в настройках. Вы можете избежать этого, используя dp вместо sp в EditText, но это только ухудшает ситуацию. Другие проблемы, такие как обработка многострочных EditTexts Sotti
28

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

Идея заключается в использовании положить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 и установите маржу программно.

Линтер предупредит васнеэффективное дерево компоновки, используйте составное рисованиетакже больше кода, чем drawableRight = ""... 最白目
Проблема этого подхода заключается в том, что он разваливается, как только вы начинаете изменять размер текста в EditText. Вы можете подумать, чтопросто на разработчикасторона, но этоЭто не так, как устройства имеют размер текста в настройках. Вы можете избежать этого, используя dp вместо sp в EditText, но это только ухудшает ситуацию. Другие проблемы, такие как обработка многострочных EditTexts Sotti
Это'Простые вещи, которые работают лучше всего. DariusL
Проблемы с полями и отступами будут для разных устройств. SMR
-2

Создайте изображение кнопки с вашим значком и установите его цвет фона прозрачным.Поместите кнопку изображения на EditTextРеализоватьonclic»k слушатель кнопки, чтобы выполнить вашу функцию
Вам нужно понять вопрос! Он / она нене спрашиваю альтернативного решения. Nizzy
Проблема этого подхода заключается в том, что он разваливается, как только вы начинаете изменять размер текста в EditText. Вы можете подумать, чтопросто на разработчикасторона, но этоЭто не так, как устройства имеют размер текста в настройках. Вы можете избежать этого, используя dp вместо sp в EditText, но это только ухудшает ситуацию. Другие проблемы, такие как обработка многострочных EditTexts Sotti
Что делать, если размер editText увеличивается? Что делать, если у меня есть много editText, который требует этого, что обычно происходит. Hardik4560
218

Простое решение, используйте методы, которые уже дал 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;
        }
    });
Для меня это работает для (event.getRawX () + editComment.getPaddingLeft ()) <= (editComment.getCompoundDrawables () [DRAWABLE_LEFT] .getBounds (). width () + editComment.getLeft ()) где для редактирования текста я применил drawable paddng Shoaib Chikate
@AZ_ У меня есть другой текст редактирования ниже, и всякий раз, когда моя деятельность начинается, второй текст редактирования получает фокус, а не первый, который имеет DRAWABLE_RIGHT. Что я должен сделать, чтобы сфокусироваться на первом? Salman Khan
Работал на меня. Вот код для нажатия левой иконки ... if (event.getRawX () <= (editComment.getCompoundDrawables () [DRAWABLE_LEFT] .getBounds (). width ())) kwh
Это решение работает также для TextView. Пожалуйста изменитеeditComment.getRight() - editComment.getCompoundDrawables() вv.getRight() - ((EditText) v).getCompoundDrawables(), Если кто-то обрабатываетonClick на текст, изменитьMotionEvent.ACTION_UP кMotionEvent.ACTION_DOWN CoolMind
-1

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

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

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

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

Похожие вопросы