近期有一个需求,需要做一个送花的动画,初始点击一朵花就出现一个动画,再点一次又出现一次,就算是连击,点击多少次就出现多少次,但是感觉效果太丑,因此将连击合并在一起只更改数字。
效果
这里先做一个demo,效果就是demo运行中截取的,大致效果如下:
多次连击只需要更新数字,不在需要重新出现动画,只有当动画执行完毕后,才出现下一次动画。
实现
这里主要包括几个元素,一个描述文本,一个缩放的View,再加一个背景效果。描述文本设置一个图标。缩放文本有一个文字边框效果。
缩放View
首先来实现一个缩放的View,初始首先想到的是采用自定义View,自己draw一个文本,先draw外层文本,再draw内层文本。代码如下:
package com.demo.demo.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import com.demo.demo.R;
public class ScaleTextView extends View {
private Paint paint;
private int outColor;
private int innerColor;
private boolean drawBorder;
private float scale;
private String text;
private int dimensionPixelSize;
public ScaleTextView(Context context) {
super(context);
init(context, null);
}
public ScaleTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ScaleTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ScaleTextView);
outColor = array.getColor(R.styleable.ScaleTextView_o_color, getResources().getColor(R.color.colorPrimary));
innerColor = array.getColor(R.styleable.ScaleTextView_i_color, getResources().getColor(R.color.colorAccent));
drawBorder = array.getBoolean(R.styleable.ScaleTextView_is_border, false);
dimensionPixelSize = array.getDimensionPixelSize(R.styleable.ScaleTextView_text_size, getResources()
.getDimensionPixelSize(R.dimen.inSize));
array.recycle();
outPaint();
}
private void outPaint() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(dimensionPixelSize);
}
public float getScale() {
return scale;
}
public void setScale(float scale) {
this.scale = scale;
setScaleX(scale);
setScaleY(scale);
}
public void setText(String text) {
this.text = text;
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(dimensionPixelSize * 4, dimensionPixelSize);
}
@Override
protected void onDraw(Canvas canvas) {
if (TextUtils.isEmpty(text)) {
return;
}
if (drawBorder) {
paint.setColor(outColor);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawText(text, 0, dimensionPixelSize, paint);
}
paint.setColor(innerColor);
paint.setStrokeWidth(0);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawText(text, 0, dimensionPixelSize, paint);
}
}
这里先不用管scale参数,这是为后面的属性动画设置的属性进行缩放动画。我们在onMeasure强制设置宽高,高就是文本的大小,宽就是最大文本的大小。
当有文本设置时,调用invalidate进行重绘,在onDraw中绘制文本,先绘制外层,再绘制内存,分别用不同的颜色。在构造的时候解析attr,attr如下:
<declare-styleable name="ScaleTextView">
<attr name="o_color" format="reference|color"></attr>
<attr name="i_color" format="reference|color"></attr>
<attr name="is_border" format="boolean"></attr>
<attr name="text_size" format="dimension"></attr>
</declare-styleable>
上面我们采用了自定义View来展示,需要我们传入文本大小,文本颜色,我在网上看到有人用TextView的方式实现了同样的效果,这里采用自定义TextView来实现同样的效果,代码如下:
package com.demo.demo.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.widget.TextView;
import com.demo.demo.R;
import java.lang.reflect.Field;
public