《Android和PHP开发最佳实践》一2.8 Android图形界面

2.8 Android图形界面

前面介绍了Android应用界面(Android UI)的相关内容,不过对于一些游戏应用来说,这些UI控件往往派不上用场。此外,一些特殊的Android应用也有可能会使用到比较底层的图形类库,因此,本节我们就来学习Android的图形系统。
Android系统中的图形大致可以分为2D图形和3D图形两类,2D图形的类库在android.graphics包下,本节将会重点介绍;3D图形的类库在android.opengl包下,由于这部分内容和游戏开发关系比较紧密,这部分内容将被放在本书第13章中介绍,感兴趣的朋友可以提前参考13.1.4节中的内容。

2.8.1 画笔(Paint)

首先,让我们来想象一下,当我们绘画的时候,最重要的两样东西是什么?答案应该没有什么悬念,那就是画笔和画布。实际上,在Android系统中绘制图形的原理是相同的,我们同样需要先使用程序构造一把画笔(Paint),然后在画布(Canvas)上进行绘画。
Android系统中的画笔类,即android.graphics包下的Paint类,该类包含了一系列的方法与属性,用于构造绘制图形用的画笔。我们把常用的方法归纳到表2-5中。

以上方法常用于画笔初始化的配置逻辑中,接下来让我们来学习Paint画笔类的使用范例,如参考代码清单2-28所示。
代码清单 2-28

public class TestPaintView extends View {
    ...
    private Paint mPaint = new Paint();
    ...
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 设置画笔
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.RED);
        mPaint.setAlpha(200);
        mPaint.setStyle(Paint.Style.FILL);
        // 绘制矩形
        canvas.drawRect(100, 100, 150, 150, mPaint);
    }
    ...
}

以上视图类TestPaintView继承自View基类,主要的绘制逻辑在onDraw方法中,即使用定制好的实心画笔绘制一个红色的矩形,这里我们可以学习到使用Paint画笔类的正确方法。此外,我们还需要注意,这里在使用setColor方法设置画笔颜色的时候,用到了Color类的预定义颜色常量,我们将这些常用的颜色常量归纳到表2-6中。

2.8.2 画布(Canvas)

设置好画笔和颜色,就可以开始在画布上绘画了,这时我们就需要用到画布类,即Canvas类。该类包含了一系列的方法与属性,用于设置画布的外观,我们把常用的方法归纳到表2-7中。
Canvas类中常用绘制方法的用法比较简单,Android系统已经在View类的onDraw方法中默认传入了canvas对象,我们可以根据需要使用不同的draw方法绘制出不同的图形。比如,代码清单2-29中就使用了drawRect方法绘制了一个矩形。

然而,游戏应用的画布中通常不只有一个图形,通常需要对其中的某些图形进行特殊处理,比如旋转、变形等,此时需要先使用save方法来保存画布,图形处理完毕之后再调用restore方法来重置、重绘,使用范例如代码清单2-29所示。
代码清单 2-29

public class TestCanvasView extends View {
    ...
    private Paint mPaint = new Paint();
    ...
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 设置画布颜色
        canvas.drawColor(Color.BLACK);
        // 设置画笔
        mPaint.setAntiAlias(true);
        // 剪裁画布
        canvas.clipRect(0, 0, 200, 200);
        // 保存画布
        canvas.save();
        // 绘制一个矩形
        canvas.rotate(10.0f);
        mPaint.setColor(Color.RED);
        canvas.drawRect(100, 100, 150, 150, mPaint);
        // 重置画布
        canvas.restore();
        // 绘制另一个矩形
        mPaint.setColor(Color.BLUE);
        canvas.drawRect(100, 0, 200, 100, mPaint);
    }
    ...
}

以上程序绘制了两个矩形。其中,红色的矩形绕着屏幕左上方的顶点顺时间旋转了10°。这里涉及Canvas画布坐标系的知识,我们将在2.8.3节中介绍。另外,我们还可以学习到如何对Canvas画布进行设置、保存、旋转、重置等一系列的操控过程。学习了以上Paint和Canvas类的编程技巧之后,开发者就可以在Android应用和游戏中方便地绘图了。

2.8.3 基础几何图形

