效果
前言
用Digest的时候发现它的打开效果很赞。类似的还有格瓦拉电影。想要自己实现一下。没有找到参考。自己现实的性能很差,内存、CPU消耗的都很多。如果有更好实现思路,请赐教。
原理
关键在于创建镂空的Bitmap。创建镂空的Bitmap的关键在于设置Xfermode,处理好src和dst的关系。之后便是不断的更新Bitmap,不断的重绘。
源码
package com.example.myronlg.myapplication;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
/**
* Created by myron.lg on 2015/6/24.
*/
public class OpenView extends View {
private Bitmap bgBitmap;
private Canvas bgCanvas;
private Paint paint;
private Paint clearPaint;
private long duration = 800;
private long startTimeMillis;
private float cx;
private float cy;
private double maxRadius;
private Interpolator interpolator;
private boolean opening;
public OpenView(Context context) {
super(context);
}
public OpenView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public OpenView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bgBitmap, 0, 0, paint);
if (opening) {
updateBgBitmap();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
init();
}
private void init() {
final int width = getMeasuredWidth();
final int height = getMeasuredHeight();
bgBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bgCanvas = new Canvas(bgBitmap);
bgCanvas.drawColor(Color.parseColor("#ff5722"));
paint = new Paint();
clearPaint = new Paint();
clearPaint.setAntiAlias(true);
clearPaint.setDither(true);
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
cx = width * 0.5F;
cy = height * 0.5F;
maxRadius = Math.ceil(Math.sqrt(width * width + height * height) * 0.5F);
interpolator = new AccelerateInterpolator(2.0F);
}
private void updateBgBitmap() {
long curTimeMillis = System.currentTimeMillis();
long animTime = curTimeMillis - startTimeMillis;
float animFraction = animTime*1.0F / duration;
if (animFraction >= 1){
opening = false;
}
float interpolatedFraction = interpolator.getInterpolation(animFraction);
float radius = (float) (maxRadius * interpolatedFraction);
bgCanvas.drawCircle(cx, cy, radius, clearPaint);
invalidate();
}
public void open() {
init();
opening = true;
startTimeMillis = System.currentTimeMillis();
updateBgBitmap();
}
}