第15回哼,我三岁就会图形应用!

来源:互联网 发布:炫踪网络 融资 编辑:程序博客网 时间:2024/05/16 13:59

这一日,阳光明媚,乌云密布。刘关张三人装作学习编程的样子,实际在院子里斗地主。三人斗得满头大汗,刘备输得快连背心都要搭进去了。

刘备:“小飞呀,没看出来啊,你平时脑子不灵光,怎么斗地主这么了得!”

张飞:“不瞒大哥,其实在家乡,杀猪只是我的业余爱好,我的主要生活来源是斗地主。”

关羽:“原来是职业玩家!”

这时忽听门外有人喊门:“有人吗……有人吗……有人吗?”

刘备:“小飞赶紧去看看,谁这么生活大爆炸,还得喊三遍……”

张飞赶紧去开门,只见门外一个老汉,穿得跟济公似的,张飞赶忙说:“老大爷,您行行好,我们几个自己口粮都不够吃啊,已经好几天揭不开锅了,实在是没有多余的口粮,您再到别的地方去讨要吧。”

老汉怒道:“你神马眼神!我像是要饭的吗?现在流行这种Style你懂不懂,这叫Fashion好不好,你完全Out了有木有!”

张飞:“天呐,好华丽的蛮文!老叔不知到此何为?”

老汉:“诸葛亮呢?”

张飞:“蹲坑呢。”

老汉:“我就知道,带我进去找他!”

张飞连忙引路,这时刘备、关羽也跟过来看看什么个情况。进到屋里,只见孔明这回竟没有蹲坑,正坐在那里喝茶,刘备奇道:“先生今日竟不在出恭?”

孔明:“我料定今日有贵人来访,特在此等候。”

不等刘关张叹服,老汉怒道:“靠,我昨天跟你约好了今天来,料你妹啊!”

孔明:“先生言重了,我没有妹妹……”

刘备问道:“孔明,这位先生是?”

老汉:“老汉张角,黄巾教教主是也!”

关羽嘀咕道:“奇怪,按剧情他不早就死了嘛,怎么瞎编呢?”

张角:“这次找孔明想让你帮忙编个APP,拿去给我们那些教友用,宣传一下我们黄巾教教义。现在时代不同啦,光用讲的不够打动人心啊!”

孔明:“我早己退隐多年,这些具体工作就交给他们三人去做吧。”

张角:“他们?他们咋看起来好搓,会做带各种图形的应用吗?”

刘备一咬牙,一抹嘴,怒道:“哼,我三岁就会图形应用!”

1.1.Android绘图简介

在开发过程中常常会用到Android的绘图功能,在Android中绘图只需要获得一个画布Canvas,并使用适当的画笔Paint进行绘制就可以了。下面将介绍画布Canvas类和画笔Paint:

 

画布Canvas

Android的绘图都是在画布Canvas上进行的。可以通过View或Bitmap位图获得其Canvas。在绘图时需要对Canvas进行一些必要的配置,如表15-1所示:

表15-1 配置Canvas类的方法

方法

解释

Canvas()

创建一个空的Canvas,可以通过setBitmap()去指定它使用的Bitmap。

Canvas(Bitmap bitmap)

用Bitmap创建一个Canvas,内容都绘制在图片上。

rotate()

旋转Canvas。

clipRect()

设置显示区域,即对Canvas进行剪裁。

           Canvas还提供了大量的绘图方法,常用的有下面几种:

表15-2 Canvas主要绘图方法

方法

说明

drawRect(RectF,Paint)

绘制一个矩形。第一个参数为图形显示区域,第二个参数是画笔。

drawLine(startX, startY, stopX, stopY, paint)

绘制一条直线。分别传入起止点坐标和所用的画笔。

drawCircle(float,float, float, Paint)

绘制一个画圆。前两个参数是圆心坐标,第三个参数为圆半径,第四个参数是画笔。

在绘制图形过程中,需要知道要绘制图形在屏幕上显示的坐标,手机屏幕的左上角是坐标原点,原点向右延伸是X轴正方向,向下延伸是Y轴正方向,如图15-1所示:

图15-1 屏幕坐标示意图

画笔Paint

Paint是Android中的画笔,表示绘制的风格,通过Paint可以修改绘图的颜色、字体风格等。Paint类的主要方法如表15-3所示:

表15-3 Paint主要方法

方法

说明

setColor(int)

设置画笔的颜色。

setTextSize(float)

设置字体大小。

setStyle(Style)

设置画笔风格,空心还是实心。

1.2. View绘图实例

在View上绘图只需要通过覆盖该View的onDraw()方法,获得Canvas创建Paint画笔进行绘图即可。下面通过一个实例演示如何使用Canvas绘制各种基本图形,新建一个自定义View,命名为CustomView,代码如下所示:

