zoukankan      html  css  js  c++  java
  • Android群英传知识点回顾——第三章:Android控件架构与自定义控件详解


    • 3.1 Android控件架构
    • 3.2 View的测量
    • 3.3 View的绘制
    • 3.4 ViewGroup的测量
    • 3.5 ViewGroup的绘制
    • 3.6 自定义View
      • 3.6.1 对现有的空间进行拓展
      • 3.6.2 创建复合控件
      • 3.6.3 重写View来实现全新的空间
    • 3.7 自定义ViewGroup
    • 3.8 事件拦截机制分析

    控件大致非为两类:

    • view控件:视图控件
    • viewGroup控件:包含多个View控件,并管理其包含的View控件
    • 两者之间的关系:上层控件负责下层子控件的测量与绘制,并传递交互事件

    UI界面架构:

    • Activity都包含一个Window对象,通常由PhoneWindow来实现
    • PhoneWindow将一个DecorView设置为整个应用窗口的根View
      • DecorView为整个Window界面的最顶层View
      • DecorView只有一个子元素为LinearLayout,代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域
      • LinearLayout里有两个FrameLayout子元素:
        • 标题栏显示界面。只有一个TextView显示应用的名称
        • 内容栏显示界面。就是setContentView()方法载入的布局界面

    MeasureSpec类:32位的int值,高2位为测量模式,低30位为测量大小

    MeasureSpec模式:

    • EXACTLY:精确模式 ,当控件的layout_width属性或layout_height属性指定为具体值,控件大小也是该具体值
    • AT_MOST:最大值模式,当控件layout_width属性或layout_height属性指定为warp_content时,控件的尺寸不要超过父控件允许的最大尺寸
    • UNSPECIFIED:未指定模式,控件要多大就多大,通常情况下再绘制自定义View中才会使用

    View类默认的onMeasure()方法只支持EXACTLY模式,View需要支持warp_content属性,那么就必须重写onMeasure()方法,来制定warp_content的大小

    下面我们通过一个简单的实例,演示如何进行View的测量,首先,需要重写onMeasure()方法:

    可以发现,onMeasure方法调用了父类的onMeasure方法,代码跟踪父类onMeasure方法

    可以发现,系统最终会调用setMeasuredDimension(int measuredWidth,int measuredHeight)方法将测量后的宽高值设置进去,我们调用自定义的measureWidth()方法和measureHeight()方法,分别对宽高进行重新定义

    下面以measureWidth()方法为例:

    第一步:从MeasureSpec对象中提取出具体的测量模式和大小

    第二步:通过不同的测量模式给出不同的测量值:

    • EXACTLY:使用指定的specSize即可
    • AT_MOST:取出我们指定的大小和SpecSize的最小值
    • UNSPECIFIED:200px

    下面这段代码基本上可以作为模板代码:

    可以发现,当指定warp_content属性时,View就获得一个默认值200px

    当测量好了一个View之后,我们通过重写View类中的onDraw()方法来绘图,要想绘制相应的图像,就必须在Canvas上进行绘制

    Canvas就像是一个画板,我们传进去一个bitmap,通过这个bitmap创建的Canvas画布紧紧联系在一起,这个过程我们称之为装载画布,这个bitmap用来存储所有绘制在Canvas上的像素信息,所以当你在后面调用所有的Canvas.drawxxx方法都会发生在这个bitmap上

    ViewGroup在测量时通过遍历所有子View,从而调用子View的Measure方法来获得每一个子View的结果

    ViewGroup测量完毕后,通常会去重写onLayout()方法来控制其子View显示位置的逻辑

    ViewGroup通常不需要绘制,如果不是指定ViewGroup的背景颜色,那么ViewGroup的onDraw()方法都不会被调用,但是,ViewGroup会使用dispatchDraw()方法来绘制子View

    在View中通常有以下一些重要的回调方法:

    • onFinishInflate():从XML加载组件后回调
    • onSizeChanged():组件大小改变时回调
    • onMeasure():回调该方法来进行测量
    • onLayout():回调该方法来确定显示的位置
    • onTouchEvent():监听到触摸事件时回调

    通常情况下,有以下三种方法来实现自定义的控件:

    • 对现有的控件进行拓展
    • 通过组合来实现新的控件
    • 重写View来实现全新的控件

    3.6.1 对现有的控件进行拓展

    • 自定义修改TextView……见经典代码回顾,案例一
    • 闪动的文字效果……见经典代码回顾,案例二

    3.6.2 创建复合控件

    • 自定义ToolBar的实现……见经典代码回顾,案例三

    3.6.3 重写View来实现全新的控件

    • 弧线展示图……见经典代码回顾,案例四
    • 音频条形图……见经典代码回顾,案例五
    • 自定义ViewGroup,仿ScrollView……见经典代码回顾,案例六

    事件拦截机制三个重要方法

    • dispatchTouchEvent():分发事件
    • onInterceptTouchEvent():拦截事件
    • onTouchEvent():处理事件

    举一个例子说明事件分发机制:

    • ViewGroupA:处于视图最下层
    • ViewGroupB:处于视图中间层
    • View:处于视图最上层

    正常的事件分发机制流程:

    • ViewGroupA dispatchTouchEvent
    • ViewGroupA onInterceptTouchEvent
    • ViewGroupB dispatchTouchEvent
    • ViewGroupB onInterceptTouchEvent
    • View dispatchTouchEvent
    • View onTouchEvent
    • ViewGroupB onTouchEvent
    • ViewGroupA onTouchEvent

    若ViewGroupB的onInterceptTouchEvent()方法返回true的分发机制流程:

    • ViewGroupA dispatchTouchEvent
    • ViewGroupA onInterceptTouchEvent
    • ViewGroupB dispatchTouchEvent
    • ViewGroupB onInterceptTouchEvent
    • ViewGroupB onTouchEvent
    • ViewGroupA onTouchEvent

    若View的onTouchEvent()方法返回true的分发机制流程:

    • ViewGroupA dispatchTouchEvent
    • ViewGroupA onInterceptTouchEvent
    • ViewGroupB dispatchTouchEvent
    • ViewGroupB onInterceptTouchEvent
    • View dispatchTouchEvent
    • View onTouchEvent

    若ViewGroupB的onTouchEvent()方法返回true的分发机制流程:

    • ViewGroupA dispatchTouchEvent
    • ViewGroupA onInterceptTouchEvent
    • ViewGroupB dispatchTouchEvent
    • ViewGroupB onInterceptTouchEvent
    • View dispatchTouchEvent
    • View onTouchEvent
    • ViewGroupB onTouchEvent

    简单的说dispatchTouchEvent()和onInterceptTouchEvent()是从下往上一层一层分发下去的,而onTouchEvent()是从上往下一层一层分发下去的




    在values文件夹中创建一个attrs.xml文件来自定义属性

    开始创建我们的ToolBar

    在布局文件中使用


    当用户不指定具体的比例值时,可以调用以下代码来设置相应的比例值



    自定义的ScrollView没有系统自带的性能好,毕竟很多因素都没考虑到,这里只是适用于练手使用

    在布局中使用

    经典回顾源码下载

    github:https://github.com/CSDNHensen/QunYingZhuang

  • 相关阅读:
    Python-zip压缩-解压
    使用zabbix监控nginx
    原已经安装好的nginx,现在需要添加一个未被编译安装的模块:
    zabbix 邮件告警配置
    lnmp-zabbix
    Mysql新建用户和数据库并授权
    git标签管理
    Ubuntu下安装tomcat
    git分支管理
    Java拦截器
  • 原文地址:https://www.cnblogs.com/zhanglixina/p/9603816.html
Copyright © 2011-2022 走看看