前面我们已经学习了画笔(Paint)和画布(Canvas)的基础知识,接下来我们就可以使用这些工具来画图了。实际上,在前面的代码范例中,我们已经介绍了如何使用Canvas对象的drawRect方法来绘制矩形,但是大家可能还不清楚方法中参数值的含义,因此我们先来熟悉Canvas画布的坐标系,如图2-12所示。
从以上的坐标系示意图中,我们可以看出以下几个要点。其一,Canvas画布的坐标原点位于整张画布的左上方,点坐标为“(0,0)”;其二,屏幕横向的是X轴,纵向的是Y轴,屏幕内的点坐标都是正数;其三,以矩形为例,我们可以看到绘图方法(drawRect)中的left、top、right、bottom等参数的含义,其他方法中的类似参数的含义都可以依此类推。
另外,在使用Canvas进行绘图的时候还要注意,画布是按照程序逻辑的先后顺序进行渲染的,因此底部图形的渲染逻辑放在前面,渲染逻辑在后面的图形则会层层覆盖上去,使用范例请参考代码清单2-30。
代码清单 2-30

public class TestGraphicsView extends View {
    ...
    private Paint mPaint = new Paint();
    ...
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 设置画布颜色
        canvas.drawColor(Color.BLACK);
        // 设置画笔
        mPaint.setAntiAlias(true);
        // 画圆形
        mPaint.setColor(Color.YELLOW);
        canvas.drawCircle(160, 160, 120, mPaint);
        // 画矩形
        mPaint.setColor(Color.RED);
        canvas.drawRect(80, 80, 240, 240, mPaint);
        // 画椭圆
        mPaint.setColor(Color.GREEN);
        RectF rectf = new RectF();
        rectf.left = 90;
        rectf.top = 100;
        rectf.right = 230;
        rectf.bottom = 220;
        canvas.drawOval(rectf, mPaint);
        // 画多边形
        Path path = new Path();
        path.moveTo(160, 110);
        path.lineTo(160-40, 110+80);
        path.lineTo(160+40, 110+80);
        path.close();
        mPaint.setColor(Color.BLUE);
        canvas.drawPath(path, mPaint);
        ...
    }
    ...
}

在上述代码中,TestGraphicsView类的onDraw方法中依次绘制了圆形、矩形、椭圆和多边形,运行结果如图2-13所示,我们可以很清楚地看到这些基础几何图形的显示效果以及图形渲染的先后顺序。
基础几何图形的绘制是Android图形系统的基础知识。在此基础之上,我们可以把Android UI控件结合到一起,开发出丰富多彩的应用UI界面。当然,我们还可以运用View控件的刷新机制完成一些简单的图形动画,相关内容将在2.8.4节中介绍。

2.8.4 常见图形变换

常见的图形变换包括位移、旋转、缩放、倾斜等,其中,位移变换在开发者掌握了画布坐标系等基础概念的情况下,实现起来是比较简单的;然而,旋转、缩放以及倾斜变换则涉及变换矩阵(Matrix)的概念,这里需要特别解释一下。
Android系统中的变换矩阵实际上是一个3×3的矩阵,专门用于控制图形变换,矩阵中的每个数值都有其特定的含义。Android SDK中的Matrix类位于android.graphics包下,我们可以通过setValue方法直接设置旋转矩阵的二维数组,但是这种用法比较难懂,更简单的用法是使用Matrix类提供的方法来控制旋转矩阵,比如setRotate方法就用于设定旋转的角度。代码清单2-31就展示了Matrix类的用法。
代码清单 2-31

public class TestImageView extends View implements Runnable {

    private Bitmap star = null;
    private int starWidth = 0;
    private int starHeight = 0;
    private float starAngle = 0.0f;
    private Matrix starMatrix = new Matrix();

    public TestImageView(Context context) {
        super(context);
        // 加载资源
        Resources res = this.getResources();
        star = BitmapFactory.decodeResource(res, R.drawable.star);
        // 获取原始图片宽高
        starWidth = star.getWidth();
        starHeight = star.getHeight();
        // 开始重绘视图
        new Thread(this).start();
    }

    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 重置旋转矩阵
        starMatrix.reset();
        // 设置旋转角度
        starMatrix.setRotate(starAngle);
        // 重绘旋转的图形
        Bitmap starBitmap = Bitmap.createBitmap(star, 0, 0, starWidth, starHeight, starMatrix, true);
        canvas.drawBitmap(starBitmap, 0, 0, null);
    }

    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                Thread.sleep(100);
                starAngle++; // 旋转角度
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            // 通知主线程更新图像
            this.postInvalidate();
        }
    }
}

