Android自定义View

本文详细探讨了Android自定义View的重要性和基本方法,包括onMeasure()、onLayout()、onDraw()三个关键步骤。文章介绍了自定义View的分类、View的构造、属性配置、视图结构、坐标系、位置描述以及View树的绘制流程。同时,讲解了LayoutParams、MarginLayoutParams、MeasureSpec及其在自定义View中的应用,为开发者提供深入理解自定义View的全面指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android自定义View

概述

Android开发进阶的必经之路

为什么要自定义View

自定义View的基本方法

自定义View的最基本的三个方法分别是: onMeasure()、onLayout()、onDraw();
View在Activity中显示出来,要经历测量、布局和绘制三个步骤,分别对应三个动作:measure、layout和draw。

  • 测量:onMeasure()决定View的大小;
  • 布局:onLayout()决定View在ViewGroup中的位置;
  • 绘制:onDraw()决定绘制这个View。

自定义控件分类

  • 自定义View: 只需要重写onMeasure()和onDraw()
  • 自定义ViewGroup: 则只需要重写onMeasure()和onLayout()

自定义View基础

View的分类

视图View主要分为两类

类别 解释 特点
单一视图 即一个View,如TextView 不包含子View
视图组 即多个View组成的ViewGroup,如LinearLayout 包含子View

View类简介

  • View类是Android中各种组件的基类,如View是ViewGroup基类
  • View表现为显示在屏幕上的各种视图

Android中的UI组件都由View、ViewGroup组成。

  • View的构造函数:共有4个

    // 如果View是在Java代码里面new的,则调用第一个构造函数
     public CarsonView(Context context) {
         
         
            super(context);
        }
    
    // 如果View是在.xml里声明的,则调用第二个构造函数
    // 自定义属性是从AttributeSet参数传进来的
        public  CarsonView(Context context, AttributeSet attrs) {
         
         
            super(context, attrs);
        }
    
    // 不会自动调用
    // 一般是在第二个构造函数里主动调用
    // 如View有style属性时
        public  CarsonView(Context context, AttributeSet attrs, int defStyleAttr) {
         
         
            super(context, attrs, defStyleAttr);
        }
    
        //API21之后才使用
        // 不会自动调用
        // 一般是在第二个构造函数里主动调用
        // 如View有style属性时
        public  CarsonView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         
         
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    

AttributeSet与自定义属性

系统自带的View可以在xml中配置属性,对于写的好的自定义View同样可以在xml中配置属性,为了使自定义的View的属性可以在xml中配置,需要以下4个步骤:

  1. 通过<declare-styleable>为自定义View添加属性
  2. 在xml中为相应的属性声明属性值
  3. 在运行时(一般为构造函数)获取属性值
  4. 将获取到的属性值应用到View

View视图结构

  1. PhoneWindow是Android系统中最基本的窗口系统,继承自Windows类,负责管理界面显示以及事件响应。它是Activity与View系统交互的接口
  2. DecorView是PhoneWindow中的起始节点View,继承于View类,作为整个视图容器来使用。用于设置窗口属性。它本质上是一个FrameLayout
  3. ViewRoot在Activtiy启动时创建,负责管理、布局、渲染窗口UI等等

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6oxIfJvh-1622431238679)(.\assets\activity.png)]

对于多View的视图,结构是树形结构:最顶层是ViewGroup,ViewGroup下可能有多个ViewGroup或View,如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e4vnqsqm-1622431238686)(.\assets\view_arch.png)]

一定要记住:无论是measure过程、layout过程还是draw过程,永远都是从View树的根节点开始测量或计算(即从树的顶端开始),一层一层、一个分支一个分支地进行(即树形递归),最终计算整个View树中各个View,最终确定整个View树的相关属性。

Android坐标系

Android的坐标系定义为:

  • 屏幕的左上角为坐标原点
  • 向右为x轴增大方向
  • 向下为y轴增大方向
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xadBtCJA-1622431238691)(.\assets\zuobiaoxi.png)]

区别于一般的数学坐标系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NfoepapF-1622431238705)(.\assets\zuobiaoxi_qubie.png)]

View位置(坐标)描述

View的位置由4个顶点决定的
4个顶点的位置描述分别由4个值决定:

请记住:View的位置是相对于父控件而言的)

  • Top:子View上边界到父view上边界的距离
  • Left:子View左边界到父view左边界的距离
  • Bottom:子View下边距到父View上边界的距离
  • Right:子View右边界到父view左边界的距离

位置获取方式

View的位置是通过view.getxxx()函数进行获取:(以Top为例)

// 获取Top位置
public final int getTop() {
   
     
    return mTop;  
}  

// 其余如下:
  getLeft();      //获取子View左上角距父View左侧的距离
  getBottom();    //获取子View右下角距父View顶部的距离
  getRight();     //获取子View右下角距父View左侧的距离

与MotionEvent中 get()和getRaw()的区别

//get() :触摸点相对于其所在组件坐标系的坐标
 event.getX();       
 event.getY();

//getRaw() :触摸点相对于屏幕默认坐标系的坐标
 event.getRawX();    
 event.getRawY();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r3jwBnMn-1622431238707)(.\assets\zuobiaoxiweizhi.png)]

Android中颜色相关内容

Android支持的颜色模式:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yPcTeO7b-1622431238709)(.\assets\color1.png)]
以ARGB8888为例介绍颜色定义:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Glnx6Aom-1622431238713)(.\assets\color2.png)]

View树的绘制流程

View树的绘制流程是谁负责的?

view树的绘制流程是通过ViewRoot去负责绘制的,ViewRoot这个类的命名有点坑,最初看到这个名字,翻译过来是view的根节点,但是事实完全不是这样,ViewRoot其实不是View的根节点,它连view节点都算不上,它的主要作用是View树的管理者,负责将DecorView和PhoneWindow“组合”起来,而View树的根节点严格意义上来说只有DecorView;每个DecorView都有一个ViewRoot与之关联,这种关联关系是由WindowManager去进行管理的;

view的添加

在这里插入图片描述

view的绘制流程

在这里插入图片描述

measure

  1. 系统为什么要有measure过程?
  2. measure过程都干了点什么事?
  3. 对于自适应的尺寸机制,如何合理的测量一颗View树?
  4. 那么ViewGroup是如何向子View传递限制信息的?
  5. ScrollView嵌套ListView问题?

在这里插入图片描述

layout

  1. 系统为什么要有layout过程?
  2. layout过程都干了点什么事?

在这里插入图片描述

draw

  1. 系统为什么要有draw过程?
  2. draw过程都干了点什么事?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值