Здравствуйте.
В ходе разработки одного приложения, захотелось добавить кнопку очистки текста к компоненту 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/
Добавить комментарий