上述代码中的TestImageView类是一个完整的重绘画布视图的例子。首先,该类继承自View基类,同时还包含了一个线程类的run方法,在该方法的逻辑中,每100ms进行一次重绘,即调用postInvalidate方法通知主线程更新图像。其次,在TestImageView类的构造方法中,主要包含了资源初始化的逻辑,这里程序加载了一个五星形状的图像资源文件。另外,在onDraw方法中,我们可以看到starMatrix变换矩阵的常见用法之一,即通过setRotate方法设置旋转的角度。该程序最终的运行效果,就是画出了一个绕着屏幕左上方顺时针旋转的五角星,如图2-14所示。
当然,我们还可以让图像绕着某个中心点旋转,这也不是问题,我们只需要对onDraw方法的逻辑稍做修改即可,修改过的逻辑实现如代码清单2-32所示。
代码清单 2-32

...
    public void onDraw(Canvas canvas) {
     super.onDraw(canvas);
     // 重置旋转矩阵
     starMatrix.reset();
     // 设置旋转中心
     float transX = 100;
     float transY = 100;
     float pivotX = starWidth/2;
     float pivotY = starHeight/2;
     starMatrix.setRotate(starAngle, pivotX, pivotY);
     starMatrix.postTranslate(transX, transY);
     // 重绘旋转的图形
     canvas.drawBitmap(star, starMatrix, null);
    }
...

要让图形绕着其中心旋转,首先要使用setRotate方法设置图形的旋转中心,然后再使用postTranslate方法把图形平移到相应的位置,即坐标(transX,transY)。该实例的运行效果如图2-15所示,我们可以看到屏幕上出现了一个不断自转的五角星。

当然,除了旋转之外,常见的图形变换还包括大小变换、倾斜变换等,限于篇幅,这里就不做介绍了,有兴趣的读者可以参考Matrix类文档中的preScale、postScale、preSkew、postSkew等方法。这里我们还需要注意的是pre和post系列方法的区别,带有pre前缀的方法表示此变换逻辑需要应用在所有变换逻辑之前,而带有post前缀的方法则表示此变换逻辑会依次往后排列,因此代码清单2-28中的旋转逻辑也可以使用代码清单2-33中的代码替代。
代码清单 2-33

...
    public void onDraw(Canvas canvas) {
     ...
     starMatrix.setTranslate(transX, transY);
     starMatrix.preRotate(starAngle, pivotX, pivotY);
     ...
    }
...
时间: 2024-11-05 14:51:02

《Android和PHP开发最佳实践》一2.8 Android图形界面的相关文章

《Android和PHP开发最佳实践》一2.7 Android应用界面

2.7 Android应用界面 Android应用界面系统,即Android UI(User Interface)系统是Android应用框架最核心的内容之一,也是开发者们需要重点掌握的内容.如果我们把Android应用也分为前后端两部分的话,那么之前介绍的核心要点和四大组件等都属于后端,而Android UI系统则属于前端.后端保证应用的稳定运行,而前端则决定应用的外观和体验.对于一个优秀的Android应用来说,漂亮的外观和流畅的体验是必不可少的.接下来,我们便来学习Android外观系统的

《Android和PHP开发最佳实践》一2.10 Android开发环境

2.10 Android开发环境 前面我们已经学习了Android系统中最重要的基础概念的内容,那么接下来就要开始正式进入Android应用的实战开发阶段."工欲善其事,必先利其器",因此,我们先来熟悉Android应用的开发环境吧. Android应用的开发环境是基于Eclipse平台的,Eclipse的强大无需多说,它当然也适应于Windows XP.Mac OS.Linux等多种操作系统.另外,我们还需要安装一些必备的开发工具包,所需要的软件见表2-8. 2.10.1 开发环境的

《Android和PHP开发最佳实践》一2.4 Android系统四大组件

