【Android自定义控件】仿IOS风格的搜索框

IOS很多控件的设计都是很值得借鉴的存在,作为移动开发的初学者,我们可以把这种模仿等同于学画、练字时为铸就基础的临摹行为。达者为师,努力学习别人的优点吧。
这里是仿IOS搜索框风格的自定义控件,引用了http://blog.csdn.net/djl461260911/article/details/46401139 这篇博客的代码,加入了清除按钮的功能。吐槽下csdn的编辑器,忽略缩进真的很影响界面效果。

1.控件最终效果图:
1)控件未获得焦点时如下:
【Android自定义控件】仿IOS风格的搜索框_第1张图片
2)点击开始编辑时:
注意软件盘右下角的回车键变成了搜索样式,同时搜索图标和hint text已经移动到编辑框最左边
【Android自定义控件】仿IOS风格的搜索框_第2张图片
3)焦点离开时:
【Android自定义控件】仿IOS风格的搜索框_第3张图片
4)输入内容,删除按钮在最右边出现:
【Android自定义控件】仿IOS风格的搜索框_第4张图片
5)删除按钮按下变色,已经按下后清除内容就不一一截图了。

2.代码实现:
1)控件样式文件 style.xml

"http://schemas.android.com/apk/res/android">
    

    
2)控件颜色资源文件colors.xml

<resources>
    <color name="search_edit_gray">#ffcccccccolor>
resources>
3)控件图片资源:

edit_delete_icon.png
这里写图片描述
edit_delete_pressed_icon.png
这里写图片描述
search_icon.png
这里写图片描述
4)控件代码 SearchEditText .java
从界面优化思想来说,自定义控件也要尽可能的减少布局节点,因此使用ViewGroup来自定义控件应该尽量避免。

public class SearchEditText extends EditText implements OnFocusChangeListener, OnKeyListener, TextWatcher{
private static final String TAG = "SearchEditText";
/**
* 图标是否默认在左边
*/
private boolean isIconLeft = false;
/**
* 是否点击软键盘搜索
*/
private boolean pressSearch = false;
/**
* 软键盘搜索键监听
*/
private OnSearchClickListener listener;

private Drawable[] drawables; // 控件的图片资源
private Drawable drawableLeft, drawableDel; // 搜索图标和删除按钮图标
private int eventX, eventY; // 记录点击坐标
private Rect rect; // 控件区域

public void setOnSearchClickListener(OnSearchClickListener listener) {
this.listener = listener;
}

public interface OnSearchClickListener {
void onSearchClick(View view);
}

public SearchEditText(Context context) {
this(context, null);
init();
}


public SearchEditText(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.editTextStyle);
init();
}


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

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


@Override
protected void onDraw(Canvas canvas) {
if (isIconLeft) { // 如果是默认样式,直接绘制
if (length() < 1) {
drawableDel = null;
}
this.setCompoundDrawablesWithIntrinsicBounds(drawableLeft, null, drawableDel, null);
super.onDraw(canvas);
} else { // 如果不是默认样式,需要将图标绘制在中间
if (drawables == null) drawables = getCompoundDrawables();
if (drawableLeft == null) drawableLeft = drawables[0];
float textWidth = getPaint().measureText(getHint().toString());
int drawablePadding = getCompoundDrawablePadding();
int drawableWidth = drawableLeft.getIntrinsicWidth();
float bodyWidth = textWidth + drawableWidth + drawablePadding;
canvas.translate((getWidth() - bodyWidth - getPaddingLeft() - getPaddingRight()) / 2, 0);
super.onDraw(canvas);
}
}


@Override
public void onFocusChange(View v, boolean hasFocus) {
// 被点击时,恢复默认样式
if (!pressSearch && TextUtils.isEmpty(getText().toString())) {
isIconLeft = hasFocus;
}
}

@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
pressSearch = (keyCode ==KeyEvent.KEYCODE_ENTER);
if (pressSearch && listener != null) {
/*隐藏软键盘*/
InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isActive()) {
imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0);
}
listener.onSearchClick(v);
}
return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
// 清空edit内容
if (drawableDel != null && event.getAction() == MotionEvent.ACTION_UP) {
eventX = (int) event.getRawX();
            eventY = (int) event.getRawY();
            Log.i(TAG, "eventX = " + eventX + "; eventY = " + eventY);
            if (rect == null) rect = new Rect();
            getGlobalVisibleRect(rect);
            rect.left = rect.right - drawableDel.getIntrinsicWidth();
            if (rect.contains(eventX, eventY)) {
            setText("");
            }
}
// 删除按钮被按下时改变图标样式
if (drawableDel != null && event.getAction() == MotionEvent.ACTION_DOWN) {
eventX = (int) event.getRawX();
            eventY = (int) event.getRawY();
            Log.i(TAG, "eventX = " + eventX + "; eventY = " + eventY);
            if (rect == null) rect = new Rect();
            getGlobalVisibleRect(rect);
            rect.left = rect.right - drawableDel.getIntrinsicWidth();
            if (rect.contains(eventX, eventY))
            drawableDel = this.getResources().getDrawable(R.drawable.edit_delete_pressed_icon);
} else {
drawableDel = this.getResources().getDrawable(R.drawable.edit_delete_icon);
}
return super.onTouchEvent(event);
}


@Override
public void afterTextChanged(Editable arg0) {
if (this.length() < 1) {
drawableDel = null;
} else {
drawableDel = this.getResources().getDrawable(R.drawable.edit_delete_icon);
}
}


@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}

@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
            int arg3) {
    }
}

3.Activity演示代码
1)布局文件 activity_main.xml
初学者注意这里自定义控件的包名,填写控件实际所在包路径

"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:padding="5dp"
    android:focusable="true" 
android:focusableInTouchMode="true"
    tools:context=".MainActivity" >


    <com.example.material.widget.SearchEditText
        android:id="@+id/activity_main_input_edittext"
        style="@style/editTextStyle"
        android:layout_marginTop="20dp" />

    <com.example.material.widget.SearchEditText
        android:id="@+id/activity_main_input_edittext2"
        style="@style/editTextStyle"
        android:layout_below="@+id/activity_main_input_edittext"
        android:layout_marginTop="20dp" />


2)Activity代码 MainActivity.java
public class MainActivity extends ActionBarActivity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}

你可能感兴趣的:(自定义,仿ios,edittext,清除按钮,搜索控件)