第一章:Android自定义View概述

各位同学,欢迎来到《Android自定义View与Kotlin绘图从入门到精通》的第一课。

说实话,我刚开始学Android的时候,最怕的就是自定义View。总觉得那是大神才碰的东西。后来做项目做多了才发现——自定义View没那么玄乎,它其实就是你给Android系统画图、写交互的一套工具

今天咱们先聊聊最基础的问题:什么是自定义View?为什么需要它?它有哪些分类?

1.1 什么是自定义View

先问个问题:你平时用的Button、TextView、ImageView,它们是什么?

它们都是View。Android系统帮我们写好了这些控件的绘制逻辑和交互逻辑。但有时候,系统提供的控件不够用——比如你想画一个圆形进度条、一个带波浪效果的图表、一个可以拖拽排序的卡片……这时候,你就得自己动手写一个View。

自定义View,说白了就是继承View或其子类,重写它的绘制、测量、触摸等方法,实现你想要的效果。

我个人的理解是:系统给你搭好了画架和画布,你只需要拿起画笔,画出你想要的东西。

核心要点:自定义View = 继承View + 重写关键方法 + 实现自定义逻辑

1.2 为什么需要自定义View

你可能会想:系统控件那么多,还不够用吗?

嗯,说实话,大部分场景确实够用。但遇到下面这些情况,你就不得不自己动手了:

  • 系统控件无法满足UI设计稿——设计师给你一个带渐变、圆角、阴影的复杂按钮,系统Button搞不定
  • 需要高性能绘制——比如实时刷新的图表、动画,用布局嵌套会卡成PPT
  • 需要特殊交互——比如拖拽排序、手势缩放、多点触控
  • 复用性高——一个自定义View封装好,整个项目到处用,省时省力

我记得有一次做电商项目,产品经理要求首页的秒杀倒计时做成圆形进度条,中间显示剩余时间。用系统控件?根本不可能。最后我写了一个自定义View,半小时搞定,还顺便封装成了通用组件,后来好几个页面都用了。

我的建议:不要为了炫技而自定义View。能用系统控件解决的,就用系统控件。只有系统控件确实搞不定时,才考虑自定义。

1.3 自定义View的分类

自定义View按实现方式,我一般分成三类。你想想看,其实就这三种路子:

分类 实现方式 适用场景 难度
组合控件 将多个系统控件组合成一个新的View 比如自定义标题栏、搜索框、带图标的按钮
继承系统控件 继承Button、TextView等,扩展功能 比如带倒计时的Button、可滚动的TextView ⭐⭐
完全自定义 继承View,重写onDraw、onMeasure等 比如图表、进度条、游戏画面 ⭐⭐⭐

组合控件是最简单的。说白了就是把几个系统控件拼在一起,写成一个类。比如你经常看到的带图标的输入框,就是EditText和ImageView的组合。

继承系统控件稍微进阶一点。比如你想让Button支持倒计时,直接继承Button,加个计时器逻辑就行。我刚开始做自定义View时,就是从这条路入门的。

完全自定义是最难的,也是咱们这门课的重点。你需要自己控制绘制、测量、布局、触摸事件。但别怕,后面我会一步步带你走通。

1.4 实现方式概览

不管哪种分类,自定义View的核心步骤其实就这几步:

  1. 创建类——继承View或其子类
  2. 重写构造方法——至少重写一个带Context和AttributeSet的构造
  3. 重写onMeasure——告诉系统这个View要占多大地方
  4. 重写onDraw——在这里画你想要的内容
  5. 处理触摸事件——如果需要交互,重写onTouchEvent

给你看个最简单的例子——一个画红色圆圈的View:

class CircleView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private val paint = Paint().apply {
        color = Color.RED
        style = Paint.Style.FILL
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        // 在View中心画一个半径为100px的红色圆
        val cx = width / 2f
        val cy = height / 2f
        canvas.drawCircle(cx, cy, 100f, paint)
    }
}

这段代码很简单,但包含了自定义View的核心骨架。你把它放到布局里,就能看到一个红色圆圈。

注意:onDraw方法会被频繁调用(比如界面刷新、动画),所以里面不要创建对象,不要做耗时操作。Paint、Path这些对象,最好在构造方法里初始化好。

我曾经犯过一个错误——在onDraw里new了一个Paint对象,结果界面稍微有点动画,内存就蹭蹭往上涨。后来用Profiler一查,发现onDraw每秒调了60次,每次都在创建对象……嗯,从那以后我再也不敢在onDraw里new东西了。

1.5 本章小结

今天咱们聊了自定义View的基本概念:

  • 什么是自定义View——继承View,重写方法,实现自定义效果
  • 为什么需要它——系统控件不够用、需要高性能、特殊交互、复用
  • 三种分类——组合控件、继承系统控件、完全自定义
  • 核心步骤——创建类、重写构造、onMeasure、onDraw、触摸事件

下一章,咱们会深入Kotlin的绘图基础——Canvas和Paint。你会真正拿起画笔,画出第一个属于自己的图形。

准备好了吗?咱们下章见。