//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 {
@Override
protected 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 到这个canvas
mPaint.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 STROKE
mPaint.setStrokeWidth(4);
// for when we draw text
mPaint.setTextSize(40);
mPaint.setTextAlign(Paint.Align.CENTER);
mFontMetrics = mPaint.getFontMetrics();
}
@Override
protected 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 {
@Override
protected 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 {
@Override
protected 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 {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static Bitmap makeBitmap1() {//红蓝色的 方格 bitmap
Bitmap 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);//把画布的内容绘制到屏幕 实际上是那些bitmap
canvas.translate(mTouchCurrX - mTouchStartX,
mTouchCurrY - mTouchStartY);//随着手指的东而移动第一层
mPaint.setShader(mShader2);
canvas.drawPaint(mPaint);
}
@Override
public 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 {
@Override
protected 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); //黑色的 path
canvas.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的
}
}
}