CustomView代码清单15-2-0:

/**

 * 在自定义View上绘图

* @author关羽:我的中文名字叫小羽羽,我的英文名字叫xiaoyuyu!

 */

public classCustomView extends View {

    public CustomView(Context context) {

                 super(context);

               }

               //重写onDraw()方法进行绘图

               @Override

               protectedvoid onDraw(Canvas canvas) {

                   Paint mPaint = new Paint();

                       /*绘制实心矩形*/

                   //设置颜色--蓝色

                   mPaint.setColor(Color.BLUE);

                   //设置样式--填充

                   mPaint.setStyle(Style.FILL);

                   //在View的Canvas上绘制一个蓝色矩形

                   canvas.drawRect(0,0, 100, 100, mPaint);

                   /*绘制空心矩形*/

                   //设置颜色--红色

mPaint.setColor(Color.RED);

           //设置样式--空心

mPaint.setStyle(Style.STROKE);

           //在View的Canvas上绘制一个蓝色矩形

canvas.drawRect(100, 0, 200, 100, mPaint);

           /*绘制文字*/

           //设置颜色

mPaint.setColor(Color.GREEN);

           //绘制文字

canvas.drawText("Hello", 200, 50, mPaint);

           /*绘制图片*/

           //从资源文件中生成位图

Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.icon);

           //绘制位图

canvas.drawBitmap(bitmap, 0, 100, mPaint);

                      }

}

之后就可以像使用其他组件一样使用该CustomView,例如,在Activity的onCreate()方法中写入setContentView(newCustomView(this))。

运行程序,结果如图15-2所示:

图15-2 使用Canvas绘图结果

1.3. 简单涂鸦

在实际生活中常常需要使用手指在手机屏幕上进行简单涂鸦。下面就通过一个实例介绍如何在Android中实现涂鸦,程序的运行结果如图15-3所示:

图15-3 涂鸦运行效果图

新建一个View,命名为PaintView,重写其onTouchEvent()和onDraw()方法,代码如下所示:

PaintView 代码清单15-3-0:

/**

           *在View上绘图

           *@author关羽:我的人生格言是“走别人的路,让别人无路可走。”

           */

public classPaintView extends View {

                      //绘制的画板

                      private Canvas mCanvas = null;

                      //在这个Bitmap上进行绘制

                      private Bitmap mBitmap = null;

                      //当前坐标

                      private float currentX = 0;

                      private float currentY = 0;

                      //要绘制的路径

                      private Path mPath = null;

                      //判断手指是否移动的标志

                      private static double TOUCH_TOLERANCE= 4.0;

                      //画笔

                      private Paint mPaint = null;

                      //是否已经创建画板

                      private boolean canvasIsCreated =false;

                      public PaintView(Context context) {

                                super(context);

                                init();

                      }

                      private void init() {

                                mCanvas = new Canvas();

                                mPath = new Path();

                                mPaint = new Paint();

                                //设置抗锯齿

                                mPaint.setAntiAlias(true);

                                //设置外边缘

                                mPaint.setStrokeJoin(Paint.Join.ROUND);

                                //设置形状

                                mPaint.setStrokeCap(Paint.Cap.ROUND);

                                //设置画笔类型

                                mPaint.setStyle(Style.STROKE);

                                //设置画笔宽度

                                mPaint.setStrokeWidth(5);

                      }

                      //每次View的大小变化时,重新创建Bitmap

                      @Override

                      protected void onSizeChanged(int w,int h, int oldw, int oldh) {

                                super.onSizeChanged(w, h,oldw, oldh);

                                if (!canvasIsCreated) {

                                           mBitmap =Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);

                                           mCanvas.setBitmap(mBitmap);

                                           canvasIsCreated= true;

                                }

                      }

                      @Override

                      public booleanonTouchEvent(MotionEvent event) {

                                float x = event.getX();

                                float y = event.getY();

                                switch (event.getAction()){

                                caseMotionEvent.ACTION_DOWN:

                                           mCanvas.setBitmap(mBitmap);

                                           //重置Path

                                           mPath.reset();

                                           mPath.moveTo(x,y);

                                           currentX = x;

                                           currentY = y;

                                           invalidate();

                                           break;

                                caseMotionEvent.ACTION_MOVE:

                                           if (isMoved(x,y)) {

                                                     drawBeziercurve(x,y);

                                                     currentX= x;

                                                     currentY= y;

                                           }

                                          //刷新页面

                                           invalidate();

                                           break;

                                case MotionEvent.ACTION_UP:

                                           mPath.lineTo(x,y);

                                           invalidate();

                                           break;

                                default:

                                           break;

                                }

                                 returntrue;

                      }

                      @Override

                      public void onDraw(Canvas canvas) {

                                canvas.drawColor(Color.WHITE);

                                canvas.drawBitmap(mBitmap,0, 0, mPaint);

                                //绘画

                                mCanvas.drawPath(mPath,mPaint);

                      }

                      //绘制贝塞尔曲线

                      private void drawBeziercurve(float x,float y) {

                                mPath.quadTo(currentX,currentY, (x + currentX) / 2, (y + currentY) / 2);

                      }

                      //判断手指是否移动

                      private boolean isMoved(float x,float y) {

                                float dx = Math.abs(x -currentX);

                                float dy = Math.abs(y -currentY);

                                boolean isMoved = dx >=TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE;

                                return isMoved;

                      }

}

           该代码通过记录手指滑动的路径,实时地将路径绘制到一个Bitmap上,在View进行更新的时候,将这个Bitmap绘制到View的Canvas上。如果直接在View的Canvas上绘制是无法保留之前的绘制路径。

