从源码学习自定义View

从源码来理解自定义View

以下这些内容都是理解自定义View的基础知识点。

首先需要理解ViewGroup的概念,ViewGroup是一个特殊的View,它可以包含其它多个View,这些被包含的View也被称为childView(子View)。

一个ViewGroup可以包含多个子View,同时,这个子View也可以是ViewGroup。
例如,LinearLayout是一个ViewGroup,在里面添加一个Button,则这个Button是LinearLayout的子View。

那么,一个View是如何呈现在手机屏幕上的呢?


View的三大工作流程:

1.[测量流程] onMeasure(int widthMeasureSpec, int heightMeasureSpec)

  • 在谷歌给的源码中,它是这么解释的:Ask all children to measure themselves and compute the measurement of this layout based on the children. 意思是:要求所有的子View测量自己,然后通过这些测量值,计算这个承载所有子View的layout。

  • 这个方法的作用就是用于测量View的尺寸。

2.[布局流程] onLayout(boolean changed, int l, int t, int r, int b)

  • 在谷歌给的源码中,它是这么解释的:Position all children within this layout. 意思是:确定所有子View的位置。

  • 作用即是确定所有View的位置。

3.[绘制流程] onDraw(Canvas canvas)

  • 作用就是将View绘制到屏幕上

1. onMeasure() 需要明白的方法

  • ① public boolean shouldDelayChlidPressedState() {return false;}

    任何一个不需要使用滑动的布局都要使用它,不滚动的子类,一般应该重写此方法并返回false。

  • ② getChildCount()

    返回ViewGroup里所有子View的个数

  • ③ getChlidAt(int)

    返回一个在ViewGroup里指定位置的View

  • ④ getVisibility()

    返回视图的可见性状态,有:VISIBLE/INVISIBLE/GONE

  • ⑤ meassureChildWithMargins(View childView, int parentWidthMeasureSpec,int widthUsed, int parentHeighMeasureSpec, int heightUsed)

    要求子View测量好自己,要求考虑到父容器的宽高,及额外的空间

  • ⑥ LayoutParams

    布局参数类

  • ⑦ childView.getLayoutParams()

    获取子View的布局参数

  • ⑧ childView.getMeasuredWidth()

    以Raw的方式计算获取宽度(自行百度getX和getRawX的区别)

  • ⑨ childView.getMeasuredWidthAndState()

    跟上面一样,但不是以Raw方式

  • ⑩ getSuggestedMinimumHeight()

    返回这个View建议使用的最小高度

  • ⑩① resolveSizeAndState()

    用于创建最终的宽度或高度值,这个助手返回适当的视图所需的尺寸

  • ⑩② 这个方法本身:

    onMeasure(int widthMeasureSpec, int heightMeasureSpec)中的两个形参,即为ViewGroup最初的测量值。

  • ⑩③ setMeasuredDimension(int measuredWidth, int measuredHeight)

    注意:这个方法在最后一定要调用,否则会在测量期间引发一个异常。它用来存储最后测量得到的宽和高。


2. onLayout() 需要明白的方法

  • ① child.layout(left, top, right, bottom)

    摆放这个子View

  • ② 这个方法本身:

    onLayout(boolean changed, int l, int t, int r, int b) 当这个视图应该给每个子View分配一个大小和位置时调用。changed:当View发生改变时,changed=true


3. onDraw() 需要理解的知识点

  • 1.在onDraw方法前创建对象是一个非常重要的优化,View重新绘制的频率非常高,很多绘图的对象需要昂贵的初始化。Android官方建议的屏幕刷新率为60FPS,那么计算下来,每一次调用onDraw方法,可以执行的时间长度仅仅为16ms。在onDraw方法中创建图形对象显著降低性能,会让用户界面变得迟缓。
  • 2.为了正确地画出你自定义的视图,精确的测量很重要,不应该对屏幕上的视图大小做出假设,而是应该通过onMeasure()来进行测量。
  • 3.如果你认为不需要对其尺寸进行特殊控制,只需要重写一个方法: onsizeChanged()
  • 4.onDraw()常用到的方法:
    • 绘制文本:使用drawText(),调用setTypeface()指定字体,文本颜色调用setColor()
    • 绘制shape:使用drawRect()/drawOval()/drawArc(),指定它们为轮廓或者填充,调用setStyle()
    • 绘制更复杂的shape:使用Path类,通过Path对象添加线条或曲线路径,然后drawpath()绘制形状,形状可以为轮廓或充满,调用setStyle()
    • 渐变:定义渐变填充,使用LinearGradient对象,吊桶setShader()来使用这个渐变填充的shape
    • Bitmap:这个直接调用drawBitmap()

看完上述内容后,再来从代码案例中理解上述的知识点:

hongyang大神的博客,Android 手把手教您自定义ViewGroup(一)

一切清晰明了

你可能感兴趣的:(安卓,学习自定义View)