转载请注明出处,谢谢~~
控件还有很大的优化和提升控件,欢迎star和pr~!
之前做的一个控件,一直没有写一篇相关的博客,今天打算提笔,写下来。不多说,一贯风格,有图有真相。
控件之始,当然是一些初始化的操作
private void init(){
setWillNotDraw(false);
paint = new Paint();
paint.setFlags(Paint.ANTI_ALIAS_FLAG);//消除锯齿
tPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
tPaint.setTextSize(dp2px(hintTextSize));
super.setPadding((int)dp2px(paddingLeft), (int)dp2px(paddingTop),
(int)dp2px(paddingRight), (int)dp2px(paddingBottom) );
mainTextSize = getTextSize();
}
这里主要是对画笔和一些padding的设定
然后在onMeasure里记录了宽高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getWidth();
height = getHeight();
}
之后主要的操作就是在OnDraw()里,我们看下代码:
@Override
protected void onDraw(Canvas canvas) {
if (!hasFocus()) {
drawDefaultLineAndText(canvas);
}else {
animateLableOut(canvas);
}
if(ratioOut >=0 && ratioOut <=1 || ratioIn >=0 && ratioIn <= 1) {
invalidate();
}
super.onDraw(canvas);
}
这里首先用hasFocus()方法来判断焦点,根据不同的焦点执行不同的绘制逻辑,然后用ratioOut和ratioIn这两个参数控制重绘时机。我们首先看下当没有获取焦点时的绘制逻辑:
private void drawDefaultLineAndText(Canvas canvas) {
ratioOut = 0;
paint.setColor(defaultLineColor);
// tPaint.setColor(defaultTextColor);
canvas.drawRect(dp2px(lineLeft), height-dp2px(lineHeight), width-dp2px(lineLeft), height, paint);
ratioIn -= INCREMENT;
if (ratioIn <= 0) {
ratioIn = 0;
ratioOut = ratioIn;
}
paint.setColor(endLineColor);
if (ratioIn == 0) {
canvas.drawRect(dp2px(lineLeft), height-dp2px(lineHeight), dp2px(lineLeft), height, paint);//解决一些手机上会绘制0-left的横线
}else {
canvas.drawRect(dp2px(lineLeft), height-dp2px(lineHeight), ratioIn*((float)(width-dp2px(lineLeft))), height, paint);
}
if (TextUtils.isEmpty(this.getText().toString().trim())) {
if (isLableOut) {
if (ratioIn == 0) {
tPaint.setColor(defaultTextColor);
canvas.drawText(hintText, dp2px(paddingLeft), (float)(height-dp2px(textMarginTop)), tPaint);
}else {
tPaint.setColor(endTextColor);
canvas.drawText(hintText, dp2px(paddingLeft), (float)(height-dp2px(textMarginTop))-(ratioIn*(mainTextSize + dp2px(10f))), tPaint);
}
}else{
if (ratioIn == 0) {
tPaint.setColor(defaultTextColor);
canvas.drawText(hintText, dp2px(paddingLeft), (float)(height-dp2px(textMarginTop)), tPaint);
}
}
}else{
if (ratioIn == 0) {
tPaint.setColor(defaultTextColor);
}else {
tPaint.setColor(endTextColor);
}
canvas.drawText(hintText, dp2px(paddingLeft), (height-(cursorSize + dp2px(textMarginTop))), tPaint);
}
}
大致讲下这里,具体的思路可以看下代码,全部代码会在文章最后给出。
首先,ratioOut和ratioIn是控制绘制的机制,这两个是一直在变的。首先在没有获取焦点的时候,会绘制一条默认的线和提示文字,提示文字在线的左边,但是如果EditText里面有用户输入的文字的话,提示文字就不会在线上绘制,就会在EditText的上方绘制。
然后贴下当获取焦点时绘制的代码:
private void animateLableOut(Canvas canvas) {
ratioOut += INCREMENT;
paint.setColor(defaultLineColor);
canvas.drawRect(dp2px(lineLeft), height-dp2px(lineHeight), width-dp2px(lineLeft), height, paint);
paint.setColor(endLineColor);
tPaint.setColor(endTextColor);
if (ratioOut >= 1) {
ratioOut = 1;
ratioIn = ratioOut;
}
canvas.drawRect(dp2px(lineLeft), height-dp2px(lineHeight), ratioOut*((float)(width-dp2px(lineLeft))), height, paint);
if (TextUtils.isEmpty(this.getText().toString().trim())) {
// canvas.drawText(hintText, dp2px(paddingLeft), (float)(height-dp2px(textMarginTop))-(ratioOut*(mainTextSize + dp2px(10f))), tPaint);
canvas.drawText(hintText, dp2px(paddingLeft), (float)(height-dp2px(textMarginTop))-(ratioOut*(cursorSize)), tPaint);
}else {
// canvas.drawText(hintText, dp2px(paddingLeft), (height-(mainTextSize + dp2px(22.5f))), tPaint);
canvas.drawText(hintText, dp2px(paddingLeft), (height-(cursorSize + dp2px(textMarginTop))), tPaint);
// ratio = 1.1f;//阻止重绘
}
isLableOut = true;
}
当获取焦点时,会对线和提示文字做一个重绘操作,当然,也要判断当前EditText是否有文字输入。
总体的逻辑大致如此,具体的细节看代码即可。希望这篇文章能对大家有些帮助。
控件还有很大的优化和提升控件,欢迎star和pr~!
代码地址:eclipse版本github代码下载地址
Android studio 版本github代码下载地址