前言
做了一個心跳的效果動畫,名為HeartBeatView,不靠Animation或Animator即可達到的客製化視圖,當中還包括可以直接在xml設定其速度和跳動幅度,效果如下:
這邊我歸納幾個實現的步驟:
- 定義HeartBeatView的屬性(declare-styleaqle)
- 實作HeartBeatView
- 初始化資源檔內容與Paint物件
- 繪製愛心
- 繪製跳動與幅度
定義HeartBeatView的屬性(declare-styleaqle)
<resources>
<declare-styleable name="HeartBeatImageView">
<attr name="animMoveFactor" format="float" />
<attr name="animCounter" format="integer" />
<attr name="heartColor" format="color" />
</declare-styleable>
</resources>
實作HeartBeatView
public class HeartBeatImageView extends View {
}
初始化資源檔內容與Paint物件
這邊則是在呼叫HeartBeatView的建構子時,順便將我們在xml裡設定的屬性給帶進來(要是你有使用到的話!),可以透過AttributeSet這個參數獲取其在xml設定的內容,程式碼如下。
public HeartBeatImageView(Context context) {
this(context, null);
}
public HeartBeatImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HeartBeatImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.initParams(context, attrs);
this.initPaint();
}
private void initParams(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HeartBeatImageView);
this.animMoveFactor = typedArray.getFloat(R.styleable.HeartBeatImageView_animMoveFactor, DEFAUT_ANIM_MOVE_FACTOR);
this.animCounter = typedArray.getInt(R.styleable.HeartBeatImageView_animCounter, DEFAULT_ANIM_COUNTER);
this.heartColor = typedArray.getColor(R.styleable.HeartBeatImageView_heartColor, DEFAULT_COLOR);
typedArray.recycle();
}
private void initPaint() {
this.redCirclePaint = new Paint();
this.redCirclePaint.setAntiAlias(true);
this.redCirclePaint.setColor(this.heartColor);
}
繪製愛心
先繪製一個正方形,再加上兩個圓形,並將之轉成45度即可,程式碼如下。
int centerX = canvas.getWidth() / 2;
int centerY = canvas.getHeight() / 2;
float radius = this.getCircleRadius(canvas.getWidth() / 6, this.animCounter, this.animMoveFactor);
canvas.rotate(45, centerX, centerY);
canvas.drawRect(centerX - radius, centerY - radius, centerX + radius, centerY + radius, this.redCirclePaint);
canvas.drawCircle(centerX - radius, centerY, radius, this.redCirclePaint);
canvas.drawCircle(centerX, centerY - radius, radius, this.redCirclePaint);
繪製跳動與幅度
這邊是透過animCounter與step這兩個參數來控制增減,並期重新更新radius數值,程式碼如下。
private void drawHeart(Canvas canvas) {
this.animCounter = this.animCounter + this.step;
int centerX = canvas.getWidth() / 2;
int centerY = canvas.getHeight() / 2;
float radius = this.getCircleRadius(canvas.getWidth() / 6, this.animCounter, this.animMoveFactor);
canvas.rotate(45, centerX, centerY);
canvas.drawRect(centerX - radius, centerY - radius, centerX + radius, centerY + radius, this.redCirclePaint);
canvas.drawCircle(centerX - radius, centerY, radius, this.redCirclePaint);
canvas.drawCircle(centerX, centerY - radius, radius, this.redCirclePaint);
if (this.animCounter >= ANIM_COUNTER_MAX) {
this.step = -1;
} else if (this.animCounter <= 0) {
this.step = 1;
}
}
private float getCircleRadius(int radius, int animCounter, double animFactor) {
return (float) (radius + animCounter * animFactor);
}