高级UI系列(一): 自定义UI理论篇(1)

简介: 自定义view是区分中级开发和初级开发的分水岭,虽说今年校招,工作三四年的老程序员一直在劝退客户端,作为职场打拼多年的老菜鸟,对android还是挺有信心的,虽说对view的知识也只是停留在纸上,很少真正落地做一些复杂高性能的ui控件,之前在akulaku确实见识了一群技术大牛,高级ui控件伸手就来,让我羡慕不已,这一次我也从基础到源码再到实战开始写几篇自定义view教程。大家有什么好的见解也欢迎到评论区多多交流。

1681529949430.png

自定义view是区分中级开发和初级开发的分水岭,虽说今年校招,工作三四年的老程序员一直在劝退客户端,作为职场打拼多年的老菜鸟,对android还是挺有信心的,虽说对view的知识也只是停留在纸上,很少真正落地做一些复杂高性能的ui控件,之前在akulaku确实见识了一群技术大牛,高级ui控件伸手就来,让我羡慕不已,这一次我也从基础到源码再到实战开始写几篇自定义view教程。大家有什么好的见解也欢迎到评论区多多交流。

一. 自定义UI的基本方法

  说到自定义view,我们就能联想到最基本的三个方法: onmeasure()onlayout()ondraw();view能在activity显示出来。

  都要经历测量布局绘制三个步骤,而这三个步骤分别对应三个动作:measurelayoutdraw。那他们分别代表什么作用呢?

1681529996578.png

  • 测量onmeasure()决定view的大小;
  • 布局onlayout()决定viewviewgroup中的位置;
  • 绘制ondraw()决定绘制这个view

二. 自定义UI分类

 按照ui继承属性来说,其实自定义view大概可分为两种,一种是自定义单view,一种是自定义viewgroup,自定义单view又根据重写方法不同分为,自绘view和继承view,他们的区别是:自绘view仅仅设置特定ui,不会涉及交互,继承view是基于系统特殊控件,保留原有功能,加以扩展。自定义viewgroup直接让组合控件成为一个新的父布局控件,这种方式难度有点大。

1681530049366.png

  1. 自定义View
  • 只需要重写onmeasure()ondraw()
  1. 自定义viewgroup
  • 则只需要重写onmeasure()onlayout()

三. 自定义UI基础

3.1 view的分类

  刚刚说了,视图View主要分为两类,这边我再次总结一下:

类别 解释 特点
自定义单view 即一个view,如textview 不包含子view
自定义viewgroup 即多个view组成的viewgroup,如LinearLayout 包含子view

3.2 view类简介

  学习自定义view,我们首先得知道,它是干什么用的,为什么会有这个东西?然后了解他里面是如何实现的?这边先聊聊他为什么会在android里出现,总结原因有两个:

  • view类是android中各种组件的基类,如viewviewgroup基类
  • view表现为显示在屏幕上的各种视图

android中的ui组件都由viewviewgroup组成。

点开view源码,我们发现里面有四个关键的构造函数,下面我就详细讲解一下,每个构造方法所代表的现实意义吧。

1681530111004.png

源码分析:

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

3.3 attributeset与自定义属性

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

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

3.4 view视图结构

  对于多view的视图,结构是树形结构:最顶层是viewgroupviewgroup下可能有多个viewgroupview,如下图:

1681530273407.png

  1. phonewindowandroid系统中最基本的窗口系统,继承自windows类,负责管理界面显示以及事件响应。它是activityview系统交互的接口
  2. decorviewphonewindow中的起始节点view,继承于view类,作为整个视图容器来使用。用于设置窗口属性。它本质上是一个framelayout
  3. viewrootactivtiy启动时创建,负责管理布局渲染窗口UI等等

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

1681530403570.png

3.5 android坐标系

android的坐标系定义为:

  • 屏幕的左上角为坐标原点
  • 向右为x轴增大方向
  • 向下为y轴增大方向
  • 1681530460320.png
  •  ❌ 注意事项: 不要把他和的数学坐标系搞混了
  • 1681530567693.png

3.6 view位置(坐标)描述

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

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

1681530635794.png

  1. Top:子view上边界到父view上边界的距离
  2. Left:子view左边界到父view左边界的距离
  3. Bottom:子view下边距到父view上边界的距离
  4. Right:子view右边界到父view左边界的距离

3.7 view位置获取方式

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

// 获取Top位置
public final int getTop() {
return mTop;
}
// 其余如下:
getLeft(); // 获取子View左上角距父View左侧的距离
getBottom(); // 获取子View右下角距父View顶部的距离
getRight(); // 获取子View右下角距父View左侧的距离

1681530685102.png

MotionEventget()getRaw()的区别

//get() :触摸点相对于其所在组件坐标系的坐标
event.getX();
event.getY();
//getRaw() :触摸点相对于屏幕默认坐标系的坐标
event.getRawX();
event.getRawY();

3.8 android中颜色相关内容

3.8.1 Android支持的颜色模式:

1681530789083.png

3.8.2 以ARGB8888为例介绍颜色定义:

1681530819288.png


相关文章
|
5天前
|
JavaScript 前端开发
Vue实现Element UI框架的自定义输入框或下拉框在输入时对列表选项进行过滤,以及右键列表选项弹出菜单进行删除
本文介绍了如何在Vue框架结合Element UI库实现自定义输入框或下拉框,在输入时对列表选项进行过滤,并支持右键点击列表选项弹出菜单进行删除的功能。
6 0
|
1月前
|
JavaScript
vue + element UI 表单中内嵌自定义组件的表单校验触发方案
vue + element UI 表单中内嵌自定义组件的表单校验触发方案
43 5
|
2月前
|
XML IDE 开发工具
【Android UI】自定义带按钮的标题栏
【Android UI】自定义带按钮的标题栏
41 7
【Android UI】自定义带按钮的标题栏
|
1月前
Element UI【实战范例】下拉选择 el-select 的 change 事件传入选中值+自定义参数
Element UI【实战范例】下拉选择 el-select 的 change 事件传入选中值+自定义参数
110 1
|
1月前
Element UI 源码改造 —— 自定义数字输入框的实现
Element UI 源码改造 —— 自定义数字输入框的实现
36 1
|
1月前
|
容器
Element UI 自定义环形进度条里的内容
Element UI 自定义环形进度条里的内容
68 2
|
1月前
|
数据安全/隐私保护
Element UI 密码输入框--可切换显示隐藏,自定义图标
Element UI 密码输入框--可切换显示隐藏,自定义图标
66 0
|
1月前
Element UI 【表格合计】el-table 实战范例 -- 添加单位,自定义计算逻辑
Element UI 【表格合计】el-table 实战范例 -- 添加单位,自定义计算逻辑
38 0
|
1月前
【亲测有效】Element UI 自定义 Notification 通知样式不生效,设置this.$notify样式不生效问题
【亲测有效】Element UI 自定义 Notification 通知样式不生效,设置this.$notify样式不生效问题
26 0
|
1月前
Element UI 自定义/修改下拉弹窗的样式(如级联选择器的下拉弹窗样式)
Element UI 自定义/修改下拉弹窗的样式(如级联选择器的下拉弹窗样式)
34 0