/** * Copyright © 2013 CVTE. All Rights Reserved. */ package external.mesh; import com.aiyou.AiYouApplication; import com.aiyou.utils.AiYouManager; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.View; import android.view.animation.Animation; import android.view.animation.Interpolator; import android.view.animation.Transformation; public class BitmapMesh { /** * 对图像进行mesh动画的视图 * * @author sollian */ public static class MeshView extends View { private static final int WIDTH = 40; private static final int HEIGHT = 40; private Bitmap mBitmap = null; private boolean mIsDebug = false; private Paint mPaint = null; private float[] mInhalePoint = null; private InhaleMesh mInhaleMesh = null; public MeshView(Context context, Bitmap bmp) { super(context); init(bmp); } public MeshView(Context context, AttributeSet attrs, Bitmap bmp) { super(context, attrs); init(bmp); } private void init(Bitmap bmp) { setFocusable(true); Matrix matrix = new Matrix(); // 旋转180度 matrix.postRotate(180); int width = bmp.getWidth(); int height = bmp.getHeight(); mBitmap = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix, true); mPaint = new Paint(); mInhalePoint = new float[] { 0, 0 }; mInhaleMesh = new InhaleMesh(WIDTH, HEIGHT); mInhaleMesh.setBitmapSize(mBitmap.getWidth(), mBitmap.getHeight()); } public void setBitmap(Bitmap bmp) { Matrix matrix = new Matrix(); matrix.postRotate(180); /* 翻转180度 */ int width = bmp.getWidth(); int height = bmp.getHeight(); mBitmap = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix, true); } public void setIsDebug(boolean isDebug) { mIsDebug = isDebug; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); float bitmapWidth = mBitmap.getWidth(); float bitmapHeight = mBitmap.getHeight(); buildPaths(AiYouManager.getInstance(AiYouApplication.getInstance()).dip2px(20), h - AiYouManager.getInstance(AiYouApplication.getInstance()).dip2px(25)); buildMesh(bitmapWidth, bitmapHeight); } public boolean startAnimation(boolean reverse) { Animation anim = this.getAnimation(); if (null != anim && !anim.hasEnded()) { return false; } PathAnimation animation = new PathAnimation(0, HEIGHT + 1, reverse, new PathAnimation.IAnimationUpdateListener() { @Override public void onAnimUpdate(int index) { mInhaleMesh.buildMeshes(index); invalidate(); } }); if (null != animation) { animation.setDuration(1000); this.startAnimation(animation); } return true; } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(0x00CCCCCC); canvas.drawBitmapMesh(mBitmap, mInhaleMesh.getWidth(), mInhaleMesh.getHeight(), mInhaleMesh.getVertices(), 0, null, 0, mPaint); // Draw the target point. // mPaint.setColor(Color.RED); // mPaint.setStrokeWidth(2); // mPaint.setAntiAlias(true); // mPaint.setStyle(Paint.Style.FILL); // canvas.drawCircle(mInhalePoint[0], mInhalePoint[1], 5, mPaint); if (mIsDebug) { // Draw the mesh vertices. canvas.drawPoints(mInhaleMesh.getVertices(), mPaint); // Draw the paths mPaint.setColor(Color.BLUE); mPaint.setStyle(Paint.Style.STROKE); Path[] paths = mInhaleMesh.getPaths(); for (Path path : paths) { canvas.drawPath(path, mPaint); } } } private void buildMesh(float w, float h) { mInhaleMesh.buildMeshes(w, h); } public void buildPaths(float endX, float endY) { mInhalePoint[0] = endX; mInhalePoint[1] = endY; mInhaleMesh.buildPaths(endX, endY); } // private int mLastPointX = 0; // private int mLastPointY = 0; // @Override // public boolean onTouchEvent(MotionEvent event) { // float[] pt = { event.getX(), event.getY() }; // // if (event.getAction() == MotionEvent.ACTION_UP) { // int x = (int) pt[0]; // int y = (int) pt[1]; // if (mLastPointX != x || mLastPointY != y) { // mLastPointX = x; // mLastPointY = y; // buildPaths(pt[0], pt[1]); // invalidate(); // } // } // return true; // } } private static class PathAnimation extends Animation { public interface IAnimationUpdateListener { public void onAnimUpdate(int index); } private int mFromIndex; private int mEndIndex; private boolean mReverse; private IAnimationUpdateListener mListener; public PathAnimation(int fromIndex, int endIndex, boolean reverse, IAnimationUpdateListener listener) { mFromIndex = fromIndex; mEndIndex = endIndex; mReverse = reverse; mListener = listener; } public boolean getTransformation(long currentTime, Transformation outTransformation) { return super.getTransformation(currentTime, outTransformation); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { Interpolator interpolator = this.getInterpolator(); if (null != interpolator) { float value = interpolator.getInterpolation(interpolatedTime); interpolatedTime = value; } if (mReverse) { interpolatedTime = 1.0f - interpolatedTime; } int currentIndex = (int) (mFromIndex + (mEndIndex - mFromIndex) * interpolatedTime); if (null != mListener) { mListener.onAnimUpdate(currentIndex); } } } }