Android 自定义EditText实现类iOS风格搜索框
最近在项目中有使用到搜索框的地方,由于其样式要求与iOS的UISearchBar的风格一致。默认情况下,搜索图标和文字是居中的,在获取焦点的时候,图标和文字左移。但是在Android是并没有这样的控件(可能见识少,并不知道有)。通常情况下我们使用组合控件,使用ReleativeLayout或者FrameLayout来实现。此篇并不是使用上述方法实现,其核心是继承系统EditText,重写onDraw方法,来改变默认的左上右下的drawable,实现平移到中间位置。这里暂时只实现了drawableLeft的情况,后续将对其进行更新。先来看看实现效果图:
直接来看代码实现
package com.jinlin.custom.iconcenterview; import android.view.View;
import android.widget.EditText;
import android.widget.Toast; public class MainActivity extends BaseActivity{
private EditText et_search; private IconCenterEditText icet_search; @Override
public void iniView() {
setContentView(R.layout.activity_main); et_search = (EditText) findViewById(R.id.et_search);
icet_search = (IconCenterEditText) findViewById(R.id.icet_search); // 实现TextWatcher监听即可
icet_search.setOnSearchClickListener(new IconCenterEditText.OnSearchClickListener() {
@Override
public void onSearchClick(View view) {
Toast.makeText(MainActivity.this, "i'm going to seach", Toast.LENGTH_SHORT).show();
}
});
}
}
这是主Activity的代码,其继承自BaseActivity基类,BaseActivity的实现详细见上篇博文Android点击空白区域,隐藏输入法软键盘只是在isShouldHideKeyboard(View v, MotionEvent event)方法内部增加一行v.clearFocus();代码进行去除焦点处理,其他均一致。
private boolean isShouldHideKeyboard(View v, MotionEvent event) {
if (v != null && (v instanceof EditText)) {
int[] l = {, };
v.getLocationInWindow(l);
int left = l[],
top = l[],
bottom = top + v.getHeight(),
right = left + v.getWidth();
if (event.getX() > left && event.getX() < right
&& event.getY() > top && event.getY() < bottom) {
// 点击EditText的事件,忽略它。
return false;
} else {
v.clearFocus();
return true;
}
}
// 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditText上,和用户用轨迹球选择其他的焦点
return false;
}
接下来是自定义View的代码实现
IconCenterEditText.java
package com.jinlin.custom.iconcenterview; import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText; /**
* Created by J!nl!n on 2015/1/26.
*/
public class IconCenterEditText extends EditText implements View.OnFocusChangeListener, View.OnKeyListener {
private static final String TAG = IconCenterEditText.class.getSimpleName();
/**
* 是否是默认图标再左边的样式
*/
private boolean isLeft = false;
/**
* 是否点击软键盘搜索
*/
private boolean pressSearch = false;
/**
* 软键盘搜索键监听
*/
private OnSearchClickListener listener; public void setOnSearchClickListener(OnSearchClickListener listener) {
this.listener = listener;
} public IconCenterEditText(Context context) {
this(context, null);
init();
} public IconCenterEditText(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.editTextStyle);
init();
} public IconCenterEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
} private void init() {
setOnFocusChangeListener(this);
setOnKeyListener(this);
} @Override
protected void onDraw(Canvas canvas) {
if (isLeft) { // 如果是默认样式,则直接绘制
super.onDraw(canvas);
} else { // 如果不是默认样式,需要将图标绘制在中间
Drawable[] drawables = getCompoundDrawables();
if (drawables != null) {
Drawable drawableLeft = drawables[];
if (drawableLeft != null) {
float textWidth = getPaint().measureText(getHint().toString());
int drawablePadding = getCompoundDrawablePadding();
int drawableWidth = drawableLeft.getIntrinsicWidth();
float bodyWidth = textWidth + drawableWidth + drawablePadding;
canvas.translate((getWidth() - bodyWidth - getPaddingLeft() - getPaddingRight()) / , );
}
}
super.onDraw(canvas);
}
} @Override
public void onFocusChange(View v, boolean hasFocus) {
Log.d(TAG, "onFocusChange execute");
// 恢复EditText默认的样式
if (!pressSearch && TextUtils.isEmpty(getText().toString())) {
isLeft = 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(), );
}
listener.onSearchClick(v);
}
return false;
} public interface OnSearchClickListener {
void onSearchClick(View view);
} }
此View重写onDraw(Canvas canvas)方法,并实现OnFocusChangeListener, OnKeyListener监听接口,在onFocusChange(View v, boolean hasFocus)方法判断是否需要恢复样式,然后在onDraw(Canvas canvas)进行重绘,实现焦点失去和获取时,平移图标和文字。同时还会判断软键盘搜索键的操作进行处理。其核心代码也就是一下这一小段:
Drawable[] drawables = getCompoundDrawables();
if (drawables != null) {
Drawable drawableLeft = drawables[];
if (drawableLeft != null) {
float textWidth = getPaint().measureText(getHint().toString());
int drawablePadding = getCompoundDrawablePadding();
int drawableWidth = drawableLeft.getIntrinsicWidth();
float bodyWidth = textWidth + drawableWidth + drawablePadding;
canvas.translate((getWidth() - bodyWidth - getPaddingLeft() - getPaddingRight()) / , );
}
}
activity_main.xml
<LinearLayout 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:focusableInTouchMode="true"
android:orientation="vertical"
android:padding="@dimen/activity_vertical_margin"
tools:context=".MainActivity"> <TextView
style="@style/StyleTextView"
android:text="默认样式" /> <EditText
android:id="@+id/et_search"
style="@style/StyleEditText" /> <TextView
style="@style/StyleTextView"
android:text="居中样式" /> <com.jinlin.custom.iconcenterview.IconCenterEditText
android:id="@+id/icet_search"
style="@style/StyleEditText" /> </LinearLayout>
bg_search_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white" />
<stroke
android:width="1px"
android:color="@android:color/darker_gray" />
<corners android:radius="3dp" />
</shape>
styles.xml
<resources> <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style> <style name="StyleEditText">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">@drawable/bg_search_bar</item>
<item name="android:drawablePadding">5dp</item>
<item name="android:drawableStart">@mipmap/icon_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:textColorHint">@color/gray_white</item>
<item name="android:textSize">16sp</item>
<item name="android:hint">搜索</item>
</style> <style name="StyleTextView">
<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> </resources>
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="gray_white">#ffcccccc</color>
</resources>
Android 自定义EditText实现类iOS风格搜索框的更多相关文章
- Android 自定义Activity基类与TitleBar
我们在开发App的时候有时候碰到多个界面有一个共同点的时候,比如,都有相同的TitleBar,并且TitleBar可以设置显示的文字.TitleBar上的点击事件,如果给每一个Activity都写一遍 ...
- C++自定义String字符串类,支持子串搜索
C++自定义String字符串类 实现了各种基本操作,包括重载+号实现String的拼接 findSubStr函数,也就是寻找目标串在String中的位置,用到了KMP字符串搜索算法. #includ ...
- Android自定义EditText去除边框并添加下划线
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- Android 自定义EditText实现粘贴,复制,剪切的监听
package com.dwtedx.qq.view; import android.annotation.SuppressLint; import android.content.Context; ...
- ios UISearchBar搜索框的基本使用
摘要: 小巧简洁的原生搜索框,漂亮而易用,如果我们的应用没有特殊需求,都可以使用它. iOS中UISearchBar(搜索框)使用总结 初始化:UISearchBar继承于UIView,我们可以像创建 ...
- iOS之搜索框UISearchController的使用(iOS8.0以后替代UISearchBar+display)
在iOS 8.0以上版本中, 我们可以使用UISearchController来非常方便地在UITableView中添加搜索框. 而在之前版本中, 我们还是必须使用UISearchBar + UISe ...
- Android 自定义Dialog工具类
由于项目的需要,系统的弹出框已经不能满足我们的需求,我们需要各式各样的弹出框,这时就需要我们去自定义弹出框了. 新建布局文件 dialog_layout.xml,将下面内容复制进去 <?xml ...
- Android自定义radiobutton(文字靠左,选框靠右)
<RadioButton android:id="@+id/rb_never" android:layout_width="fill_parent" an ...
- Android 浮动搜索框 searchable 使用(转)。
Android为程序的搜索功能提供了统一的搜索接口,search dialog和search widget,这里介绍search dialog使用.search dialog 只能为于activity ...
随机推荐
- sc.textFile("file:///home/spark/data.txt") Input path does not exist解决方法——submit 加参数 --master local 即可解决
use this val data = sc.textFile("/home/spark/data.txt") this should work and set master as ...
- 89.[NodeJS] Express 模板传值对象app.locals、res.locals
转自:https://blog.csdn.net/Elliott_Yoho/article/details/53537437 locals是Express应用中 Application(app)对象和 ...
- 模仿百度首页“元宵节汤圆”动图(js的定时任务:setInterval)
模仿百度首页“元宵节汤圆”动图:(js的定时任务:setInterval) 原理:需要一张切图,通过不断定位使得图片就像一帧一帧的图片在播放从而形成了动画 效果图: 切图地址: https://ss1 ...
- Spark SQL - 对大规模的结构化数据进行批处理和流式处理
Spark SQL - 对大规模的结构化数据进行批处理和流式处理 大体翻译自:https://jaceklaskowski.gitbooks.io/mastering-apache-spark/con ...
- C#.Net版本自动更新程序及3种策略实现
C#.Net版本自动更新程序及3种策略实现 C/S程序是基于客户端和服务器的,在客户机编译新版本后将文件发布在更新服务器上,然后建立一个XML文件,该文件列举最新程序文件的版本号及最后修改日期.如程序 ...
- JS循环 for while 全局/局部变量 短路
循环语句: For for循环的格式 for(var i = 0; i < 10; i ++){ } for循环的执行顺序: ① ② 若判断为 true 进④ 进③ 进②判断 ……循环 ...
- SpringBoot(五) 番外---Docker
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的 Li ...
- LeetCode hard 668. Kth Smallest Number in Multiplication Table(二分答案,一次过了,好开心,哈哈哈哈)
题目:https://leetcode.com/problems/kth-smallest-number-in-multiplication-table/description/ 668. Kth S ...
- javascript满天小星星
- 监控RMAN操作进度的脚本
REM ------------------------------- REM Script to monitor rman backup/restore operations REM To run ...