最近在项目中有使用到搜索框的地方,由于其样式要求与iOS的UISearchBar的风格一致。默认情况下,搜索图标和文字是居中的,在获取焦点的时候,图标和文字左移。但是在Android是并没有这样的控件(可能见识少,并不知道有)。通常情况下我们使用组合控件,使用ReleativeLayout或者FrameLayout来实现。此篇并不是使用上述方法实现,其核心是继承系统EditText,重写onDraw方法,来改变默认的左上右下的drawable,实现平移到中间位置。这里暂时只实现了drawableLeft的情况,后续将对其进行更新。先来看看实现效果图: 
 

直接来看代码实现

  1. package com.jinlin.custom.iconcenterview;
  2.  
  3. import android.view.View;
  4. import android.widget.EditText;
  5. import android.widget.Toast;
  6.  
  7. public class MainActivity extends BaseActivity{
  8. private EditText et_search;
  9.  
  10. private IconCenterEditText icet_search;
  11.  
  12. @Override
  13. public void iniView() {
  14. setContentView(R.layout.activity_main);
  15.  
  16. et_search = (EditText) findViewById(R.id.et_search);
  17. icet_search = (IconCenterEditText) findViewById(R.id.icet_search);
  18.  
  19. // 实现TextWatcher监听即可
  20. icet_search.setOnSearchClickListener(new IconCenterEditText.OnSearchClickListener() {
  21. @Override
  22. public void onSearchClick(View view) {
  23. Toast.makeText(MainActivity.this, "i'm going to seach", Toast.LENGTH_SHORT).show();
  24. }
  25. });
  26. }
  27. }
这是主Activity的代码,其继承自BaseActivity基类,BaseActivity的实现详细见上篇博文Android点击空白区域,隐藏输入法软键盘只是在isShouldHideKeyboard(View v, MotionEvent event)方法内部增加一行v.clearFocus();代码进行去除焦点处理,其他均一致。
  1. private boolean isShouldHideKeyboard(View v, MotionEvent event) {
  2. if (v != null && (v instanceof EditText)) {
  3. int[] l = {, };
  4. v.getLocationInWindow(l);
  5. int left = l[],
  6. top = l[],
  7. bottom = top + v.getHeight(),
  8. right = left + v.getWidth();
  9. if (event.getX() > left && event.getX() < right
  10. && event.getY() > top && event.getY() < bottom) {
  11. // 点击EditText的事件,忽略它。
  12. return false;
  13. } else {
  14. v.clearFocus();
  15. return true;
  16. }
  17. }
  18. // 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditText上,和用户用轨迹球选择其他的焦点
  19. return false;
  20. }

接下来是自定义View的代码实现


IconCenterEditText.java

  1. package com.jinlin.custom.iconcenterview;
  2.  
  3. import android.content.Context;
  4. import android.graphics.Canvas;
  5. import android.graphics.drawable.Drawable;
  6. import android.text.TextUtils;
  7. import android.util.AttributeSet;
  8. import android.util.Log;
  9. import android.view.KeyEvent;
  10. import android.view.View;
  11. import android.view.inputmethod.InputMethodManager;
  12. import android.widget.EditText;
  13.  
  14. /**
  15. * Created by J!nl!n on 2015/1/26.
  16. */
  17. public class IconCenterEditText extends EditText implements View.OnFocusChangeListener, View.OnKeyListener {
  18. private static final String TAG = IconCenterEditText.class.getSimpleName();
  19. /**
  20. * 是否是默认图标再左边的样式
  21. */
  22. private boolean isLeft = false;
  23. /**
  24. * 是否点击软键盘搜索
  25. */
  26. private boolean pressSearch = false;
  27. /**
  28. * 软键盘搜索键监听
  29. */
  30. private OnSearchClickListener listener;
  31.  
  32. public void setOnSearchClickListener(OnSearchClickListener listener) {
  33. this.listener = listener;
  34. }
  35.  
  36. public IconCenterEditText(Context context) {
  37. this(context, null);
  38. init();
  39. }
  40.  
  41. public IconCenterEditText(Context context, AttributeSet attrs) {
  42. this(context, attrs, android.R.attr.editTextStyle);
  43. init();
  44. }
  45.  
  46. public IconCenterEditText(Context context, AttributeSet attrs, int defStyleAttr) {
  47. super(context, attrs, defStyleAttr);
  48. init();
  49. }
  50.  
  51. private void init() {
  52. setOnFocusChangeListener(this);
  53. setOnKeyListener(this);
  54. }
  55.  
  56. @Override
  57. protected void onDraw(Canvas canvas) {
  58. if (isLeft) { // 如果是默认样式,则直接绘制
  59. super.onDraw(canvas);
  60. } else { // 如果不是默认样式,需要将图标绘制在中间
  61. Drawable[] drawables = getCompoundDrawables();
  62. if (drawables != null) {
  63. Drawable drawableLeft = drawables[];
  64. if (drawableLeft != null) {
  65. float textWidth = getPaint().measureText(getHint().toString());
  66. int drawablePadding = getCompoundDrawablePadding();
  67. int drawableWidth = drawableLeft.getIntrinsicWidth();
  68. float bodyWidth = textWidth + drawableWidth + drawablePadding;
  69. canvas.translate((getWidth() - bodyWidth - getPaddingLeft() - getPaddingRight()) / , );
  70. }
  71. }
  72. super.onDraw(canvas);
  73. }
  74. }
  75.  
  76. @Override
  77. public void onFocusChange(View v, boolean hasFocus) {
  78. Log.d(TAG, "onFocusChange execute");
  79. // 恢复EditText默认的样式
  80. if (!pressSearch && TextUtils.isEmpty(getText().toString())) {
  81. isLeft = hasFocus;
  82. }
  83. }
  84.  
  85. @Override
  86. public boolean onKey(View v, int keyCode, KeyEvent event) {
  87. pressSearch = (keyCode == KeyEvent.KEYCODE_ENTER);
  88. if (pressSearch && listener != null) {
  89. /*隐藏软键盘*/
  90. InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
  91. if (imm.isActive()) {
  92. imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), );
  93. }
  94. listener.onSearchClick(v);
  95. }
  96. return false;
  97. }
  98.  
  99. public interface OnSearchClickListener {
  100. void onSearchClick(View view);
  101. }
  102.  
  103. }

