自定義View–支持右側圖片點擊的EditTextView
知識點:onTouchEvent
相信大家都用過EditTextView的drawableRight屬性,在xml文件中使用android:drawableRight="@mipmap/ic_search",就可以在輸入框的右側增加一個圖標
但是,這個EditTextView並沒有給我們提供這個圖標的點擊回調方法,導致我們無法根據點擊這個圖標來編寫我們之後的邏輯操作。
我們首先需要先能得到這個圖標的位置,再根據我們手指觸摸的屏幕的位置對比是否處在圖標內,就可以繼續我們點擊後的操作了。
所以onTouchEvent()這個回調函數就登場了
首先,我們先了解一下onTouchEvent,onTouchEvent() 和 onTouch() 這兩個方法很像,但是千萬不要弄混了。
onTouchEvent(MotionEvent event)是View中定義的方法,而且是Public類型,所以Activity、ViewGroup、View均可以調用這個方法,最常見的關於這塊的知識點在Android事件分發中,onTouchEvent()是每個事件處理對象都有的方法,用於根據下層的onTouchEvent()返回值類型判斷是否調用,最常見的用法是自定義View時寫入到view中,從而讓該View獲取用戶對手機屏幕的各種操作,並對不同類型的操作實現不同的反饋,屬於一個宏觀的屏幕觸摸監控方法;
onTouch((View v, MotionEvent event)是View.OnTouchListener接口中實現的唯一方法,接收兩個參數,第二個參數是之前提過的event事件對象,第一個參數是一個具體的view類型對象,這就意味着onTouch()方法必須和某個控件進行綁定,即某個控件實現了View.OnTouchListener接口,才能調用onTouch()方法。
首先,我們新建一個class類,名字叫做EditTextWithDrawable(英語不好,隨便起的😹),這個類繼承了AppCompatEditText類,我們需要重寫onTouchEvent這個回調函數。
首先,我們需要先獲取到右側圖標的左右座標閾值,因爲我們是繼承了EditTextView,所以我們可以使用EditTextView提供的函數
getWidth() 獲取自定義EditTextView控件的寬度
getCompoundPaddingRight()返回視圖的右側填充,以及右側Drawable的空間(如果有)
event.getX()手指觸摸的位置座標x
getPaddingRight() 返回此視圖的右填充。如果有插入和啓用滾動條,此值可能還包括顯示滾動條所需的空間。
所以,圖片的左閾值爲getWidth() - getCompoundPaddingRight(),右閾值爲getWidth() - getPaddingRight()
我們已經知道了圖片的左右閾值,我們根據觸摸點的x座標與閾值對比,在閾值範圍內即爲點擊到圖片。
注意,我們還需要先獲取圖片資源
EditTextView爲我們提供了方法getCompoundDrawables獲取已設置的drawable
/**
* Returns drawables for the left, top, right, and bottom borders.
* 返回值爲左,頂部,右,底部的drawable
*
* @attr ref android.R.styleable#TextView_drawableLeft
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableRight
* @attr ref android.R.styleable#TextView_drawableBottom
*/
@NonNull
public Drawable[] getCompoundDrawables() {
final Drawables dr = mDrawables;
if (dr != null) {
return dr.mShowing.clone();
} else {
return new Drawable[] { null, null, null, null };
}
}
判斷右側圖片是否存在,在進行座標比較。
if (mCompoundRightDrawable != null) {
if (getWidth() - getCompoundPaddingRight() < event.getX() && getWidth() - getPaddingRight() > event.getX()) {
if (mRightClickListener != null) {
mRightClickListener.onClick();
return true;
}
}
}
我們還可以定義一個接口,這樣我們就可以寫回調方法,點擊右側圖片的回調
public interface onDrawableRightClick {
void onClick();
}
再定義一個public方法,在使用接口回調的地方將listener傳進來
public void setOnRightDrawableClickListener(onDrawableRightClick clickListener) {
this.mRightClickListener = clickListener;
}
那我們如何使用呢?
首先activity_main.xmll文件添加
<com.felix.baselibrary.UI.EditTextWithDrawable
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableRight="@mipmap/ic_search" />
MainActivity.java
mEtTest = (EditTextWithDrawable) findViewById(R.id.et_test);
mEtTest.setOnRightDrawableClickListener(new EditTextWithDrawable.onDrawableRightClick() {
@Override
public void onClick() {
//這裏我們就可以寫點擊事件了
}
});
這樣,我們的自定義View就完成了。
本人剛開始寫博客,以前都是通過別人的博客cv代碼,看完就忘了,所以現在打算自己開始寫博客記錄我的學習之旅,寫的不好,大家多多批評
完整源碼
package com.felix.client.widget;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
/**
* Created by fangxin on 2020/4/15.
*/
public class EditTextWithDrawable extends AppCompatEditText {
private static final String TAG = EditTextWithDrawable.class.getSimpleName();
private Drawable[] mCompoundDrawables;
private Drawable mCompoundRightDrawable;
private Drawable mCompoundLeftDrawable;
private Drawable mCompoundTopDrawable;
private Drawable mCompoundBottomDrawable;
private onDrawableRightClick mRightClickListener;
private onDrawableLeftClick mLeftClickListener;
private onDrawableTopClick mTopClickListener;
private onDrawableBottomClick mBottomClickListener;
public EditTextWithDrawable(Context context) {
super(context);
init();
}
public EditTextWithDrawable(Context context, AttributeSet attrs) {
// super(context, attrs);
super(context, attrs, android.R.attr.editTextStyle);
init();
}
public EditTextWithDrawable(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mCompoundDrawables = getCompoundDrawables();//getCompoundDrawables() -> Returns drawables for the left, top, right, and bottom borders.
mCompoundLeftDrawable = mCompoundDrawables[0];
mCompoundTopDrawable = mCompoundDrawables[1];
mCompoundRightDrawable = mCompoundDrawables[2];
mCompoundBottomDrawable = mCompoundDrawables[3];
}
public void setOnRightDrawableClickListener(onDrawableRightClick clickListener) {
this.mRightClickListener = clickListener;
}
public void setOnLeftDrawableClickListener(onDrawableLeftClick clickListener) {
this.mLeftClickListener = clickListener;
}
public void setOnTopDrawableClickListener(onDrawableTopClick clickListener) {
this.mTopClickListener = clickListener;
}
public void setOnBottomDrawableClickListener(onDrawableBottomClick clickListener) {
this.mBottomClickListener = clickListener;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
//右側照片點擊監聽
if (mCompoundRightDrawable != null) {
if (getWidth() - getCompoundPaddingRight() < event.getX() && getWidth() - getPaddingRight() > event.getX()) {
if (mRightClickListener != null) {
mRightClickListener.onClick();
return true;
}
}
}
//左側照片點擊
if (mCompoundLeftDrawable != null) {
if (getCompoundPaddingLeft() > event.getX() && event.getX() > getPaddingLeft()) {
if (mLeftClickListener != null) {
mLeftClickListener.onClick();
return true;
}
}
}
//上側照片點擊
if (mCompoundTopDrawable != null) {
if (getCompoundPaddingTop() > event.getY() && event.getY() > getPaddingTop()) {
if (mTopClickListener != null) {
mTopClickListener.onClick();
return true;
}
}
}
//下側照片點擊
if (mCompoundBottomDrawable != null) {
if (getHeight() - getPaddingBottom() > event.getY() && event.getY() > getHeight() - getCompoundPaddingBottom()) {
if (mBottomClickListener != null) {
mBottomClickListener.onClick();
return true;
}
}
}
}
return super.onTouchEvent(event);
}
public interface onDrawableRightClick {
void onClick();
}
public interface onDrawableLeftClick {
void onClick();
}
public interface onDrawableTopClick {
void onClick();
}
public interface onDrawableBottomClick {
void onClick();
}
}