Android (自定义控件) 初次尝试:带提示框的EditText--PopEditText
2016-02-22 09:45
176 查看
一、前言
从2015年7月份毕业到现在,工作已经有半年时间了。虽然不再去读书写公式,但是自己的学习旅程并没有结束。在这新年伊始,我将以全新的方式记录自己学习成长的点滴。二、PopEditText将要实现的效果
1.文字描述
在我们使用输入框传入文字数据的时候,可能需要对输入的文字加以规则限制,比如:开头字母加7-10位数字字母区分大小写。一般我们会将提示的规则写入hint或者在输入框下排加一行醒目的提示text。PopEditText将要实现的效果就是在输入框获取焦点的时候,在其上方显示一个小的气泡,气泡中有我们想要显示的提示规则;在其失去焦点的时候,让小气泡消失。可配置选项:可以设置气泡的颜色,可以设置气泡中文字的颜色,可以设置气泡中文字的大小,可以设置气泡中的文字内容。
2.gif图展示效果
三、实现思路
1.首先具有EditText的全部属性:让PopEditText继承EditText2.当PopEditText焦点改变的时候设置pop气泡的显示与消失:重写onFocusedChanged方法
3.气泡显示时使用canvas.draw方法绘制自己需要的图形以及文字:重写onDraw方法
4.测量新控件的宽高:重写onMeasure方法
备注:当然,上面的思路是在我成功做出自己想要的效果之后总结出来的。在实现效果之前,我查阅并尝试学习了很多资料,包括很多前辈的博客。必然的,在这过程中遇到过很多的问题。最开始成功的显示了我想要的pop之后却发现我的控件的边界覆盖了我的pop,尝试了很多方法之后未果,暂时中断了编写。之后学习的过程中偶然的发现一篇资料中说到:重写onMeasure来测量控件的尺寸,这让我豁然开朗。再次投入编写中,运用学到的知识终于成功的显示了我的PopTextView。这同时也让我意识到了问题:在尝试进阶技能之前,应该先做好基础知识的学习,比如view的绘制原理,view的测量等等问题。
四、关键代码编写
1.PopEditText的焦点改变
@Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { super.onFocusChanged(focused, direction, previouslyFocusedRect); if (focused) { // 显示气泡 if (popPaintAlpha <= 255) { Thread showPopThread = new Thread(new ShowPop()); showPopThread.start(); } } else { // 气泡消失 if (popPaintAlpha >= 0) { Thread dissPopThread = new Thread(new DissMissPop()); dissPopThread.start(); } } }
2.绘制pop气泡及文字
@Override protected void onDraw(Canvas canvas) { initSanJiaoPath(); popRectF.set(5+PADDINTLEFT, 25, popWidth-10+PADDINTLEFT, popHeight-10); // 画圆角矩形 canvas.drawRoundRect(popRectF, 40, 40, popPaint); // 画直角三角形 canvas.drawPath(sanJiaoPath, popPaint); // 显示文字 canvas.drawText(ruleText, 50+PADDINTLEFT, popHeight - getStringBlank(ruleTextPaint, ruleText) - 25, ruleTextPaint); super.onDraw(canvas); }
3.测量新控件的尺寸
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); blankWidth = getMeasuredWidth();//获取width原值 blankHeight = getMeasuredHeight();//获取height原值 setMeasuredDimension(blankWidth, blankHeight + popHeight);//重设width与height }
4.动态绘制pop
在这个追求视觉盛宴的时代,有很多追求酷炫的朋友会觉得,为自己的控件加入动画效果会更显得有逼格,我也是这样认为的。如何实现这个功能呢,下面是我实现的思路。通过不间断的改变Paint的Alpha透明值来改变画面
/** * 显示pop */ class ShowPop implements Runnable { @Override public void run() { for (int i = 0; i < 51; i++) { try { if (popPaintAlpha < 255) { popPaintAlpha=popPaintAlpha+5; } if (ruleTextPaintAlpha < 255) { ruleTextPaintAlpha=ruleTextPaintAlpha+5; } initPopPaint(); initRuleTextPaint(); postInvalidate(); Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * 消除pop * 通过控制Paint的Alpha值来控制pop的显示与隐藏 */ class DissMissPop implements Runnable { @Override public void run() { for (int i = 0; i < 51; i++) { try { if (popPaintAlpha > 0) { popPaintAlpha=popPaintAlpha-5; } if (ruleTextPaintAlpha > 0) { ruleTextPaintAlpha=popPaintAlpha-5; } initPopPaint(); initRuleTextPaint(); postInvalidate(); Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } } }
源码里面可以看出来我使用的是用子线程来实现连续的变化,然后调用postInvaliDate来刷新界面(Invalidate不能在这里面使用,具体原因我还真说不明白)。为什么这样做呢,在Android 5.1之后系统button都有了波纹效果,查看了源码,发现它的实现方式也是线程控制的,照葫芦画瓢,我也就这样去实现了。
5.可设置的属性
/** * 设置提示文字的大小 * * @param ruleTextSize */ public void setRuleTextSize(float ruleTextSize) { this.ruleTextSize = ruleTextSize; initRuleTextPaint(); invalidate(); } public int getRuleTextColor() { return ruleTextColor; } /** * 设置提示的字体颜色 * * @param ruleTextColor */ public void setRuleTextColor(int ruleTextColor) { this.ruleTextColor = ruleTextColor; initRuleTextPaint(); invalidate(); } public String getRuleText() { return ruleText; } /** * 设置提示的文字的内容 * * @param ruleText */ public void setRuleText(String ruleText) { this.ruleText = ruleText; initRuleTextPaint(); invalidate(); } public int getPopColor() { return popColor; } /** * 设置提示框的颜色 * * @param popColor */ public void setPopColor(int popColor) { this.popColor = popColor; initRuleTextPaint(); invalidate(); }
在设置过这些属性之后,一定要重新加载一下画笔,并且invalidate刷新画面(invalidate不能在线程中使用,在这里是可以使用的)
五、控件的使用
在xml布局文件中可以直接使用<com.zhang.diyview.PopEditText android:id="@+id/met_test" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="5585" android:textColor="@color/blue2" android:textSize="28sp" android:background="@null" />
在Activity中我们还需要几行代码设置一下pop样式
metFirstTest=(PopEditText)findViewById(R.id.met_test); metFirstTest.setPopColor(Color.WHITE); metFirstTest.setRuleTextColor(Color.BLACK); metFirstTest.setRuleText("tips"); metFirstTest.setRuleTextSize(64);
直接运行就可以看到效果
六、总结(存在的问题以及优化方案)
存在的问题1.只是单纯的为了实现功能,没有考虑到它的可维护性,可扩展性,等等问题
2.动态效果单一,且有些时候会出现卡顿
3.输入框中的文字,强制设定gravity:bottom,如果设置为其他属性,会出现文字覆盖pop的问题
4.没有给pop中的文字设置自动换行
优化与改进
1.进一步学习设计模式,争取构造出更漂亮的代码
2.放开动态效果的接口,争取做到可以自定义配置动态效果
3.丰富动态效果,优化实现方式
最后放上源码地址:源码不要钱
相关文章推荐
- Android TreeView效果实现方法(附demo源码下载)
- Android开发艺术探索学习笔记(三)
- android 防止重复点击
- Android 6.0 运行时权限处理完全解析
- 利用 Android Gradle 瘦身 apk
- Android Studio debug使用release的签名
- Android Studio 配置和技巧
- 记Android富文本编辑器那些踩过的坑(上)
- Android,iOS打开手机QQ与指定用户聊天界面
- Android开发中关于获取当前Activity的一些思考
- Android,iOS打开手机QQ与指定用户聊天界面
- Android中用代码安装APK
- Android消息推送
- 强制Volley缓存图片到磁盘
- Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚
- 【Android】11.6 Fragments基本用法示例
- 【Android】11.5 创建和管理Fragments
- 按首字母分类并排序显示的列表(二)--给BaseExpandableListAdapter提供数据的HashList
- 【Android】11.4 Fragment及其生命周期
- ViewPager详解