Android 自定义 View 之使用 drawBitmapMesh 扭曲图像示例

本文参考文献:《疯狂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);
        }
    }

}

显示效果:


Android 自定义 View 之使用 drawBitmapMesh 扭曲图像示例_第1张图片
显示效果

你可能感兴趣的:(Android 自定义 View 之使用 drawBitmapMesh 扭曲图像示例)