孔明:使用贝塞尔曲线进行绘制,可以使绘制的曲线更为光滑好看。如果想在已经存储的图片上进行绘制,就将mBitmap替换为载入的图片就好啦。

m

 

          

 

1.4.使用Bitmap位图

从前面的例子可以看出Bitmap位图在Android图形应用中有很重要的作用,下面将介绍如何使用Bitmap。

 

Canvas上绘制Bitmap

通过使用Canvas的drawBitmap()方法可以将Bitmap绘制到一个View的Canvas中,例如,下面代码将载入一个Bitmap并将其绘制到Canvas上。

Bitmap pic =BitmapFactory.decodeResource(getResources, R.drawable.demo);

canvas.drawBitmap(pic);

 

缩放Bitmap

可以使用Bitmap 的createScaledBitmap()方法对Bitmap进行缩放,如下代码所示:

//从资源文件中生成Bitmap

Bitmap bitmap =BitmapFactory.decodeResource(getResources(), R.drawable.icon);

//进行缩放

Bitmap bm =Bitmap.createScaledBitmap(bitmap, 200, 300, false);

//绘图

canvas.drawBitmap(bm,60, 50, mPaint);

           上述代码将原像素100*150的图片放大为200*300,绘制效果如图15-4所示:

图15-4 图片缩放效果图

 

使用Matrix变化Bitmap

使用Matrix可以控制图片缩放、旋转、移动、颜色变换等。Matrix使用如下矩阵进行变换:

                       cosValue,   -sinValue,          translateX,

                        sinValue,    cosValue,           translateY,

                        0,                             0,                          scale

在上面的矩阵中cosValue、sinValue表示旋转的角度(按逆时针方向计算),translateX与translateY表示X和Y的偏移量,scale表示放大倍数。例如:最简单的旋转90度矩阵应该是:

0,     -1,      0

1,     0,        0

0,     0,        1

下面就通过一个实例演示如何使用Matrix实现一个图片的旋转、缩放效果,代码如下所示:

Matrix旋转、缩放代码15-4-0:

/**

           *使用Matrix

* @author关羽:我太有才了,因为上辈子我是裁缝!

           */

public classCustomView extends View {

                      public CustomView(Context context) {

                                super(context);

                                init();

                      }

                      private Bitmap mBitmap;

                      private Matrix mMatrix = newMatrix();

 

                      private void init() {

                                mBitmap =BitmapFactory.decodeResource(getResources(), R.drawable.icon);

                                float cosValue = (float)Math.cos(-Math.PI/6);

                                float sinValue = (float)Math.sin(-Math.PI/6);

                                mMatrix.setValues(

                                                      //所使用的矩阵

                                new float[]{

                          cosValue,-sinValue, 100,

                                sinValue, cosValue, 100,

                                0, 0, 2});

                      }

                      @Override

void onDraw(Canvas canvas) {

                                canvas.drawBitmap(mBitmap, mMatrix,null);

                      }

}

运行程序,结果如图15-5所示:

图15-5 使用Matrix

1.5.刘备有话说

关羽:我在载入Bitmap时经常出现“Out of Memory”错误,什么情况?

刘备:图片必须要进行缩放才能载入,另外在不用Bitmap的时候要注意进行手动的垃圾回收,代码如下所示:

if(bitmap!=null && !bitmap.isRecycled()){

bitmap.recycle();

                        System.gc();

       }

 

关羽:怎样才能做一个镜像图片呢?

刘备:使用Matrix和Bitmap就可以直接创建,代码如下所示:

Matrix m = new Matrix();

             m.preScale(-1, 1);

       Bitmapsrc = d.getBitmap();

       Bitmapdst = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), m,false);

dst.setDensity(DisplayMetrics.DENSITY_DEFAULT);

0 0
原创粉丝点击