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

简介: 本节书摘来自华章出版社《Android和PHP开发最佳实践》一书中的第2章,第2.8节,作者 黄隽实,更多章节内容可以访问云栖社区“华章计算机”公众号查看

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中。
image

以上方法常用于画笔初始化的配置逻辑中,接下来让我们来学习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中。
image

2.8.2 画布(Canvas)

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

然而,游戏应用的画布中通常不只有一个图形,通常需要对其中的某些图形进行特殊处理,比如旋转、变形等,此时需要先使用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);
     ...
    }
...
相关文章
|
4月前
|
数据采集 存储 缓存
PHP爬虫的使用与开发
本文深入探讨了PHP爬虫的使用与开发,涵盖基本原理、关键技术、开发实践及优化策略。从发送HTTP请求、解析HTML到数据存储,再到处理反爬机制,全面指导读者构建高效可靠的爬虫程序。
118 3
|
1月前
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
140 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
1月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
259 76
|
4天前
|
前端开发 PHP 开发者
Wordpress主题开发之index.php
本文介绍了 WordPress 主题开发中页面结构与模板文件的使用方法。通过 header.php、sidebar.php、footer.php 和 index.php 等模板文件,实现网站模块化设计,便于统一管理和代码重用。Header 部分包含 logo、导航条等;Content 展示主体内容;Side bar 显示推荐信息或广告;Footer 则呈现版权和备案信息等内容。文章还提供了各模板文件的具体代码示例,帮助开发者快速理解和应用 WordPress 模板机制。
|
7天前
|
API PHP 数据库
PhalApi 2.x:让PHP接口开发从“简单”到“极简”的开源框架
PhalApi 2.x 是一款专为接口开发设计的轻量级PHP框架,性能卓越且易于上手。它支持多协议、自动生成文档、提供多种客户端SDK,并采用现代化技术栈,适合中小型项目及微服务架构。通过清晰的分层架构和丰富的扩展库,开发者可快速构建高可用API。其日均超1000万次调用,广泛应用于移动App、物联网、电商等领域。官网:https://www.phalapi.net/,欢迎体验高效开发之旅!
|
2月前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
83 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
2月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
217 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
2月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
72 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
3月前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
174 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
2月前
|
安全 Android开发 iOS开发
escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
escrcpy 是一款基于 Scrcpy 的开源项目,使用 Electron 构建,提供图形化界面来显示和控制 Android 设备。它支持 USB 和 Wi-Fi 连接,帧率可达 30-120fps,延迟低至 35-70ms,启动迅速且画质清晰。escrcpy 拥有丰富的功能,包括自动化任务、多设备管理、反向网络共享、批量操作等,无需注册账号或广告干扰。适用于游戏直播、办公协作和教育演示等多种场景,是一款轻量级、高性能的 Android 控制工具。
116 1