Android-仿IOS搜索框
目录
Android 仿IOS搜索框
搜索框样式如图
实现步骤:
1、素材
ico_delete.png
ico_delete_p.png
ico_search.png
selector_search_bg.xml
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<corners android:radius="5dp"/>
<solid android:color="@color/theme_front_light"/>
<stroke android:width="0dp" android:color="@color/theme_front_light"/>
</shape>
</item>
<item android:state_focused="true">
<shape>
<corners android:radius="5dp"/>
<solid android:color="@color/theme_front_light"/>
<stroke android:width="0dp" android:color="@color/theme_front_light"/>
</shape>
</item>
<item>
<shape>
<corners android:radius="5dp"/>
<solid android:color="@color/theme_front_dark"/>
<stroke android:width="0dp" android:color="@color/theme_front_dark"/>
</shape>
</item>
</selector>
style.xml
<!-- 自定义搜索框样式 -->
<style name="editTextStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">35dp</item>
<item name="android:background">@drawable/selector_search_bg</item>
<item name="android:drawablePadding">5dp</item>
<item name="android:drawableStart">@drawable/ico_search</item>
<item name="android:gravity">center_vertical</item>
<item name="android:imeOptions">actionSearch</item>
<item name="android:padding">5dp</item>
<item name="android:singleLine">true</item>
<item name="android:textSize">15sp</item>
<item name="android:textColor">@color/white</item>
<item name="android:textColorHint">@color/light_white</item>
<item name="android:hint">@string/t_search</item>
</style>
<!-- 自定义搜索框文本样式 -->
<style name="textViewStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">40dp</item>
<item name="android:gravity">center</item>
<item name="android:textSize">20sp</item>
</style>
2、控件
SearchEditText.java
/**
* Created by xl on 2018/1/29.
* 自定义搜索框
* 使用方法:
* 需要设置SearchEditText不自动获取焦点
* 设置方法:在父控件中加入以下两个属性
* android:focusable="true"
* android:focusableInTouchMode="true"
*/
public class SearchEditText extends EditText implements View.OnFocusChangeListener, View.OnKeyListener, TextWatcher {
private static final String TAG = SearchEditText.class.getSimpleName();
private Context mContext;
//图标是否默认在左边
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;
/**
* 构造器
*
* @param context
*/
public SearchEditText(Context context) {
this(context, null);
this.mContext = context;
init();
}
/**
* 构造器
*
* @param context
*/
public SearchEditText(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.editTextStyle);
this.mContext = context;
init();
}
/**
* 构造器
*
* @param context
*/
public SearchEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
init();
}
/**
* 初始化函数
*/
private void init() {
setOnFocusChangeListener(this);
setOnKeyListener(this);
addTextChangedListener(this);
}
/**
* 绘制
*
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
if (isIconLeft) { // 如果是默认样式,直接绘制
if (length() < 1) {
drawableDel = null;
}
//drawable的宽高是按drawable固定的宽高,即通过getIntrinsicWidth()与getIntrinsicHeight()获得
//this.setCompoundDrawablesWithIntrinsicBounds(drawableLeft, null, drawableDel, null);
//drawable的宽高是按drawable.setBound()设置的宽高
this.setCompoundDrawables(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.getBounds().width();
int drawableWidth = drawableLeft.getIntrinsicWidth();
float bodyWidth = textWidth + drawableWidth + drawablePadding;
canvas.translate((getWidth() - bodyWidth - getPaddingLeft() - getPaddingRight()) / 2, 0);
super.onDraw(canvas);
}
}
/**
* 焦点监听
*
* @param v
* @param hasFocus
*/
@Override
public void onFocusChange(View v, boolean hasFocus) {
// 被点击时,恢复默认样式
if (!pressSearch && TextUtils.isEmpty(getText().toString())) {
isIconLeft = hasFocus;
}
}
/**
* 按键监听
*
* @param v
* @param keyCode
* @param event
* @return
*/
@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;
}
/**
* 触摸监听
*
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
// 清空edit内容
if (drawableDel != null && event.getAction() == MotionEvent.ACTION_UP) {
eventX = (int) event.getRawX();
eventY = (int) event.getRawY();
MyLogger.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();
MyLogger.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.ico_delete_p);
} else {
drawableDel = this.getResources().getDrawable(R.drawable.ico_delete);
}
return super.onTouchEvent(event);
}
/**
* 输入变化监听
*
* @param arg0
*/
@Override
public void afterTextChanged(Editable arg0) {
if (this.length() < 1) {
drawableDel = null;
} else {
drawableDel = this.getResources().getDrawable(R.drawable.ico_delete);
}
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
/**
* 测量
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (drawables == null) {
drawables = getCompoundDrawables();
}
if (drawableLeft == null) {
drawableLeft = drawables[0];
//drawableLeft.setBounds(0, 0, DensityUtil.dip2px(mContext, 16), DensityUtil.dip2px(mContext, 16));
}
if (drawableDel != null) {
drawableDel.setBounds(0, 0, DensityUtil.dip2px(mContext, 18), DensityUtil.dip2px(mContext, 18));
}
}
/**
* 设置接口
*
* @param listener
*/
public void setOnSearchClickListener(OnSearchClickListener listener) {
this.listener = listener;
}
/**
* 定义接口
*/
public interface OnSearchClickListener {
void onSearchClick(View view);
}
}
3、工具类
DensityUtil.java
**
* dip与px之间的转换,工具类
* Created by xl on 2018/2/5.
*/
public class DensityUtil {
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
}
4、使用
a、布局文件
<RelativeLayout
android:id="@+id/lay"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:focusable="true"
android:focusableInTouchMode="true"
android:visibility="gone">
<com.app.view.SearchEditText
android:id="@+id/search"
style="@style/editTextStyle"
android:layout_centerVertical="true" />
</RelativeLayout>
b、activity
/**
* Created by xl on 2018/5/30.
*/
public class DevListActivity extends Activity {
private SearchEditText mSearch;
mSearch = (SearchEditText) findViewById(R.id.search);
mSearch.setOnSearchClickListener(new SearchEditText.OnSearchClickListener() {
@Override
public void onSearchClick(View view) {
// 搜索
if (mstrKeyWord.equals("")) {
return;
}
mListView.setMode(PullToRefreshBase.Mode.PULL_FROM_END);
mbSearchFlag = true;
miPagerNo = 1;
mbNoMoreData = false;
mListAdapter.clear();
selectDev();
}
});
mSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
@Override
public void afterTextChanged(Editable arg0) {
mHandler.post(new Runnable() {
@Override
public void run() {
mstrKeyWord = mSearch.getText().toString();
if (mstrKeyWord.equals("")) {
mListAdapter.updateList(mList);
mbEditEmpty = true;
if (mbSearchFlag) {
miPagerNo = miTempPagerNo;
mbNoMoreData = mbTempNoMoreData;
mbSearchFlag = false;
}
if (mbNoMoreData) {
mListView.setMode(PullToRefreshBase.Mode.PULL_FROM_START);
} else {
mListView.setMode(PullToRefreshBase.Mode.BOTH);
}
} else {
mListSearch.clear();
if (mbEditEmpty) {
mbEditEmpty = false;
mList.clear();
mList.addAll(mListAdapter.getList());
mListView.setMode(PullToRefreshBase.Mode.DISABLED);
miTempPagerNo = miPagerNo;
mbTempNoMoreData = mbNoMoreData;
}
for (int i = 0; i < mList.size(); i++) {
if (mList.get(i).getCode().contains(mstrKeyWord)) {
mListSearch.add(mList.get(i));
}
}
mListAdapter.updateList(mListSearch);
}
}
});
}
});
完!!!