IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 自定义View学习 -> 正文阅读

[游戏开发]自定义View学习

  • 自定义View是Android中的一个重要部分,设计需要对UI界面进行定制化时,往往会用到自定义View的相关知识。

学习来源:Carson带你学自定义View

自定义View的类型

1、自定义组合控件:多个控件组合成一个新的控件,方便复用,例如项目中使用的自定义Dialog。
2、继承系统子View:继承系统的原生View再进行扩展,例如项目中的NumKeyView。
3、继承系统ViewGroup:继承自LinearLayout等系统控件,在系统控件的基础功能上进行扩展。

自定义View的基础概念:

1、Android中的坐标系:

在Android坐标系中,以屏幕的左上角为原点,原点往右为正,往下为正。如下图:
在这里插入图片描述

2、View坐标系:

在View当中,其位置都是使用与父View的位置来进行确定的,如下图:

在这里插入图片描述

通过与父View的相对位置来进行确定子View的位置。主要有以下4个情况:

  • 顶部(Top):视图左上顶点到父控件上边界的距离;
  • 左边(Left):视图左上顶点到父控件左边界的距离;
  • 右边(Right):视图右下顶点到父控件左边界的距离;
  • 底部(Bottom):视图右下顶点到父控件上边界的距离。
    对应的获取方法:
  • getLeft():获取View到其父布局左边的距离。
  • getRight():获取View到其父布局左边的距离
  • getTop():获取View到其父布局顶边的距离
  • getBottom():获取View到其父布局底边的距离

3、几个重要的类:

Activity:
负责控制生命周期、处理事件。通过其他的触摸事件回调方法来与Window、View交互。但是不负责真正的View绘制。
Window:
视图的承载器。可以理解为整个的手机的屏幕,其唯一实现类的PhoneView,内部通过windowManager进行管理,将DecorVIew传递给ViewRoot进行绘制逻辑。
DecorView:
顶级VIew,也就是所有VIew 的根节点,本质上是一个FrameLayout的子类,包含标题栏、内容栏两部分。
ViewRoot:
连接器,负责连接windowManagerService和DecorView,同时负责真正的绘制逻辑。也就是onMesure() -> onLayout() -> onDraw();同时也负责wMS通讯,向decorWindow传递事件

其关系见图:

在这里插入图片描述

  • 来自Carson的文章

绘制前的准备工作:
从Activity的onCreate的setContentView开始:

  1. 创建window类,也就是创建对应的phoneWindow。
  2. 为phoneWindow创建对应的WindowManeger。
  3. 创建DecorView,同时为其设置相关的布局文件。
  4. 将DecorView放入到WindowManager中。
  5. 创建ViewRoot对象。
  6. 通过WIndowManager将DecorView传递给ViewRoot。
  7. 开始绘制。

绘制流程:
基本绘制流程:onMeasure() (确定大小)-> onLayout()(确定位置) -> onDraw()(实际绘制)。
onMeasure()

学习onMeasure()前要先了解两个基本的类:
ViewGroup.layoutParams: 指定View的高度和宽度以及其他布局参数。通过xml配置后得来。

MeasureSpec:测量规格类,用来设置view的大小。本质上是一个32位INT类型组成。包含两部分内容信息:
1、 测量模式(mode):占测量规格的前2位,主要分为三种:EXACTLY(精确模式)、AT_MOST(最大限定模式)、UNSPECIED(无限制)。
2、设置大小,也就是设置的精确大小。
三种模式的区别:(重要)
在这里插入图片描述

onMeasure的流程:

对于单一的View绘制:
整体绘制流程图:

在这里插入图片描述
1、measure():measure的入口,通过该入口开始执行measure流程,在此调用onMeasure()方法开始真正测量。
2、onMesure():测量的真正逻辑,在此进行真正的测量。
3、setMeasureDimension(): 保存测量的结果,一般来说onMeasure可能会执行多次,最后在此方法保存结果。

onMeasure()源码:

 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
   // 参数说明:View的宽 / 高测量规格
   setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),  
                        getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));  
   // setMeasuredDimension() :保存View宽/高的测量值
   // 也就是通过getDefaultSize方法传输宽度和高度的MeasureSpec后,把该数据进行保存,完成测量过程

getDefaultSize()源码:

  public static int getDefaultSize(int size, int measureSpec) {  

    // 参数说明:
    // size:提供的默认大小
    // measureSpec:宽/高的测量规格(含模式 & 测量大小)

    // 设置默认大小
    int result = size; 
        
    // 获取宽/高测量规格的模式 & 测量大小
    int specMode = MeasureSpec.getMode(measureSpec);  
    int specSize = MeasureSpec.getSize(measureSpec);  
  
    switch (specMode) {  
        // 模式为UNSPECIFIED时,使用提供的默认大小 = 参数Size
        case MeasureSpec.UNSPECIFIED:  
            result = size;  
            break;  

        // 模式为AT_MOST,EXACTLY时,使用View测量后的宽/高值 = measureSpec中的Size
        case MeasureSpec.AT_MOST:  
        case MeasureSpec.EXACTLY:  
            result = specSize;  
            break;  
    }  

    // 返回View的宽/高值
    return result;  
  }    

对于的ViewGroup的绘制:
基本绘制流程图:
在这里插入图片描述

测量流程:
1、measure():measure的入口,通过该入口开始执行measure流程,在此调用onMeasure()方法开始真正测量。

2、onMesure():需要进行复写的方法。在此遍历所有的子VIew,计算出所有的子View的宽高,最后进行合并成最终的ViewGroup尺寸。同时还要在此执行保存尺寸的逻辑。

3、measureChidren():遍历所有的子View,并且调用measureChild()方法测量子View的大小。

4、measureChild():计算子View的大小,同时在此进行一次measure()的流程。

5、getChildMeasureSpec():获得子View的测量大小

6、setMeasureDimension(): 保存测量的结果,一般来说onMeasure可能会执行多次,最后在此方法保存结果。

onLayout()流程

流程图:
在这里插入图片描述

  • 来自Carson的图

onLayout的流程与onMeasure类似,也是通过计算layout的四个顶点,计算时若有子View计算子View的四个顶点位置,最后保存到 mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom)中

onDraw():

绘制的过程也是与onMeasure()流程相似,基本流程图:
在这里插入图片描述

1、draw():绘制的入口。
2、drawBackground():绘制背景。
3、onDraw():绘制本身的内容。
4、disPathDraw():绘制子View,这个不一定有。
5、onDrawScrollBars():绘制装饰边,例如颜色,滑动条等等。
也可以从源码看出来,绘制的过程中,主要流程:绘制背景->绘制本身->绘制子类->绘制装饰类。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:42:53  更:2022-04-04 12:45:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年10日历 -2024/10/25 8:24:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码