此View重写onDraw(Canvas canvas)方法,并实现OnFocusChangeListener, OnKeyListener监听接口,在onFocusChange(View v, boolean hasFocus)方法判断是否需要恢复样式,然后在onDraw(Canvas canvas)进行重绘,实现焦点失去和获取时,平移图标和文字。同时还会判断软键盘搜索键的操作进行处理。其核心代码也就是一下这一小段:

  1. Drawable[] drawables = getCompoundDrawables();
  2. if (drawables != null) {
  3. Drawable drawableLeft = drawables[];
  4. if (drawableLeft != null) {
  5. float textWidth = getPaint().measureText(getHint().toString());
  6. int drawablePadding = getCompoundDrawablePadding();
  7. int drawableWidth = drawableLeft.getIntrinsicWidth();
  8. float bodyWidth = textWidth + drawableWidth + drawablePadding;
  9. canvas.translate((getWidth() - bodyWidth - getPaddingLeft() - getPaddingRight()) / , );
  10. }
  11. }

activity_main.xml

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:focusableInTouchMode="true"
  6. android:orientation="vertical"
  7. android:padding="@dimen/activity_vertical_margin"
  8. tools:context=".MainActivity">
  9.  
  10. <TextView
  11. style="@style/StyleTextView"
  12. android:text="默认样式" />
  13.  
  14. <EditText
  15. android:id="@+id/et_search"
  16. style="@style/StyleEditText" />
  17.  
  18. <TextView
  19. style="@style/StyleTextView"
  20. android:text="居中样式" />
  21.  
  22. <com.jinlin.custom.iconcenterview.IconCenterEditText
  23. android:id="@+id/icet_search"
  24. style="@style/StyleEditText" />
  25.  
  26. </LinearLayout>

bg_search_bar.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android">
  3. <solid android:color="@android:color/white" />
  4. <stroke
  5. android:width="1px"
  6. android:color="@android:color/darker_gray" />
  7. <corners android:radius="3dp" />
  8. </shape>

styles.xml

  1. <resources>
  2.  
  3. <!-- Base application theme. -->
  4. <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  5. <!-- Customize your theme here. -->
  6. </style>
  7.  
  8. <style name="StyleEditText">
  9. <item name="android:layout_width">match_parent</item>
  10. <item name="android:layout_height">wrap_content</item>
  11. <item name="android:background">@drawable/bg_search_bar</item>
  12. <item name="android:drawablePadding">5dp</item>
  13. <item name="android:drawableStart">@mipmap/icon_search</item>
  14. <item name="android:gravity">center_vertical</item>
  15. <item name="android:imeOptions">actionSearch</item>
  16. <item name="android:padding">5dp</item>
  17. <item name="android:singleLine">true</item>
  18. <item name="android:textColorHint">@color/gray_white</item>
  19. <item name="android:textSize">16sp</item>
  20. <item name="android:hint">搜索</item>
  21. </style>
  22.  
  23. <style name="StyleTextView">
  24. <item name="android:layout_width">match_parent</item>
  25. <item name="android:layout_height">40dp</item>
  26. <item name="android:gravity">center</item>
  27. <item name="android:textSize">20sp</item>
  28. </style>
  29.  
  30. </resources>

