Custom EditText с тремя кнопками справа

от автора

Здравствуйте.

В ходе разработки одного приложения, захотелось добавить кнопку очистки текста к компоненту EditText. Решение было найдено достаточно быстро и заключалось в том, чтобы отлавливать координаты касания и если касание произошло над правым фоновым изображением (drawableRight), то обрабатывать как нажатие кнопки (очищать текст), иначе — стандартным для данного компонента способом.

Решение получилось достаточно лаконичным и надёжно работающим. Но затем захотелось пойти дальше и сделать 2-3 кнопки, мало ли какой ещё функционал можно навесить на них, например выбор из списка, который открывается в отдельном окне или включение/отключение режима редактирования, чтобы защитить поле от случайных изменений.

Итак, начнём:
1. Создаём новый проект с пустой activity (среда разработки Android Studio 1.5.1).

2. Добавляем новый класс и называем его MyCustomEditText, полный листинг:

import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; import android.widget.EditText;  public class MyCustomEditText extends EditText {      Bitmap drawableRight; //стандартный drawable справа     Bitmap drawableRight2; //то, ЧТО будем рисовать     Bitmap drawableRight3; //то, ЧТО будем рисовать     Paint paint; //то, ЧЕМ будем рисовать      public MyCustomEditText(Context context) {         super(context);          init();      }      public MyCustomEditText(Context context, AttributeSet attrs) {         super(context, attrs);          initDrawables(attrs);          init();     }      public MyCustomEditText(Context context, AttributeSet attrs, int defStyleAttr) {          super(context, attrs, defStyleAttr);          initDrawables(attrs);          init();      }      @Override     protected void onDraw(Canvas canvas) {          super.onDraw(canvas);          if (drawableRight != null) {              //рисуем drawableRight2 только при наличии drawableRight             if (drawableRight2 != null) {                  canvas.drawBitmap(drawableRight2, getWidth() + getScrollX() - drawableRight.getWidth() * 2, (getHeight() - drawableRight2.getHeight()) / 2, paint);                  //рисуем drawableRight3 только при наличии drawableRight2                 if (drawableRight3 != null) {                      canvas.drawBitmap(drawableRight3, getWidth() + getScrollX() - drawableRight.getWidth() * 3, (getHeight() - drawableRight3.getHeight()) / 2, paint);                  }              }          }      }      /**      * Returns the right padding of the view, plus space for the right      * Drawable if any.      */     @Override     public int getCompoundPaddingRight() {          //здесь мы устанавливаем отступ справа, чтобы каретка не наезжала на наши кнопки         int paddingRight = super.getCompoundPaddingRight();          if (drawableRight2 != null) {             paddingRight = paddingRight + drawableRight2.getWidth();         }         if (drawableRight3 != null) {             paddingRight = paddingRight + drawableRight3.getWidth();         }         return paddingRight;     }      private void initDrawables(AttributeSet attrs) {          //инициализируем наши drawables, если были заполнены соответствующие атрибуты         for (int i = 0; i < attrs.getAttributeCount(); i++) {              if (attrs.getAttributeName(i).equals("drawableRight")) {                  drawableRight = BitmapFactory.decodeResource(getResources(), attrs.getAttributeResourceValue(i, 0));              }              if (attrs.getAttributeName(i).equals("drawableRight2")) {                  drawableRight2 = BitmapFactory.decodeResource(getResources(), attrs.getAttributeResourceValue(i, 0));              }              if (attrs.getAttributeName(i).equals("drawableRight3")) {                  drawableRight3 = BitmapFactory.decodeResource(getResources(), attrs.getAttributeResourceValue(i, 0));              }          }      }      private void init() {          paint = new Paint();      }  } 

3. Чтобы у нашего компонента были нужные нам свойства, необходимо создать attrs.xml следующего содержания:

<?xml version="1.0" encoding="utf-8"?> <resources>     <declare-styleable name="MyCustomEditText">         <attr name="drawableRight2" format="reference"/>         <attr name="drawableRight3" format="reference"/>     </declare-styleable> </resources> 

4. После чего можно установить значения этих свойств в файле-разметки:

<ru.vlsoft.mycustomedittext.MyCustomEditText         android:id="@+id/customEditText"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_alignParentLeft="true"         android:layout_alignParentStart="true"         android:drawableEnd="@drawable/one"         android:drawableRight="@drawable/one"         android:textAppearance="?android:attr/textAppearanceLarge"         app:drawableRight2="@drawable/two"         android:singleLine="true"         app:drawableRight3="@drawable/three"         android:layout_alignParentRight="true"         android:layout_alignParentEnd="true" /> 

5. Ну и последним шагом будет добавление обработчика события onTouchListener в главной activity, полный листинг которой ниже:

import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.MotionEvent; import android.view.View;  public class MainActivity extends AppCompatActivity {      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);          MyCustomEditText customEditText = (MyCustomEditText) findViewById(R.id.customEditText);         customEditText.setOnTouchListener(new View.OnTouchListener() {             @Override             public boolean onTouch(View v, MotionEvent event) {                  if (event.getAction() == MotionEvent.ACTION_DOWN) {                      MyCustomEditText editText = (MyCustomEditText) v;                                          //подразумеваем, что все 3 изображения справа указаны                     //и т.к. все изображения у нас одного размера, то будем отталкиваться от размера самого правого                     int drawableSize = editText.getCompoundDrawables()[2].getBounds().width();                      if (event.getRawX() >= editText.getRight() - drawableSize) {                          Log.i("sdf", "one");                         return true;                      } else if (event.getRawX() >= editText.getRight() - drawableSize * 2) {                          Log.i("sdf", "two");                         return true;                      } else if (event.getRawX() >= editText.getRight() - drawableSize * 3) {                          Log.i("sdf", "three");                         return true;                      } else {                          return false;                     }                 } else {                      return false;                  }             }         });      } }  

Весь проект можно скачать — здесь
Надеюсь, кому-нибудь пригодится, спасибо за внимание.

ссылка на оригинал статьи http://habrahabr.ru/post/273589/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *