本文参考文献:《疯狂Android讲义 : 第2版 》
实例:可以揉动的图片
下面的程序示例将会通过 drawBitmapMesh 方法来控制图片的扭曲,当用户“触摸”图片的指定点时,该图片会在这个点被用户“按”下去, —— 就像这张图片铺在“极软的床上”一样。
package com.toby.personal.testlistview;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
public class MainActivity extends AppCompatActivity {
final private static String TAG = "Toby_Test";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TestView(this, R.drawable.img04));
}
class TestView extends View {
// 定义两个常量,这两个常量将图片的横向、纵向划分20格
private final int WIDTH = 20;
private final int HEIGHT = 20;
private final int COUNT = (WIDTH + 1) * (HEIGHT + 1);
// 记录 Bitmap 上的 21 × 21 个点的坐标
private final float[] orig = new float[COUNT * 2];
// 记录 Bitmap 上的 21 × 21 个点经过扭曲之后的坐标
// 对图片进行扭曲的关键就是修改该数组里面元素的值
private final float[] verts = new float[COUNT * 2];
private Bitmap bitmap;
public TestView(Context context, int drawableId) {
super(context);
setFocusable(true);
bitmap = BitmapFactory.decodeResource(getResources(), drawableId);
float bitmapWidth = bitmap.getWidth();
float bitmapHeight = bitmap.getHeight();
int index = 0;
for (int y = 0; y <= HEIGHT; ++y) {
float fy = bitmapHeight * y / HEIGHT;
for (int x = 0; x <= WIDTH; ++x) {
float fx = bitmapWidth * x / WIDTH;
orig[index * 2] = verts[index * 2] = fx;
orig[index * 2 + 1] = verts[index * 2 + 1] = fy;
index += 1;
}
}
setBackgroundColor(Color.WHITE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.GRAY);
canvas.drawBitmapMesh(bitmap, WIDTH, HEIGHT, verts, 0, null, 0, null);
}
private void warp(float cx, float cy) {
for (int i = 0; i < COUNT * 2; i += 2) {
float dx = cx - orig[i];
float dy = cy - orig[i + 1];
float dd = dx * dx + dy * dy;
float d = (float) Math.sqrt(dd);
float pull = 80000 / ((float) (dd * d));
if (pull >= 1) {
verts[i] = cx;
verts[i + 1] = cy;
} else {
verts[i] = orig[i] + dx * pull;
verts[i + 1] = orig[i + 1] + dy * pull;
}
}
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
warp(event.getX(), event.getY());
return super.onTouchEvent(event);
}
}
}
显示效果: