您的位置:首页 > 移动开发 > Android开发

Android (自定义控件) 初次尝试:带提示框的EditText--PopEditText

2016-02-22 09:45 176 查看

一、前言

从2015年7月份毕业到现在,工作已经有半年时间了。虽然不再去读书写公式,但是自己的学习旅程并没有结束。在这新年伊始,我将以全新的方式记录自己学习成长的点滴。

二、PopEditText将要实现的效果

1.文字描述

在我们使用输入框传入文字数据的时候,可能需要对输入的文字加以规则限制,比如:开头字母加7-10位数字字母区分大小写。一般我们会将提示的规则写入hint或者在输入框下排加一行醒目的提示text。PopEditText将要实现的效果就是在输入框获取焦点的时候,在其上方显示一个小的气泡,气泡中有我们想要显示的提示规则;在其失去焦点的时候,让小气泡消失。

可配置选项:可以设置气泡的颜色,可以设置气泡中文字的颜色,可以设置气泡中文字的大小,可以设置气泡中的文字内容。

2.gif图展示效果



三、实现思路

1.首先具有EditText的全部属性:让PopEditText继承EditText

2.当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.丰富动态效果,优化实现方式

最后放上源码地址:源码不要钱
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: