转载至:http://emmet1988.iteye.com/blog/1058517
BasicViewDraw.java
- package com.view;
- import com.test.R;
- import android.view.View;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.RectF;
- import android.graphics.Path;
- import android.graphics.Shader;
- import android.graphics.LinearGradient;
- /* 自定义继承View 的MyView*/
- public class BasicViewDraw extends View {
- public BasicViewDraw(Context context) {
- super(context);
- }
- /* 重写onDraw() */
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- /* 设置背景为白色 */
- canvas.drawColor(Color.WHITE);
- Paint paint = new Paint();
- /* 去锯齿 */
- paint.setAntiAlias(true);
- /* 设置paint的颜色 */
- paint.setColor(Color.RED);
- /* 设置paint的 style 为STROKE:空心 */
- paint.setStyle(Paint.Style.STROKE);
- /* 设置paint的外框宽度 */
- paint.setStrokeWidth(3);
- /* 画一个空心圆形 */
- canvas.drawCircle(40, 40, 30, paint);
- /* 画一个空心正方形 */
- canvas.drawRect(10, 90, 70, 150, paint);
- /* 画一个空心长方形 */
- canvas.drawRect(10, 170, 70, 200, paint);
- /* 画一个空心椭圆形 */
- RectF re = new RectF(10, 220, 70, 250);
- canvas.drawOval(re, paint);
- /* 画一个空心三角形 */
- Path path = new Path();
- path.moveTo(10, 330);
- path.lineTo(70, 330);
- path.lineTo(40, 270);
- path.close();//记得要close
- canvas.drawPath(path, paint);
- /* 画一个空心梯形 */
- Path path1 = new Path();
- path1.moveTo(10, 410);
- path1.lineTo(70, 410);
- path1.lineTo(55, 350);
- path1.lineTo(25, 350);
- path1.close();
- canvas.drawPath(path1, paint);
- /* 设置paint 的style为 FILL:实心 */
- paint.setStyle(Paint.Style.FILL);
- /* 设置paint的颜色 */
- paint.setColor(Color.BLUE);
- /* 画一个实心圆 */
- canvas.drawCircle(120, 40, 30, paint);
- /* 画一个实心正方形 */
- canvas.drawRect(90, 90, 150, 150, paint);
- /* 画一个实心长方形 */
- canvas.drawRect(90, 170, 150, 200, paint);
- /* 画一个实心椭圆 */
- RectF re2 = new RectF(90, 220, 150, 250);
- canvas.drawOval(re2, paint);
- /* 画一个实心三角形 */
- Path path2 = new Path();
- path2.moveTo(90, 330);
- path2.lineTo(150, 330);
- path2.lineTo(120, 270);
- path2.close();
- canvas.drawPath(path2, paint);
- /* 画一个实心梯形 */
- Path path3 = new Path();
- path3.moveTo(90, 410);
- path3.lineTo(150, 410);
- path3.lineTo(135, 350);
- path3.lineTo(105, 350);
- path3.close();
- canvas.drawPath(path3, paint);
- /* 设置渐变色 */
- Shader mShader = new LinearGradient(0, 0, 100, 100, new int[] {
- Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW }, null,
- Shader.TileMode.REPEAT);
- paint.setShader(mShader);
- /* 画一个渐变色圆 */
- canvas.drawCircle(200, 40, 30, paint);
- /* 画一个渐变色正方形 */
- canvas.drawRect(170, 90, 230, 150, paint);
- /* 画一个渐变色长方形 */
- canvas.drawRect(170, 170, 230, 200, paint);
- /* 画一个渐变色椭圆 */
- RectF re3 = new RectF(170, 220, 230, 250);
- canvas.drawOval(re3, paint);
- /* 画一个渐变色三角形 */
- Path path4 = new Path();
- path4.moveTo(170, 330);
- path4.lineTo(230, 330);
- path4.lineTo(200, 270);
- path4.close();
- canvas.drawPath(path4, paint);
- /* 画一个渐变色梯形 */
- Path path5 = new Path();
- path5.moveTo(170, 410);
- path5.lineTo(230, 410);
- path5.lineTo(215, 350);
- path5.lineTo(185, 350);
- path5.close();
- canvas.drawPath(path5, paint);
- /* 写字 */
- paint.setTextSize(24);
- canvas.drawText(getResources().getString(R.string.str_text1), 240, 50,paint);
- canvas.drawText(getResources().getString(R.string.str_text2), 240, 120,paint);
- canvas.drawText(getResources().getString(R.string.str_text3), 240, 190,paint);
- canvas.drawText(getResources().getString(R.string.str_text4), 240, 250,paint);
- canvas.drawText(getResources().getString(R.string.str_text5), 240, 320,paint);
- canvas.drawText(getResources().getString(R.string.str_text6), 240, 390,paint);
- }
- }
BasicView2Draw.java
- class BasicView2Draw extends View{
- Paint paint;
- Bitmap bitmap;
- public BasicView2Draw(Context context) {
- super(context);
- paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
- }
- private Bitmap createBitmap1(){
- Bitmap bitmap1 = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap1);
- canvas.drawColor(Color.BLUE);
- // canvas.drawARGB(0, 0, 0, 0);// 透明色
- canvas.drawBitmap(bitmap, 0, 0, paint);
- canvas.drawText("Hello Android", 25, 55, paint);
- return bitmap1;
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- // 绘制位图
- // 1.绘制位图在(10,10)位置上
- canvas.drawBitmap(createBitmap1(), 10, 10, paint);
- // 2. canvas.drawBitmap(Bitmap bitmap,Rect src,Rect dest,Paint paint);
- // canvas.drawBitmap(Bitmap bitmap,Rect src,RectF dest,Paint paint);
- // 绘制位图到一个指定的矩形dest中,位图会自动进行平移和缩放等操作,如果src的参数不为null
- // 则会裁剪位图的部分区域来进行绘制
- Rect rect = new Rect(10, 10, 50, 60);
- RectF rectF1 = new RectF(180.0f, 20.0f, 240.0f, 80.0f);
- RectF rectF2 = new RectF(180.0f, 100.0f, 240.0f, 160.0f);
- canvas.drawBitmap(createBitmap1(), null, rectF1, paint);
- canvas.drawBitmap(createBitmap1(), rect, rectF2, paint);
- // 点
- paint.setStyle(Paint.Style.FILL_AND_STROKE);
- paint.setStrokeWidth(5.0f);
- paint.setColor(Color.YELLOW);
- canvas.drawPoints(new float[]{120,120,140,140,160,160,180,180}, paint);
- // 线
- paint.reset();// 重置画笔
- paint.setColor(Color.GREEN);
- paint.setAntiAlias(true);
- canvas.drawLine(30, 30, 130, 40, paint);
- paint.setColor(Color.RED);
- canvas.drawLines(new float[]{ 40,40,140,40 ,50,50,90,90 }, paint);
- // 矩形
- paint.setColor(Color.CYAN);
- canvas.drawRect(10, 150, 150, 250, paint);
- paint.setColor(Color.GRAY);
- canvas.drawRect(new Rect(10, 260, 150, 280), paint);
- paint.setColor(Color.DKGRAY);
- canvas.drawRect(new RectF(20.2f, 290.9f, 120.2f, 300.3f), paint);
- // 绘制文本
- // paint.setTextSize(20);
- // paint.setColor(0x40ffffff);// 半透明白色
- // paint.setTextAlign(Paint.Align.RIGHT);// 对齐方向
- // canvas.drawText("Cool Android", 250, 180, paint);// 这里注意,坐标(180,180)是文本的左下点坐标
- // 画布平移:
- // 平移的单位是像素,分别是在x,y轴上平移的像素点
- // 正数代表的正方向,x轴为平面的右侧,y轴为平面的下方,相应的,负数则向反方向平移
- // canvas.translate(30.0f, 30.0f);
- // 画布缩放:
- // 参数分别是在想x,y轴上放大或缩小的倍数,大雨1为放大,小于1为缩小,
- // 缩放的原点默认为画布的原点(0,0),也可以指定缩放的原点
- // canvas.scale(2.0f, 1.5f);
- // canvas.scale(0.5f, 0.5f, 100.0f, 100.0f);// 指定坐标(100.0f,100.0f)为缩放原点
- // 这里剖析一下第二个缩放方法,其实系统为我们做的事情是这样的
- /*
- scale(float sx, float sy, float px, float py){
- translate(px,py);
- scale(sx,sy);
- translate(-px,-py);
- }
- */
- // 画布旋转
- // 1.以画布为原点,顺时针旋转40.0f度
- // canvas.rotate(40.0f);
- // 2.以(100.11f, 100.22f)为原点,顺时针旋转50.0f度
- // canvas.rotate(50.0f, 100.11f, 100.22f);
- // 相应的,为了加深理解,我们再剖析一下第二个旋转方法
- // ,其实系统为我们做的事情是这样的
- /*
- rotate(float degrees, float px, float py){
- translate(px,py);
- rotate(degrees);
- translate(-px,-py);
- }
- */
- // 画布倾斜
- // skew(float sx,float xy);将画布在x及y轴方向上倾斜相应的角度,sx或sy为倾斜角度的tan值,
- // 如canvas.skew(1,0);为在x方向上倾斜45度 >> tan(45) = 1
- // canvas.skew(1,0);
- }
- }
ClipRectDraw.java
- package com.view;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Path;
- import android.graphics.Region;
- import android.util.AttributeSet;
- import android.view.View;
- /**
- * ---------------------------------------------------矩形区域-------------------------------------------------
- * canvas.clipRect(左上角x轴坐标, 左上角y轴坐标, 右下角x轴坐标, 右下角y轴坐标, Region.Op.XOR);
- * 最后一个参数有多个选择分别是:
- * //DIFFERENCE是第一次不同于第二次的部分显示出来
- //REPLACE是显示第二次的
- //REVERSE_DIFFERENCE 是第二次不同于第一次的部分显示
- //INTERSECT:交集显示
- //UNION:全部显示
- //XOR补集,就是全集的减去交集剩余部分显示
- * @author emmet1988.iteye.com
- *
- */
- public class ClipRectDraw extends View {
- Context context;
- Paint paint;
- Path path;
- public ClipRectDraw(Context context) {
- super(context);
- init();
- }
- public ClipRectDraw(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
- public ClipRectDraw(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
- private void init(){
- paint = new Paint();
- paint.setAntiAlias(true);
- paint.setStrokeWidth(5);
- paint.setTextSize(15);
- paint.setTextAlign(Paint.Align.RIGHT);
- path = new Path();
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- canvas.drawColor(Color.GRAY);
- //左上图
- canvas.save();
- canvas.translate(10, 10);
- drawScene(canvas);
- canvas.restore();
- //右上图
- canvas.save();
- canvas.translate(160, 10);
- canvas.clipRect(10, 10, 90, 90);
- canvas.clipRect(30, 30, 70, 70, Region.Op.XOR);
- drawScene(canvas);
- canvas.restore();
- //左中图
- canvas.save();
- canvas.translate(10, 130);
- path.reset();
- /*抛物曲线*/
- path.cubicTo(0, 0, 100, 0, 100, 100);
- path.cubicTo(100, 100, 0, 100, 0, 0);
- canvas.clipPath(path, Region.Op.REPLACE);
- drawScene(canvas);
- canvas.restore();
- //右中图
- canvas.save();
- canvas.translate(160, 130);
- canvas.clipRect(0, 0, 60, 60);
- canvas.clipRect(40, 40, 100, 100, Region.Op.UNION);
- drawScene(canvas);
- canvas.restore();
- //左下图
- canvas.save();
- canvas.translate(10, 250);
- canvas.clipRect(0, 0, 60, 60);
- canvas.clipRect(40, 40, 100, 100, Region.Op.XOR);
- drawScene(canvas);
- canvas.restore();
- //右下图
- canvas.translate(160, 250);
- canvas.clipRect(0, 0, 60, 60);
- canvas.clipRect(40, 40, 100, 100, Region.Op.REVERSE_DIFFERENCE);
- drawScene(canvas);
- canvas.restore();
- }
- private void drawScene(Canvas canvas){
- canvas.clipRect(0, 0, 100, 100);
- canvas.drawColor(Color.WHITE);
- paint.setColor(Color.RED);
- canvas.drawLine(0, 0, 100, 100, paint);
- paint.setColor(Color.GREEN);
- canvas.drawCircle(30, 70, 30, paint);
- paint.setColor(Color.BLUE);
- canvas.drawText("ChenJianLi", 100, 30, paint);
- }
- }
MatrixDraw.java
- package com.view;
- import com.test.R;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
- import android.graphics.Matrix;
- import android.graphics.Paint;
- import android.graphics.drawable.BitmapDrawable;
- import android.view.View;
- /**
- * 在 Android 里面, Matrix 由 9 个 float 值构成,是一个 3*3 的矩阵。
- * cosX, -sinX,translateX
- * sinX, cosX,translateY
- * 0, 0, scale
- * 解释一下,上面的 sinX 和 cosX ,表示旋转角度的 cos 值和 sin 值,注意,
- * 旋转角度是按顺时针方向计算的。 translateX 和 translateY 表示 x 和 y 的平移量。
- * scale 是缩放的比例, 1 是不变, 2 是表示缩放 1/2 ,
- * @author emmet1988.iteye.com
- *
- */
- public class MatrixDraw extends View implements Runnable{
- Bitmap bitmap;
- Matrix matrix = new Matrix();
- Paint paint;
- public MatrixDraw(Context context) {
- super(context);
- bitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.rotate_surfaceview)).getBitmap();
- paint = new Paint();
- paint.setAntiAlias(true);
- new Thread(this).start();
- }
- float m;
- float n;
- @Override
- protected void onDraw(Canvas canvas) {
- /*
- float cosValue = (float)Math.cos(-Math.PI/m);
- float sinValue = (float)Math.sin(-Math.PI/m);
- Log.d("matrixdraw", "Math.PI =" + Math.PI);
- Log.d("matrixdraw", "Math.PI/m =" + Math.PI/m);
- Log.d("matrixdraw", "Math.cos(-Math.PI/m) =" + (float)Math.cos(-Math.PI/m));
- Log.d("matrixdraw", "Math.sin(-Math.PI/m) =" + (float)Math.sin(-Math.PI/m));
- matrix.setValues(new float[]{
- cosValue,-sinValue,100,
- sinValue,cosValue,100,
- 0, 0, 2
- });//举例,若缩放值为0.9,代表放大原图的十分之一
- // super.onDraw(canvas);//当然,如果界面上还有其他元素需要绘制,只需要将这句话写上就行了。
- // Matrix matrix2 = new Matrix(matrix);
- canvas.drawBitmap(bitmap, matrix, paint);
- // canvas.drawBitmap(bitmap, matrix2, paint);
- */
- n ++;
- if (n == 60) {
- n = 0;
- }
- matrix.postRotate(n);
- matrix.postTranslate(n, n);
- matrix.postScale(1, 1, n, n);
- canvas.drawBitmap(bitmap, matrix, paint);
- }
- @Override
- public void run() {
- while(!Thread.currentThread().isInterrupted()){
- try {
- Thread.sleep(100);
- postInvalidate();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
- }
- /**
- * 以左上角为顶点,缩放一半,逆时针旋转30度,
- * 然后沿x轴和y轴分别平移50个像素,
- * 代码 里面写的是100,为什么是平移50呢,
- * 因为缩放了一半。
- * 大家可以自己设置一下Matrix的值,或者尝试一下两个
- * Matrix相乘,得到的值设置进去,
- * 这样才能对Matrix更加熟练。
- */
- }
Matrix2Draw.java
- public class Matrix2Draw extends View {
- private Bitmap mBitmap;
- private Matrix mMatrix = new Matrix();
- public Matrix2Draw(Context context) {
- super(context);
- initialize();
- }
- private void initialize() {
- Bitmap bmp = ((BitmapDrawable)getResources().getDrawable(R.drawable.rotate_surfaceview)).getBitmap();
- mBitmap = bmp;
- /*首先,将缩放为100*100。这里scale的参数是比例。有一点要注意,如果直接用100/
- bmp.getWidth()的话,会得到0,因为是整型相除,所以必须其中有一个是float型的,
- 直接用100f就好。*/
- mMatrix.setScale(100f/bmp.getWidth(), 100f/bmp.getHeight());
- /*// post 方式:后乘 >> 当前的矩阵乘以参数给出的矩阵。可以连续多次使用post,来完成所需的整个变换。
- //平移到(100,100)处
- mMatrix.postTranslate(100, 100);
- //倾斜x和y轴,以(100,100)为中心。
- mMatrix.postSkew(0.2f, 0.2f, 100, 100);*/
- // pre 方式:前乘 >> 参数给出的矩阵乘以当前的矩阵。所以操作是在当前矩阵的最前面发生的。
- //平移到(100,100)处
- mMatrix.preTranslate(100, 100);
- //倾斜x和y轴,以(100,100)为中心。
- mMatrix.preSkew(0.2f, 0.2f, 100, 100);
- }
- @Override protected void onDraw(Canvas canvas) {
- // super.onDraw(canvas); //如果界面上还有其他元素需要绘制,只需要将这句话写上就行了。
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- canvas.drawBitmap(mBitmap, mMatrix, paint);
- }
- }
- /**
- Matrix的操作:
- 总共分为translate(平移),rotate(旋转),scale(缩放)和skew(倾斜)四种,每一种变换在
- Android的API里都提供了set, post和pre三种操作方式,除了translate,其他三种操作都可以指定中心点。
- set是直接设置Matrix的值,每次set一次,整个Matrix的数组都会变掉。
- post是后乘,当前的矩阵乘以参数给出的矩阵。可以连续多次使用post,来完成所需的整个变换。
- pre是前乘,参数给出的矩阵乘以当前的矩阵。所以操作是在当前矩阵的最前面发生的。
- 旋转、缩放和倾斜都可以围绕一个中心点来进行,如果不指定,默认情况下,是围绕(0,0)点来进行。
- */
SimpleDraw.java
- package com.view;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Rect;
- import android.view.View;
- public class SimpleDraw extends View implements Runnable {
- /*
- * 我们继续来介绍Android平台底层绘图类的相关内容,在Android UI开发专题(一)
- * 之界面设计中我们介绍了有关Android平台资源使用以及Bitmap相关类的操作
- * ,接下来将会以实例的方式给大家演示各种类的用处以及注意点。今天我们继续
- * 了解android.graphics包中比较重要的绘图类。
- *
- * 一、 android.graphics.Matrix有关图形的变换、缩放等相关操作常用的方法有:
- * Java代码: void reset() // 重置一个matrix对象。
- * void set(Matrix src) //复制一个源矩阵,和本类的构造方法 Matrix(Matrix src) 一样
- * boolean isIdentity() //返回这个矩阵是否定义(已经有意义)
- * void setRotate(float degrees) //指定一个角度以0,0为坐标进行旋转
- * void setRotate(float degrees, float px, float py) //指定一个角度以px,py为坐标进行旋转
- * void setScale(float sx, float sy) // 缩放
- * void setScale(float sx, float sy, float px, float py) //以坐标px,py进行缩放
- * void setTranslate(float dx, float dy) //平移
- * void setSkew (float kx, float ky, float px, float py) //以坐标px,py进行倾斜
- * void setSkew (float kx, float ky) //倾斜 复制代码 二、android.graphics.NinePatch
- *
- * NinePatch是Android平台特有的一种非矢量图形自然拉伸处理方法,可以帮助常规的
- * 图形在拉伸时不会缩放,
- * 实例中Android开发网提示大家对于Toast的显示就是该原理,同时SDK中提供了一
- * 个工具名为Draw
- * 9-Patch,有关该工具的使用方法可以参考我们经发布的 Draw
- * 9-Patch使用方法介绍一文。由于该类提供了高质量支持透明的缩放方式,所以图形
- * 格式为PNG,文件命名方式为.9.png
- * 的后缀比如eoeandroid。
- *
- * 三、android.graphics.Paint。Paint类我们可以理解为画笔、画刷的属性定义,本类
- * 常用的方法如下:
- *
- * Java代码: void reset() //重置
- * void setARGB(int a, int r, int g, int b) 或 void setColor(int color)
- * //均为设置Paint对象的颜色
- * void setAntiAlias(boolean aa)
- *
- * //是否抗锯齿,需要配合void setFlags (Paint.ANTI_ALIAS_FLAG) 来帮助消除锯齿
- * 使其边缘更平滑。
- * Shader setShader(Shader shader)
- *
- * //设置阴影,Shader类是一个矩阵对象,如果为NULL将清除阴影。
- * void setStyle(Paint.Style style) //设置样式,一般为 FILL 填充,或者STROKE凹陷
- * 效果。
- * void setTextSize(float textSize) //设置字体大小
- * void setTextAlign(Paint.Align align) //文本对齐方式
- * Typeface setTypeface(Typeface typeface)
- * //设置字体,通过Typeface可以加载Android内部的字体,一般为宋体对于中文,
- * 部分ROM可以自己添加比如雅黑等等
- * void setUnderlineText(boolean underlineText)
- *
- * //是否设置下划线,需要撇和void setFlags (Paint.UNDERLINE_TEXT_FLAG) 方法。 复制代码
- * 四、android.graphics.Rect
- *
- * Rect我们可以理解为矩形区域,类似的还有Point一个点,Rect类除了表示一个矩
- * 形区域位置描述外,
- * eoeandroid提示主要可以帮助我们计算图形之间是否碰撞
- * (包含)关系,对于Android游戏开发比较有用,其主要的成员contains包含了三种
- * 重载方法,来判断包含关系.
- *
- * Java代码:
- * boolean contains(int left, int top, int right, int bottom)
- * boolean contains(int x, int y)
- *
- * boolean contains(Rect r) 复制代码 五、android.graphics.Region
- * Region在Android平台中表示一个区域和Rect不同的是
- * ,它表示的是一个不规则的样子,可以是椭圆、多边形等等,而Rect仅仅是矩形。
- * 同样Region的boolean contains(int x,
- * int y) 成员可以判断一个点是否在该区域内。
- *
- * 六、android.graphics.Typeface
- * Typeface类是帮助描述一个字体对象,在TextView中通过使用setTypeface方法来
- * 制定一个输出文本的字体
- * ,其直接构造调用成员create方法可以直接指定一个字体名称和样式,比如
- * Java代码: static Typeface create(Typeface family, int style)
- *
- * static Typeface create(String familyName, int style) 复制代码
- * 同时使用isBold和isItalic方法可以判断出是否包含粗体或斜体的字型。
- *
- * Java代码: final boolean isBold()
- * final boolean isItalic() 复制代码 该类的创建方法还有从apk的资源或从一个具体的
- * 文件路径,其具体方法为
- * Java代码: static Typeface createFromAsset(AssetManager mgr, String path)
- * static Typeface createFromFile(File path)
- * static Typeface createFromFile(String path) 复制代码
- */
- private Paint paint;
- public SimpleDraw(Context context) {
- super(context);
- paint = new Paint();
- new Thread(this).start();
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- canvas.drawColor(Color.GRAY);//
- paint.setAntiAlias(true);//
- canvas.save();//
- canvas.clipRect(10, 10, 110, 110);//
- canvas.drawColor(Color.WHITE);//
- // canvas.rotate(m);//以屏幕左上角为坐标原点旋转
- m += 45.0f;
- if (m == 360.0f) {
- m = 0.0f;
- }
- canvas.rotate(m, 60, 60);// 以(60,60)为原点旋转
- paint.setColor(Color.GREEN);
- canvas.drawRect(new Rect(50, 50, 70, 70), paint);
- canvas.restore();
- canvas.save();
- canvas.translate(140, 10);
- canvas.clipRect(0, 0, 100, 100);// 一定要先剪辑出矩形区域再设画布背景,
- //否则会覆盖整张画布
- canvas.drawColor(Color.BLACK);
- paint.setColor(Color.BLUE);
- canvas.drawRect(new Rect(10, 10, 50, 50), paint);
- canvas.restore();
- //
- canvas.save();
- canvas.translate(120, 120);
- canvas.clipRect(new Rect(0, 0, 100, 100));
- canvas.drawColor(Color.GREEN);
- // paint.setColor(Color.BLUE);
- paint.setStrokeWidth(4);
- paint.setColor(Color.BLACK);
- canvas.drawLine(0, 60, 100, 60, paint);
- paint.setARGB(255, 51, 51, 51);
- paint.setTextSize(20);
- paint.setFlags(Paint.ANTI_ALIAS_FLAG);
- paint.setUnderlineText(true);
- // paint.setFlags(Paint.UNDERLINE_TEXT_FLAG);
- canvas.drawText("陈建立", 25, 80, paint);
- paint.setColor(Color.WHITE);
- canvas.drawRect(new Rect(10, 10, 50, 50), paint);
- canvas.restore();
- }
- float m = 0.0f;
- public void run() {
- while (!Thread.currentThread().isInterrupted()) {
- try {
- Thread.sleep(500);// 每半秒执行一次
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- postInvalidate();
- }
- }
- }
TextDraw.java
- package com.view;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Paint.FontMetrics;
- import android.util.Log;
- import android.view.View;
- public class TextDraw extends View {
- public TextDraw(Context context) {
- super(context);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- Paint textPaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- textPaint.setTextSize( 35);
- textPaint.setColor( Color.WHITE);
- // FontMetrics
- FontMetrics fontMetrics = textPaint.getFontMetrics();
- String text = "abcdefghijklm";
- //
- float baseX = 0;
- float baseY = 100;
- Log.d("textDraw", "top = "+fontMetrics.top+
- "ascent = "+fontMetrics.ascent+
- "descent = "+fontMetrics.descent+
- "bottom = "+fontMetrics.bottom+"\n");
- float topY = baseY + fontMetrics.top;
- float ascentY = baseY + fontMetrics.ascent;
- float descentY = baseY + fontMetrics.descent;
- float bottomY = baseY + fontMetrics.bottom;
- Log.d("textDraw", "topY = "+topY+
- "ascentY = "+ascentY+
- "descentY = "+descentY+
- "bottomY = "+bottomY);
- //
- canvas.drawText( text, baseX, baseY, textPaint);
- // BaseLine
- Paint baseLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- baseLinePaint.setColor( Color.RED);
- canvas.drawLine(0, baseY, getWidth(), baseY, baseLinePaint);
- // Base
- canvas.drawCircle( baseX, baseY, 5, baseLinePaint);
- // TopLine
- Paint topLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- topLinePaint.setColor( Color.LTGRAY);
- canvas.drawLine(0, topY, getWidth(), topY, topLinePaint);
- // AscentLine
- Paint ascentLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- ascentLinePaint.setColor( Color.GREEN);
- canvas.drawLine(0, ascentY, getWidth(), ascentY, ascentLinePaint);
- // DescentLine
- Paint descentLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- descentLinePaint.setColor( Color.YELLOW);
- canvas.drawLine(0, descentY, getWidth(), descentY, descentLinePaint);
- // ButtomLine
- Paint bottomLinePaint = new Paint( Paint.ANTI_ALIAS_FLAG);
- bottomLinePaint.setColor( Color.MAGENTA);
- canvas.drawLine(0, bottomY, getWidth(), bottomY, bottomLinePaint);
- }
- }
RoundAndReflectionDraw.java
- class RoundImageView extends View {
- private Bitmap bitmap;
- int bitmapWidth;
- int bitmapHeight;
- public RoundImageView(Context context) {
- super(context);
- bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.rotate_surfaceview);
- bitmapWidth = bitmap.getWidth();
- bitmapHeight = bitmap.getHeight();
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- // 第一种方法:
- /*Bitmap roundBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight,Bitmap.Config.ARGB_8888);
- canvas = new Canvas(roundBitmap);
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setColor(Color.BLUE);
- canvas.drawRoundRect(new RectF(0, 0, bitmapWidth, bitmapHeight),20.0f, 20.0f, paint);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
- canvas.drawBitmap(bitmap, 0, 0, null);
- canvas.drawBitmap(roundBitmap, 0, 0, paint);*/
- // 第二种方法:
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setColor(0xffffffff);
- paint.setTextSize(15);
- canvas.drawText("生成带圆角的图片", 10, 25, paint);
- canvas.drawBitmap(getRoundedCornerBitmap(bitmap), 10, 30, paint);
- canvas.drawText("生成带倒影的图片", 170, 160, paint);
- canvas.drawBitmap(createReflectionImageWithOrigin(bitmap), 170, 165, paint);
- }
- public Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
- // 创建一个指定宽度和高度的空位图对象
- Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), Config.ARGB_8888);
- // 用该位图创建画布
- Canvas canvas = new Canvas(output);
- // 画笔对象
- final Paint paint = new Paint();
- // 画笔的颜色
- final int color = 0xff424242;
- // 矩形区域对象
- final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
- // 未知
- final RectF rectF = new RectF(rect);
- // 拐角的半径
- final float roundPx = 12;
- // 消除锯齿
- paint.setAntiAlias(true);
- // 画布背景色
- canvas.drawARGB(0, 0, 0, 0);
- // 设置画笔颜色
- paint.setColor(color);
- // 绘制圆角矩形
- canvas.drawRoundRect(rectF, roundPx, roundPx,paint);
- // 未知
- paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
- // 把该图片绘制在该圆角矩形区域中
- canvas.drawBitmap(bitmap, rect, rect, paint);
- // 最终在画布上呈现的就是该圆角矩形图片,然后我们返回该Bitmap对象
- return output;
- }
- //获得带倒影的图片方法
- public Bitmap createReflectionImageWithOrigin(Bitmap bitmap){
- // 图片与倒影之间的距离间隔
- final int reflectionGap = 2;
- // 原图的宽度
- int width = bitmap.getWidth();
- // 原图的高度
- int height = bitmap.getHeight();
- // 图片旋转,缩放等控制对象
- Matrix matrix = new Matrix();
- // 缩放(这里pre,set,post三种效果是不一样的,注意区别)
- matrix.preScale(1, -1);
- /**
- set是直接设置Matrix的值,每次set一次,整个Matrix的数组都会变掉。
- post是后乘,当前的矩阵乘以参数给出的矩阵。可以连续多次使用post,
- 来完成所需的整个变换。例如,要将一个图片旋
- 转30度,然后平移到(100,100)的地方,那么可以这样做:
- Matrix m = new Matrix();
- m.postRotate(30);
- m.postTranslate(100, 100);
- 这样就达到了想要的效果。
- pre是前乘,参数给出的矩阵乘以当前的矩阵。所以操作是在当前矩阵的最前面发生的。
- 例如上面的例子,如果用pre的话,就要这样:
- Matrix m = new Matrix();
- m.setTranslate(100, 100);
- m.preRotate(30);
- 旋转、缩放和倾斜都可以围绕一个中心点来进行,如果不指定,默认情况下,
- 是围绕(0,0)点来进行。
- 关于缩放:
- scale的参数是比例。例如,我们缩放为100%,则有一点要注意,如果直接用
- 100/bmp.getWidth()的话,会得到0,因为是整型相除,所以必须其中有一个是
- float型的,直接用100f就好 。
- 如:matrix.setScale(100f/bmp.getWidth(), 100f/bmp.getHeight());
- */
- // 创建一个初始的倒影位图
- Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height/2, width, height/2, matrix, false);
- // 新建一个宽度为原图宽度,高度为原图高度的3/2的位图,用于绘制新的位图,即整体的效果图位图对象
- Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height/2), Config.ARGB_8888);
- // 由该位图对象创建初始画布(规定了画布的宽高)
- Canvas canvas = new Canvas(bitmapWithReflection);
- // 在该画布上绘制原图
- canvas.drawBitmap(bitmap, 0, 0, null);
- // 创建一个画笔
- Paint deafalutPaint = new Paint();
- // 绘制一个矩形区域,该矩形区域便是原图和倒影图之间的间隔图
- canvas.drawRect(0, height,width,height + reflectionGap,deafalutPaint);
- // 绘制该倒影图于间隔图的下方
- canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
- // 创建一个画笔
- Paint paint = new Paint();
- // 创建一个线性渐变对象
- LinearGradient shader = new LinearGradient(
- 0, bitmap.getHeight(),
- 0, bitmapWithReflection.getHeight() + reflectionGap,
- 0x70ffffff, 0x00ffffff,
- TileMode.CLAMP
- );
- // 把渐变效果应用在画笔上
- paint.setShader(shader);
- // Set the Transfer mode to be porter duff and destination in
- // 未知
- paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
- // Draw a rectangle using the paint with our linear gradient
- // 绘制出该渐变效果,也就是最终的倒影效果图
- canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);
- // 返回
- return bitmapWithReflection;
- }
- }
- /**
- * 绘制圆角背景以及图片圆角的处理
- .配置文件实现
- <?xml version="1.0" encoding="utf-8"?>
- <layer-list
- * xmlns:android="http://schemas.android.com/apk/res/android"> <item
- * android:drawable="@drawable/icon_home_button_img"/> <item
- * android:drawable="@drawable/icon_home_shape_overlay"/>
- * </layer-list>
- * icon_home_shape_overlay如下
- * <?xml version="1.0" encoding="utf-8"?>
- * <shape
- * xmlns:android="http://schemas.android.com/apk/res/android"> <solid
- * android:color="#60000000"/>
- * <stroke android:width="3dp"
- * color="#ff000000"/>
- * <corners android:radius="10dp" />
- * </shape>
- * 或者直接使用一种效果
- * <?xml version="1.0" encoding="UTF-8"?>
- * <shape
- * xmlns:android="http://schemas.android.com/apk/res/android">
- * <solid
- * android:color="#99FFFFFF"/>
- * <corners android:radius="30px"/>
- * <padding
- * android:left="0dp" android:top="0dp" android:right="0dp"
- * android:bottom="0dp" />
- * </shape>
- * 然后
- * android:background="@drawable/my_shape_file"
- *
- *
- * 2.图片本身加上圆角 Bitmap myCoolBitmap = ... ; // <-- Your bitmap you want rounded
- *
- * int w = myCoolBitmap.getWidth(), h = myCoolBitmap.getHeight();
- * Bitmap rounder = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888); Canvas
- * canvas = new Canvas(rounder);
- *
- * Paint xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- * xferPaint.setColor(Color.RED);
- *
- * canvas.drawRoundRect(new RectF(0,0,w,h), 20.0f, 20.0f, xferPaint);
- *
- * xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
- * canvas.drawBitmap(myCoolBitmap, 0,0, null);
- * canvas.drawBitmap(rounder, 0,0, xferPaint);
- * 或者
- * public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
- * Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
- * bitmap.getHeight(), Config.ARGB_8888);
- * Canvas canvas = newCanvas(output);
- *
- * final int color = 0xff424242; final Paint paint = new Paint(); final Rect
- * rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF
- * rectF = new RectF(rect); final float roundPx = 12;
- *
- * paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0);
- * paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx,paint);
- *
- * paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
- * canvas.drawBitmap(bitmap, rect, rect, paint);
- *
- * return output;
- * }
- */
SurfaceViewDraw.java
- package com.view;
- import com.test.R;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.Matrix;
- import android.graphics.Paint;
- import android.graphics.Rect;
- import android.util.Log;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- /**
- * http://wallage.blog.163.com/blog/static/173896242010101232220959/
- * @author emmet1988.iteye.com
- *
- */
- public class SurfaceViewDraw extends SurfaceView implements Runnable,SurfaceHolder.Callback {
- private Bitmap backgroundBitmap;
- private Bitmap rotateBitmap;
- SurfaceHolder surfaceHolder;
- public SurfaceViewDraw(Context context) {
- super(context);
- backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.background_surfaceview);
- rotateBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.rotate_surfaceview);
- surfaceHolder = this.getHolder();
- surfaceHolder.addCallback(this);
- }
- public void surfaceCreated(SurfaceHolder holder) {
- new Thread(this).start();
- Log.d("surfaceview", "surfaceCreated");
- }
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
- Log.d("surfaceview", "surfaceChanged");
- }
- public void surfaceDestroyed(SurfaceHolder holder) {
- Log.d("surfaceview", "surfaceDestroyed");
- }
- @Override
- public void run() {
- Log.d("surfaceview", "run");
- Canvas canvas = null;
- int rotateValue = 0;//旋转角度
- int frameCount = 0;//帧计数器
- while (!Thread.currentThread().isInterrupted()) {
- try {
- // canvas = surfaceHolder.lockCanvas();//获取画布对象(获取整个屏幕的画布)
- canvas = surfaceHolder.lockCanvas(new Rect(10, 10, 240, 250));//获取某个区域的画布
- Paint paint = new Paint();
- Log.d("surfaceview", "rotateValue " +rotateValue+"|frameCount "+frameCount);
- if (frameCount++ < 2) {//仅在第一次绘制时绘制背景
- /*
- * 这里为什么设置成<2,而不是1,是由于SurfaceView本身的双缓冲技术。
- 覆盖刷新其实就是将每次的新的图形绘制到上一帧去,
- 所以如果图像是半透明的,就要考虑重复叠加导致的问题了,
- 而如果是完全不透明的图形则不会有任何问题。
- 背景会在背景图和黑色背景之间来回闪。
- 这个问题其实是源于SurfaceView的双缓冲机制,我理解就是它会缓冲
- 前两帧的图像交替传递给后面的帧用作覆盖,这样由于我们仅在第一帧
- 绘制了背景,第二帧就是无背景状态了,且通过双缓冲机制一直保持下
- 来,解决办法就是改为在前两帧都进行背景绘制。
- */
- canvas.drawBitmap(backgroundBitmap, 0, 0, paint);//绘制背景
- }
- //创建矩阵以控制图片的旋转和平移
- Matrix matrix = new Matrix();
- rotateValue += 40;
- matrix.setRotate(rotateValue, rotateBitmap.getWidth()/2, rotateBitmap.getHeight()/2);
- // matrix.postRotate(rotateValue, rotateBitmap.getWidth()/2, rotateBitmap.getHeight()/2);
- // matrix.setTranslate(100, rotateValue);
- if (rotateValue == 360) {
- rotateValue = 0;
- }
- matrix.setTranslate(80,50);//设置左边距和上边距
- //绘制问号
- Log.d("surfaceview", "canvas "+canvas);
- Log.d("surfaceview", "rotateBitmap "+rotateBitmap);
- Log.d("surfaceview", "matrix "+matrix);
- Log.d("surfaceview", "paint "+paint);
- if (canvas != null) {
- canvas.drawBitmap(rotateBitmap, matrix, paint);
- //解锁画布,提交画好的图像
- surfaceHolder.unlockCanvasAndPost(canvas);
- }
- Thread.sleep(30);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- Log.d("surfaceview", "InterruptedException");
- } finally {
- Log.d("surfaceview", "finally");
- }
- }
- }
- }