2.4 Android系统四大组件 之前我们已经学习了Android应用框架的四大核心要点,对Android的应用框架有了一个总体性的了解,接下来我们要学习Android应用程序中的四个重要组成部分,也就是我们一般所说的"应用组件".在前面讲解四大核心要点的篇幅中,我们曾经提到了控件(View控件)的概念,现在我们再来学习一下Android应用框架中的组件的概念.那么何谓组件呢?顾名思义,组件当然要比控件复杂,简而言之,组件是用于工业化组装的部件.要达到组件的标准,必须符合三个要求,以

《Android和PHP开发最佳实践》一1.3 如何学习Android和PHP

1.3 如何学习Android和PHP 前面我们已经讨论过"为何学"的问题,大家应该对Android加PHP这套应用开发解决方案有了大致的了解.接下来介绍"如何学"的问题,由于本书的内容比较广泛,既涉及客户端开发的技术也包含很多服务端开发的内容,所以在正式开始学习本书之前,先搞清楚应该使用什么样的学习方法比较有效是非常有必要的.接下来,笔者会把这个问题分解为以下几个部分来探讨. 1.3.1 如何学习Android 由于Android学习是本书最核心的内容,因此我们先

《Android和PHP开发最佳实践》一2.9 Android动画效果

2.9 Android动画效果 适当地使用动画效果可以很好地提升Android应用或游戏的操作体验.目前Android系统支持的动画效果主要有两种,即逐帧动画(Frame Animation)和补间动画(Tween Animation).虽然,在Android 3.0以后的版本中还引入了新的动画系统,但是目前最主流的动画效果还是这两种. 2.9.1 逐帧动画(Frame Animation) 逐帧动画类似于GIF动画图片,即按照顺序播放图片.我们通常会在Android项目的res/drawabl

《Android和PHP开发最佳实践》一2.3 Android应用框架

2.3 Android应用框架 前面介绍了Android的系统框架,主要目的是让大家对Android系统有整体的概念,也为日后更深入的学习打好基础.然而,目前我们更需要重点学习和掌握的则是Android的应用框架,因为是否能掌握和理解Android应用框架,直接关系到是否能学好Android应用开发. Android的应用框架是一个庞大的体系,想要理解透彻并不是那么简单的事情,但是,好在其中有一些比较清晰的脉络可以帮助我们快速地熟悉这个系统,因此抓住这些脉络中的核心要点对于能否学好Android

《Android和PHP开发最佳实践 》一导读

前 言 2012年,移动互联网革命正在如火如荼地进行,一个充满机遇的巨大市场正在开启,无论是创业者还是从业者都需要做好准备.Android和PHP两种技术,作为目前移动领域和互联网领域中的热门技术,已经受到广大开发者们的关注. 本书是目前市面上唯一一本同时讲述Android客户端开发和PHP服务端开发两方面内容,并且把Android移动互联网应用开发的完整解决方案分析透彻的书籍.通过本书,您不仅可以学习到Android客户端开发技巧,而且可以掌握PHP服务端开发的精华,甚至还可以开拓软件架构的思

《Android和PHP开发最佳实践》一2.1 Android背景知识

2.1 Android背景知识 Android是一种基于Linux平台的.开源的.智能移动终端的操作系统,主要使用于便携设备,Android操作系统最初由Andy Rubin开发,主要支持手机设备.2005年由Google收购注资,并召集多家制造商组成"开放手机联盟"对其进行开发改良,并逐渐扩展到平板电脑及其他领域,近年来逐渐成为主流的移动终端操作系统之一. Android平台的研发队伍十分强大,包括Google.HTC.T-Mobile.高通.摩托罗拉.三星.LG以及中国移动在内的3

《Android和PHP开发最佳实践》一1.1 移动互联网时代的来临

1.1 移动互联网时代的来临 2011年,Android操作系统就已经占领了全球智能手机市场份额的半壁江山,霸主的地位彰显无遗(如图1-1所示).在国内,随着各大手机厂商的更新换代,Android操作系统的占有率也在火速上升中:中国移动公司已经早早推出了自己基于Android的OMS系统和OPhone,甚至连各大互联网巨头也在纷纷推出自己基于Android的手机产品.据统计,2012年内全球智能手机市场增长率达到49%,中国移动互联网用户量已经突破4亿,手机用户量也已经超越了PC. 看到这里,相