1. 程式人生 > >ClearEditText,自帶清除功能的EditText

ClearEditText,自帶清除功能的EditText

一、效果圖


二、特點

1.簡單。只有一個不到100行的類,且無任何依賴,也沒有自定義屬性

2.高效。沒有使用LinearLayout包含EditText+ImageView的組合形式實現,僅僅只有一個繼承EditText的自定義view,減少了佈局的巢狀和view的數量

3.易用。看我程式碼中的呼叫就知道多簡單了

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.afei.myedittext.MainActivity">

    <com.afei.myedittext.ClearEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</RelativeLayout>

三、ClearEditText程式碼

package com.afei.myedittext;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;

public class ClearEditText extends EditText implements View.OnFocusChangeListener, TextWatcher {

    private Drawable mClearDrawable;
    private boolean hasFocus;

    public ClearEditText(Context context) {
        this(context, null);
    }

    public ClearEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

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

    private void init() {
        // getCompoundDrawables() Returns drawables for the left(0), top(1), right(2) and bottom(3)
        mClearDrawable = getCompoundDrawables()[2]; // 獲取drawableRight
        if (mClearDrawable == null) {
            // 如果為空,即沒有設定drawableRight,則使用R.mipmap.close這張圖片
            mClearDrawable = getResources().getDrawable(R.mipmap.close);
        }
        mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
        setOnFocusChangeListener(this);
        addTextChangedListener(this);
        // 預設隱藏圖示
        setDrawableVisible(false);
    }

    /**
     * 我們無法直接給EditText設定點選事件,只能通過按下的位置來模擬clear點選事件
     * 當我們按下的位置在圖示包括圖示到控制元件右邊的間距範圍內均算有效
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            if (getCompoundDrawables()[2] != null) {
                int start = getWidth() - getTotalPaddingRight() + getPaddingRight(); // 起始位置
                int end = getWidth(); // 結束位置
                boolean available = (event.getX() > start) && (event.getX() < end);
                if (available) {
                    this.setText("");
                }
            }
        }
        return super.onTouchEvent(event);
    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        this.hasFocus = hasFocus;
        if (hasFocus && getText().length() > 0) {
            setDrawableVisible(true); // 有焦點且有文字時顯示圖示
        } else {
            setDrawableVisible(false);
        }
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int count, int after) {
        if (hasFocus) {
            setDrawableVisible(s.length() > 0);
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void afterTextChanged(Editable s) {
    }

    protected void setDrawableVisible(boolean visible) {
        Drawable right = visible ? mClearDrawable : null;
        setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
    }

}

四、注意事項

1.圖示你可以通過在xml中android:drawableRight=""指定,當然如果你不指定我沒呢就會使用一個預設圖示,這個圖示需要事先準備,畢竟ic_launcher太醜了

2.圖示預設顯示在右側,如果你的需求很古怪的話可以自己修改相應程式碼輕鬆實現(修改getCompoundDrawables()[]對應的陣列下標)

3.DropEditText整個控制元件的高度不要太小,否則文字或者圖片會顯示不全,這是EditText都會有的問題

4.例如我的DropEditText使用的高度為“wrap_content",但是圖片如果較大的話當drawable顯示的時候就會撐高DropEditText的高度,所以你的圖片高度應該適中,我使用的圖片是60*60的,放置在xxhdpi下效果就很好

五、其他資源及git地址

close.png圖片: