【Android自定义控件】仿IOS风格的搜索框
2015-06-09 20:00
429 查看
IOS很多控件的设计都是很值得借鉴的存在,作为移动开发的初学者,我们可以把这种模仿等同于学画、练字时为铸就基础的临摹行为。达者为师,努力学习别人的优点吧。 这里是仿IOS搜索框风格的自定义控件,引用了http://blog.csdn.net/djl461260911/article/details/46401139 这篇博客的代码,加入了清除按钮的功能。吐槽下csdn的编辑器,忽略缩进真的很影响界面效果。
1.控件最终效果图:
1)控件未获得焦点时如下:
2)点击开始编辑时:
注意软件盘右下角的回车键变成了搜索样式,同时搜索图标和hint text已经移动到编辑框最左边
3)焦点离开时:
4)输入内容,删除按钮在最右边出现:
5)删除按钮按下变色,已经按下后清除内容就不一一截图了。
2.代码实现:
1)控件样式文件 style.xml
<resources xmlns:android="http://schemas.android.com/apk/res/android"> <style name="editTextStyle"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:background">@drawable/search_edit_bg</item> <item name="android:drawablePadding">5dp</item> <item name="android:drawableStart">@drawable/search_icon</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">16sp</item> <item name="android:hint">搜索</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> </resources>
2)控件颜色资源文件colors.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="search_edit_gray">#ffcccccc</color> </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
初学者注意这里自定义控件的包名,填写控件实际所在包路径
<RelativeLayout 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: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" /> </RelativeLayout>
2)Activity代码 MainActivity.java
public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
相关文章推荐
- android的环境搭配
- Android_Intent详解
- Android 性能优化之使用MAT分析内存泄露问题
- Android Studio 乱码问题
- Android控件整理
- 关于Android Studio无法更新安装而导致无法启动的问题
- OpenCV+Android开发配置
- 如何进行Android客户端的优化?
- Android(java)学习笔记106-1:类的加载器(反射机制)
- android Graphics:canvas变换与操作
- android分辨率
- android xml 的解析.
- 正则表达式校验 android
- android:inputType参数类型说明
- Android 取view的cache图片
- Android开源框架的SlidingFragment的使用
- Android ViewTreeObserver
- Android开发: 错误整理(不断更新)
- android获得屏幕高度和宽度
- Android studio设置背景图片