Android自定义带搜索图标及删除按钮的搜索框SearchEditText

最近项目需求要用到带删除按钮的搜索框,开始设计时搜索图标及提示文字是在左侧的,但是经讨论要求与IOS的UISearchBar风格一致即默认情况下,搜索图标和文字是居中的,在获取焦点时,图标及提示文字左移,输入搜索文字时,删除按钮右端显示,如下图所示:

默认情况:

获取焦点时:

输入文字后:

首先直接自定义SearchEditText:

@SuppressLint("AppCompatCustomView")
public class SearchEditText extends EditText implements View.OnFocusChangeListener, TextWatcher {
    private static final String TAG = "SearchEditText";
    /**
     * 删除按钮与右边编辑框之间的paddingRight距离
     */
    private int paddingRightValueBetweenRightBorderAndDel = 0;

    /**
     * 图标是否默认在左边
     */
    private boolean isIconLeft = false;

    /**
     * 控件的图片资源
     */
    private Drawable[] mDrawables;

    /**
     * drawableLeft:搜索图标; drawableDel:删除按钮图标
     */
    private Drawable drawableLeft, drawableDel;

    /**
     * 记录点击坐标
     */
    private int eventX, eventY;

    /**
     * 控件区域
     */
    private Rect mRect;

    public SearchEditText(Context context) {
        super(context);
        init();
    }

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

    public SearchEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public SearchEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init(){
        setOnFocusChangeListener(this);
        addTextChangedListener(this);
    }

    @Override
    protected void onDraw(Canvas canvas){

        if(isIconLeft){
            if(length() < 1){
                drawableDel = null;
            }
            this.setCompoundDrawablesWithIntrinsicBounds(drawableLeft, null, drawableDel, null);  //在edittext的左上右下设置Drawable
            super.onDraw(canvas);
        }else {
            if(mDrawables == null){
                mDrawables = getCompoundDrawables(); //返回包含左上右下四个位置的Drawable数组
            }
            if(drawableLeft == null){
                drawableLeft = mDrawables[0];
            }
            float textWidth = getPaint().measureText(getHint().toString());
            int drawablePadding = getCompoundDrawablePadding();  //返回Drawable和text之间的padding值
            int drawableWidth = drawableLeft.getIntrinsicWidth();   //获得Drawable的固有宽度
            float bodyWidth = textWidth + drawablePadding + drawableWidth;
            canvas.translate((getWidth() - bodyWidth - getPaddingLeft() - getPaddingRight()) / 2, 0);
            super.onDraw(canvas);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(drawableDel != null && event.getAction() == MotionEvent.ACTION_UP){
            eventX = (int)event.getRawX();
            eventY = (int)event.getRawY();
            if(mRect == null){
                mRect = new Rect();
            }
            getGlobalVisibleRect(mRect);  // edittext在屏幕中的坐标
            mRect.left = mRect.right - drawableDel.getIntrinsicWidth() - getPaddingRightValueBetweenRightBorderAndDel();
            if(mRect.contains(eventX, eventY)){
                setText("");
            }
        }
//        if(drawableDel != null && event.getAction() == MotionEvent.ACTION_DOWN){
//            eventX = (int)event.getRawX();
//            eventY = (int)event.getRawY();
//            if(mRect == null){
//                mRect = new Rect();
//            }
//            getGlobalVisibleRect(mRect);
//            mRect.left = mRect.right - drawableDel.getIntrinsicWidth();
//            if(mRect.contains(eventX, eventY)){
//                drawableDel = this.getResources().getDrawable(R.mipmap.clear_edit);
//            }else {
//                drawableDel = this.getResources().getDrawable(R.mipmap.clear_edit);
//            }
//        }
        return super.onTouchEvent(event);
    }

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

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        if(this.length() < 1){
            drawableDel = null;
        }else {
            drawableDel = this.getResources().getDrawable(R.mipmap.clear_edit);
        }
    }

    @Override
    public void afterTextChanged(Editable s) {

    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if(TextUtils.isEmpty(getText().toString())){
            isIconLeft = hasFocus;
        }
    }

    public void setPaddingRightValueBetweenRightBorderAndDel(int dimenID){
        this.paddingRightValueBetweenRightBorderAndDel = dimenID;
    }

    private int getPaddingRightValueBetweenRightBorderAndDel(){
        return this.getResources().getDimensionPixelOffset(paddingRightValueBetweenRightBorderAndDel);
    }
}

搜索框样式:


    

搜索框背景:



    
        
            
            
            
        
    

布局代码:




    


备注:

1.每次进入界面后,EditText自动获取焦点导致输入法自动弹出来,所以为了解决这个问题,在EditText的父布局中加两个属性:

android:focusable="true" 
android:focusableInTouchMode="true"

2.在清单配置文件的对应Activity加上

android:windowSoftInputMode="adjustPan"防止布局被输入法顶上去。

你可能感兴趣的:(Android)