博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
View绘制系列(3)-自定义View简介
阅读量:4256 次
发布时间:2019-05-26

本文共 2852 字,大约阅读时间需要 9 分钟。

自定义View简介

经过前面两篇文章的介绍,相信大多数同学已经清楚的认识了View,那么我们来看下自定义View这个主题,在小册简介中,我们已经描述了自定义View的目的,同学们还记得吗?用于解决使用系统控件实现不了或实现比较复杂的UI效果。

View简介部分,我们看到不管是XXXLayout还是XXXView,这些系统组件都直接或间接继承自View,那么自定义View的方式自然也有区分,根据继承父类的不同,我们大致可以将自定义View分为三类:

  • 继承自View
  • 继承自ViewGroup
  • 继承自已有控件(ImageViewTextViewLinearLayout等诸如此类系统控件)

有同学们要问了,你前两节讲的是View,这里又提到了ViewGroup,是不是又要讲下ViewGroup的生命周期?当然不需要啦。ViewGroup作为View的子类,它的特点是什么呢?管理其内部的多个子View,其生命周期与View生命周期基本相同,同样要经过构造,绑定,布局,绘制的过程,只不过在布局过程中的测量部分,其需要驱动内部子View进行自身测量,在布局过程的layout部分,其需要驱动子View layout,在绘制过程中其既要完成自身绘制,又要驱动内部子View绘制。从这里可以看出View树的创建过程实际上是一个对布局的深度优先遍历过程,因为整个Activity布局的根布局肯定是ViewGroup的直接或间接子类。

那么自定义View究竟怎么做呢?那么多函数是否都需要重写?答案是不需要,通常情况下我们只需要重写构造,布局及绘制过程即可,一个基本的自定义View代码如下图所示(以继承自View为例):

public class MyCustomView extends View {
/****** 构造过程 ****/ public MyCustomView(Context context) {
super(context); } public MyCustomView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs); } public MyCustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); } public MyCustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); } /****** 布局过程中的测量部分 ****/ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); } /****** 布局过程中的布局部分 ****/ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom); } /****** 测量过程 ****/ @Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas); }}

完成了自定义View的声明,我们怎么使用它呢?有两种方式:

  • 直接使用new关键词调用构造函数创建,随后添加到View树中
  • 直接在xml文件中声明引用

使用new关键词创建并添加到View树的示例代码如下:

public class CustomViewActivity extends AppCompatActivity {
private MyCustomView mCustomView = null; @Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); mCustomView = new MyCustomView(this); setContentView(mCustomView); }}

使用xml直接声明引用的代码如下:

对应的java代码如下:

public class CustomViewActivity extends AppCompatActivity {
private MyCustomView mCustomView; @Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_view); mCustomView = findViewById(R.id.custom_view); }}

总体来说和系统控件的使用方式是一样的,需要注意的是在xml文件中引用时,一定要使用完整包路径并保证路径和实际一致,在代码重构中,移动了自定义View的包路径后,记得修改xml中引用的路径,否则会爆ClassNotFoundException,这是因为View树的创建过程中,是通过反射进行View对象初始化的。有些好奇的同学要问了,为啥系统组件不用写包路径,自己写的View就需要包路径,这不是赤果果的歧视吗?当然不是,其实对于系统组件而言,其在View树创建时系统默认添加了包路径,所以就不需要自己指定了哈。

转载地址:http://sqpei.baihongyu.com/

你可能感兴趣的文章
Typora Markdown 语法
查看>>
【IO】程序访问文件的几种方式
查看>>
Java NIO 系列教程
查看>>
fork() || fork()和fork() && fork()笔试题
查看>>
Qt:事件处理
查看>>
sublime Text3使用笔记
查看>>
使用webstom或者idea上传代码到github或coding
查看>>
YAML 语法
查看>>
AES加密
查看>>
使用Github进行合作开发
查看>>
Hadoop常用命令
查看>>
Impala入门笔记(转载)
查看>>
大数据分析:机器学习算法实现的演化
查看>>
自学大数据:用以生产环境的Hadoop版本比较
查看>>
Cloudera Manager和Managed Service的数据库
查看>>
cloudera Manager中监控数据的存储
查看>>
Kafka简要介绍
查看>>
Maven环境的搭建
查看>>
hbase 学习梳理
查看>>
浅谈医学大数据(中)
查看>>