colors.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <color name="gray_white">#ffcccccc</color>
  4. </resources>

示例代码下载

Android 自定义EditText实现类iOS风格搜索框的更多相关文章

  1. Android 自定义Activity基类与TitleBar

    我们在开发App的时候有时候碰到多个界面有一个共同点的时候,比如,都有相同的TitleBar,并且TitleBar可以设置显示的文字.TitleBar上的点击事件,如果给每一个Activity都写一遍 ...

  2. C++自定义String字符串类,支持子串搜索

    C++自定义String字符串类 实现了各种基本操作,包括重载+号实现String的拼接 findSubStr函数,也就是寻找目标串在String中的位置,用到了KMP字符串搜索算法. #includ ...

  3. Android自定义EditText去除边框并添加下划线

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  4. Android 自定义EditText实现粘贴,复制,剪切的监听

    package com.dwtedx.qq.view; import android.annotation.SuppressLint; import android.content.Context; ...

  5. ios UISearchBar搜索框的基本使用

    摘要: 小巧简洁的原生搜索框,漂亮而易用,如果我们的应用没有特殊需求,都可以使用它. iOS中UISearchBar(搜索框)使用总结 初始化:UISearchBar继承于UIView,我们可以像创建 ...

  6. iOS之搜索框UISearchController的使用(iOS8.0以后替代UISearchBar+display)

    在iOS 8.0以上版本中, 我们可以使用UISearchController来非常方便地在UITableView中添加搜索框. 而在之前版本中, 我们还是必须使用UISearchBar + UISe ...

  7. Android 自定义Dialog工具类

    由于项目的需要,系统的弹出框已经不能满足我们的需求,我们需要各式各样的弹出框,这时就需要我们去自定义弹出框了. 新建布局文件 dialog_layout.xml,将下面内容复制进去 <?xml ...

  8. Android自定义radiobutton(文字靠左,选框靠右)

    <RadioButton android:id="@+id/rb_never" android:layout_width="fill_parent" an ...

  9. Android 浮动搜索框 searchable 使用(转)。

    Android为程序的搜索功能提供了统一的搜索接口,search dialog和search widget,这里介绍search dialog使用.search dialog 只能为于activity ...

随机推荐

  1. centos6高速部署java应用

    眼下提供IDC服务的厂商真的是五花八门,可是更正服务到位的却为数不多,搞得比較好的应该是阿里云.天成.51idc,出于时间考虑还是建议选用windows,至少安装开发环境会方便得多,不会耗费太长时间. ...

  2. kentico api

    http://devnet.kentico.com/docs/10_0/api/html/R_Project_Kentico_API.htm ScriptHelper.RegisterClientSc ...

  3. DB-MySQL:目录

    ylbtech-DB-MySQL:目录 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   作者:ylbtech出处:http://ylbt ...

  4. IE6 css fixed

    .fixed-top{position:fixed;bottom:auto;top:0px;} .fixed-bottom{position:fixed;bottom:0px;top:auto;} . ...

  5. python下载网页转化成pdf

    最近在学习一个网站补充一下cg基础.但是前几天网站突然访问不了了,同学推荐了waybackmachine这个网站,它定期的对网络上的页面进行缓存,但是好多图片刷不出来,很憋屈.于是网站恢复访问后决定把 ...

  6. ccs元素分类 gcelaor

    ccs元素的分类与特点 内联元素特点: 1.和其他元素都在一行上: 2.元素的高度.宽度及顶部和底部边距不可设置: 3.元素的宽度就是它包含的文字或图片的宽度,不可改变. inline-block 元 ...

  7. 在js中关于同名变量和函数的地位争夺问题

    先上一段让大家比较蒙圈的代码,接下来再慢慢讲解 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  8. 【模板】多项式乘法 NTT

    相对来说是封装好的,可以当模板来用. #include <bits/stdc++.h> #define maxn 5000000 #define G 3 #define ll long l ...

  9. Mateclass

    Mateclass 一切皆对象: Eg: class Foo: pass f=Foo() In [60]: print(type(f)) <class '__main__.Foo'> In ...

  10. tinymce原装插件源码分析(六)-preview

    priview 此插件文件结构比较简单,按钮注册.editor.windowManager.open.窗口出现之前的渲染数据的准备.页面代码的准备. 注意: 1.preview的默认宽高设置: 2.c ...