View与自定义View

View基础

1.简介
  • View类是Android中各种组件的基类(如View是ViewGroup基类)。

  • View表现为显示在屏幕上的各种视图,Android中的UI组件都由View、ViewGroup组成。

  • 它定义了所有UI组件共有的特性和行为(绘制、事件处理、状态变化……)。

2.分类
  • 单一视图 :即一个View,(如TextView),不包含子View。
  • 视图组:即多个View组成的ViewGroup(如LinearLayout) 包含子View。
3.视图结构

  • PhoneWindow是Android系统中最基本的窗口系统,继承自Windows类,负责管理界面显示以及事件响应。它是Activity与View系统交互的接口。

  • DecorView是PhoneWindow中的起始节点View,继承于View类,作为整个视图容器来使用。用于设置窗口属性。

  • ViewRoot在Activtiy启动时创建,负责管理、布局、渲染窗口UI等等。

  • View的层级结构是树形的,遍历时遵循自上而下的顺序(树形递归)。
4.生命周期

测量(Measure)

  • 系统会调用onMeasure()方法来确定View的大小。
  • 这个方法通常会调用getDefaultSize()来获取布局文件中定义的宽度和高度,或者根据子视图来计算大小。

布局(Layout)

  • 系统会调用onLayout()方法来确定View及其子视图在父视图中的位置。
  • 这个方法是在所有子视图的onMeasure()方法都被调用之后调用的。

绘制(Draw)

  • 系统会调用onDraw()方法来绘制View的内容。
  • 这个方法通常会在视图的布局确定之后调用。

状态变化(State Change)

  • View的状态发生变化时(例如,是否选中、是否禁用、是否有焦点等),会调用相应的回调方法,如onDrawableStateChanged()

焦点变化(Focus Change)

  • View获取或失去焦点时,会调用onFocusChange()方法。

触摸事件(Touch Event)

  • 当用户与View交互时,会调用触摸事件相关的回调方法,如onTouchEvent()onKeyDown()onKeyUp()等。

布局变化(Layout Change)

  • View的布局参数发生变化时,会调用onLayoutChange()方法。

视图回收(View Recycling)

  • View不再可见时,系统可能会将其回收以重用。被回收的View对象会被放入一个回收池中,等待未来重新使用。
5.绘制流程

在这里插入图片描述

View 类的 performTraversals() 方法,它内部会调用一系列的回调方法来完成这些任务。

测量(Measure):

  • 系统会调用ViewonMeasure()方法来确定View的大小。在这个阶段,View会确定自己的宽度和高度,可以通过setMeasuredDimension()方法来设置测量结果。

布局(Layout):

  • 在测量完成后,系统会调用ViewonLayout()方法,在这个方法中,View会计算其在容器中的位置,即确定其左上角的位置。

绘制(Draw):

  • 系统会调用ViewonDraw()方法来绘制View的内容。在这个阶段,View可以调用Canvas对象的绘图方法来绘制自己。这包括绘制文本、图像、形状等。

自定义View

1.分类
  • 自定义View

    • 在没有现成的View,需要自己实现的时候,就使用自定义View。

    • 一般继承自View,SurfaceView或其他的View。

    • 自定义View主要是实现 onMeasure + onDraw

  • 自定义ViewGroup

    • 自定义ViewGroup一般是利用现有的组件根据特定的布局方式来组成新的组件。
    • 大多继承自ViewGroup或各种Layout。
    • 自定义ViewGroup主要是实现onMeasure + onLayout
2.基本方法
  • View在Activity中显示出来,要经历测量、布局和绘制三个步骤,分别对应三个动作:measure、layout和draw。
  • 测量:onMeasure()决定View的大小;
  • 布局:onLayout()决定View在ViewGroup中的位置;
  • 绘制:onDraw()决定绘制这个View。
3.自定义View的绘制流程

在这里插入图片描述

