//android.graphics.Matrix 类提供二维坐标变换(平移,旋转,缩放等)使用Matrix通常的方法是直接指定所需的Matrix的值,另外一种如果已知坐标变换前后几个点的坐标,你可以根据这些点的映射关系算出对应的变换矩阵。但Matrix提供了一种更为简洁的方法:
//
//public boolean setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount)
//
//提供指定变换前(src)和变换后(dst)的坐标对,Matrix自动帮你计算出实现这些坐标变换对于的Matrix。每个坐标的格式为[x0,y0,x1,y1 ...]两个float值代表一个点。
//
//本例使用1 个点 (偏移变换) 2个点(旋转/缩放) ,3个点(旋转/剪切),4个点(透视变换) 使用polyToPoly 计算出对应的Matrix,然后使用计算出的Matrix来绘制图形:
import android.content.Context;
import android.graphics.*;
import android.os.Bundle;
import android.view.View;public class PolyToPoly extends GraphicsActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(new SampleView(this));}private static class SampleView extends View {private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);private Matrix mMatrix = new Matrix();private Paint.FontMetrics mFontMetrics;private void doDraw(Canvas canvas, float src[], float dst[]) {canvas.save();mMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1);//扭曲这个图形canvas.concat(mMatrix);//应用matrix 到这个canvasmPaint.setColor(Color.GRAY);mPaint.setStyle(Paint.Style.STROKE);canvas.drawRect(0, 0, 64, 64, mPaint);canvas.drawLine(0, 0, 64, 64, mPaint);canvas.drawLine(0, 64, 64, 0, mPaint);mPaint.setColor(Color.RED);mPaint.setStyle(Paint.Style.FILL);// how to draw the text center on our square// centering in X is easy... use alignment (and X at midpoint)float x = 64/2;// centering in Y, we need to measure ascent/descent first计算文件的上下 ascent 和 descent 用于 英文float y = 64/2 - (mFontMetrics.ascent + mFontMetrics.descent)/2;canvas.drawText(src.length/2 + "", x, y, mPaint);canvas.restore();}public SampleView(Context context) {super(context);// for when the style is STROKEmPaint.setStrokeWidth(4);// for when we draw textmPaint.setTextSize(40);mPaint.setTextAlign(Paint.Align.CENTER);mFontMetrics = mPaint.getFontMetrics();}@Overrideprotected void onDraw(Canvas canvas) {canvas.drawColor(Color.WHITE);canvas.save();canvas.translate(10, 10);// translate (1 point)doDraw(canvas, new float[] { 0, 0 }, new float[] { 5, 5 });canvas.restore();canvas.save();canvas.translate(160, 10);// rotate/uniform-scale (2 points)doDraw(canvas, new float[] { 32, 32, 64, 32 },new float[] { 32, 32, 64, 48 });canvas.restore();canvas.save();canvas.translate(10, 110);// rotate/skew (3 points)doDraw(canvas, new float[] { 0, 0, 64, 0, 0, 64 },new float[] { 0, 0, 96, 0, 24, 64 });canvas.restore();canvas.save();canvas.translate(160, 110);// perspective (4 points)doDraw(canvas, new float[] { 0, 0, 64, 0, 64, 64, 0, 64 },new float[] { 0, 0, 96, 0, 64, 96, 0, 64 });canvas.restore();}}
}
public class DrawPoints extends GraphicsActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(new SampleView(this));}private static class SampleView extends View {private Paint mPaint = new Paint();private float[] mPts;private static final float SIZE = 300;private static final int SEGS = 32;private static final int X = 0;private static final int Y = 1;private void buildPoints() {final int ptCount = (SEGS + 1) * 2;mPts = new float[ptCount * 2];float value = 0;final float delta = SIZE / SEGS;for (int i = 0; i <= SEGS; i++) {mPts[i*4 + X] = SIZE - value;//每四个像素一个点mPts[i*4 + Y] = 0;mPts[i*4 + X + 2] = 0;mPts[i*4 + Y + 2] = value;value += delta;}}public SampleView(Context context) {super(context);buildPoints();}@Override protected void onDraw(Canvas canvas) {Paint paint = mPaint;canvas.translate(10, 10);canvas.drawColor(Color.WHITE);paint.setColor(Color.RED);paint.setStrokeWidth(0);canvas.drawLines(mPts, paint); //x1y1 x2y2 ...paint.setColor(Color.BLUE);paint.setStrokeWidth(3);canvas.drawPoints(mPts, paint);//绘制数组的点而已 x1y1 x2y2 ...}}
}
public class Pictures extends GraphicsActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(new SampleView(this));}private static class SampleView extends View {private Picture mPicture;private Drawable mDrawable;static void drawSomething(Canvas canvas) {Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);p.setColor(0x88FF0000);canvas.drawCircle(50, 50, 40, p);p.setColor(Color.GREEN);p.setTextSize(30);canvas.drawText("Pictures", 60, 60, p);}public SampleView(Context context) {super(context);setFocusable(true);setFocusableInTouchMode(true);//Picture在android.graphics.Picture包中,相对于Drawable和Bitmap而言,Picture对象就小巧的多,//它并不存储实际的像素,仅仅记录了每个绘制的过程。//整个类提供了两个重载形式,其中比较特别的是 Picture(Picture src) 从一个Picture对象去实例化操作mPicture = new Picture();drawSomething(mPicture.beginRecording(200, 100)); //开始记录绘制的东西但是其实在屏幕上什么也没有mPicture.endRecording();mDrawable = new PictureDrawable(mPicture);}@Override protected void onDraw(Canvas canvas) {canvas.drawColor(Color.WHITE);canvas.drawPicture(mPicture);canvas.drawPicture(mPicture, new RectF(0, 100, getWidth(), 200)); //对以前的绘制进行缩放mDrawable.setBounds(0, 200, getWidth(), 300); mDrawable.draw(canvas);//通过picturedrawabke 绘制下一个ByteArrayOutputStream os = new ByteArrayOutputStream();mPicture.writeToStream(os);//可以保持这个绘制的过程 ,应该生成的文件会很小InputStream is = new ByteArrayInputStream(os.toByteArray());canvas.translate(0, 300);canvas.drawPicture(Picture.createFromStream(is));//从二进制流中拿出来并绘制}}
}
public class Patterns extends GraphicsActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(new SampleView(this));}private static Bitmap makeBitmap1() {//红蓝色的 方格 bitmapBitmap bm = Bitmap.createBitmap(40, 40, Bitmap.Config.RGB_565);Canvas c = new Canvas(bm);c.drawColor(Color.RED);Paint p = new Paint();p.setColor(Color.BLUE);c.drawRect(5, 5, 35, 35, p);return bm;}private static Bitmap makeBitmap2() { //绿色的圆Bitmap bm = Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_8888);Canvas c = new Canvas(bm);Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);p.setColor(Color.GREEN);p.setAlpha(0xCC);c.drawCircle(32, 32, 27, p);return bm;}private static class SampleView extends View {private final Shader mShader1;private final Shader mShader2;private final Paint mPaint;private final DrawFilter mFastDF;private float mTouchStartX;private float mTouchStartY;private float mTouchCurrX;private float mTouchCurrY;private DrawFilter mDF;public SampleView(Context context) {super(context);setFocusable(true);setFocusableInTouchMode(true);mFastDF = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG |Paint.DITHER_FLAG,0);//绘制滤镜?mShader1 = new BitmapShader(makeBitmap1(), Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);//重复绘制方形mShader2 = new BitmapShader(makeBitmap2(), Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);//重复绘制圆Matrix m = new Matrix();m.setRotate(30); //圆形进行了整个旋转mShader2.setLocalMatrix(m);mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);//是bitmap填充}@Override protected void onDraw(Canvas canvas) {canvas.setDrawFilter(mDF);mPaint.setShader(mShader1);canvas.drawPaint(mPaint);//把画布的内容绘制到屏幕 实际上是那些bitmapcanvas.translate(mTouchCurrX - mTouchStartX,mTouchCurrY - mTouchStartY);//随着手指的东而移动第一层mPaint.setShader(mShader2);canvas.drawPaint(mPaint);}@Overridepublic boolean onTouchEvent(MotionEvent event) {float x = event.getX();float y = event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mTouchStartX = mTouchCurrX = x;mTouchStartY = mTouchCurrY = y;mDF = mFastDF;invalidate();break;case MotionEvent.ACTION_MOVE:mTouchCurrX = x;mTouchCurrY = y;invalidate();break;case MotionEvent.ACTION_UP:mDF = null;invalidate();break;}return true;}}
}
public class PathFillTypes extends GraphicsActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(new SampleView(this));}private static class SampleView extends View {private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);private Path mPath;public SampleView(Context context) {super(context);setFocusable(true);setFocusableInTouchMode(true);mPath = new Path();mPath.addCircle(40, 40, 45, Path.Direction.CCW);mPath.addCircle(80, 80, 45, Path.Direction.CCW);}private void showPath(Canvas canvas, int x, int y, Path.FillType ft,Paint paint) {canvas.save();canvas.translate(x, y);canvas.clipRect(0, 0, 120, 120);canvas.drawColor(Color.WHITE);mPath.setFillType(ft);canvas.drawPath(mPath, paint);canvas.restore();}@Override protected void onDraw(Canvas canvas) {Paint paint = mPaint;canvas.drawColor(0xFFCCCCCC); //黑色的 pathcanvas.translate(20, 20);paint.setAntiAlias(true);showPath(canvas, 0, 0, Path.FillType.WINDING, paint);//全集 path内的都是黑色showPath(canvas, 160, 0, Path.FillType.EVEN_ODD, paint);//他们的差集 (共同的也是白色)showPath(canvas, 0, 160, Path.FillType.INVERSE_WINDING, paint); //翻转showPath(canvas, 160, 160, Path.FillType.INVERSE_EVEN_ODD, paint); //2的}}
}