4.View的坐标与位置
  • Android的坐标系定义为:屏幕的左上角为坐标原点,向右为x轴增大方向,向下为y轴增大方向。

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

    Top:子View上边界到父view上边界的距离。

    Left:子View左边界到父view左边界的距离。

    Bottom:子View下边距到父View上边界的距离。

    Right:子View右边界到父view左边界的距离。

MeasureSpec

1.简介
  • 用来描述一个视图(View)或者布局(Layout)的测量规格。
  • MeasureSpec 包含了视图需要测量的大小限制信息,包括宽度和高度的限制。
  • 在视图层次结构中的每个节点在布局过程中都会经历两次测量过程:一次用于确定其宽度的测量规格,另一次用于确定其高度的测量规格。
  • 测量规格由MeasureSpec类表示,它是一个int值,可以分解为两个部分:模式(Mode)和大小(Size)。
  • MeasureSpec是View中的内部类,基本都是二进制运算。由于int是32位的,用高两位表示mode,低30位表示size,MODE_SHIFT = 30的作用是移位。
2.模式部分对子视图的限制
  • UNSPECIFIED:父视图没有对子视图的尺寸做任何限制,子视图可以任意大小。
  • EXACTLY:父视图精确地确定了子视图的大小,子视图必须严格按照这个大小来测量。
  • AT_MOST:父视图对子视图的大小做了最大值的限制,子视图的大小不能超过这个限制,但可以小于这个限制。
3.LayoutParams与MeasureSpec的关系
  • 在视图的测量阶段(Measure phase),视图会根据其LayoutParams以及父视图的MeasureSpec来确定自己的尺寸。

  • MeasureSpec提供了父视图对子视图尺寸的限制信息,而LayoutParams则提供了子视图对自己尺寸的期望或要求。

    视图确定尺寸的过程

    • 父视图通过MeasureSpec提供了对子视图尺寸的限制。

    • 子视图根据自己的LayoutParams以及父视图的MeasureSpec来确定自己的尺寸。

    • 如果子视图是ViewGroup,它还需要对它的子视图递归地调用measure方法来进行测量。

    果一个LinearLayoutLayoutParams设置了一个固定宽度,而父视图的MeasureSpecAT_MOST模式,那么子视图的最终宽度将由其LayoutParams中的宽度值和父视图的可用空间共同决定。

4.进行measure的意义
  • 响应布局变化:当视图的布局参数发生变化时(例如,LinearLayoutLayoutParams中宽度或高度的值发生变化),视图需要重新测量以反映新的尺寸。
  • 适应父视图空间:视图需要根据父视图提供的空间(由MeasureSpec表示)来确定自己的大小。父视图可能限制了视图的最大尺寸,或者提供了视图可以使用的可用空间。
  • 视图间的关系:在有约束的布局中(如ConstraintLayout),视图之间可能存在依赖关系,如Match_ParentWrap_Content。这些关系需要在测量阶段解决,以确保视图按预期分配空间。
  • 内容自适应:对于内容驱动的视图(如TextView),其内容的大小可能会改变(例如,文本被剪切或滚动),这时视图需要重新测量以适应新的内容尺寸。
  • 布局重排:当视图树的结构发生变化时(例如,新的视图被添加或删除),整个视图树可能需要重新测量和布局,以确保所有视图都正确放置和大小。
  • 属性变化:视图的某些属性可能会影响其大小,例如android:layout_marginandroid:padding等。当这些属性发生变化时,视图需要重新测量。
  • 屏幕方向变化:当设备屏幕方向变化时(例如,从 portrait 到 landscape),视图的尺寸可能会发生变化,因此需要重新测量。
  • 属性变化:视图的某些属性可能会影响其大小,例如android:layout_marginandroid:padding等。当这些属性发生变化时,视图需要重新测量。
  • 屏幕方向变化:当设备屏幕方向变化时(例如,从 portrait 到 landscape),视图的尺寸可能会发生变化,因此需要重新测量。
  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值