android draw ondraw(一)

261 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情

dispatchDraw

  1. 第一段
final int childrenCount = mChildrenCount;
final View[] children = mChildren;
int flags = mGroupFlags;

首先初始化一些局部变量

  • mChildrenCount表示子view个数
    
    那mChildrenCount在哪里赋值的呢。我们在ViewGroup里面搜索后发现是在addInArray执行了加1操作。addInArray的执行是由于addView的执行。 那谁调用了addView呢?只能用debug看一下

image.png

看了debug知道是由于inflate的执行调用的addView。而view也正是在inflate中创建的。(inflate会先创建根view,然后再创建子类view,这样一个layout就会inflate完毕)

  • mChildren数组也是在addview过程赋值的

    扩容规则:mChildren数组如果满了,就会在当前大小基础上再增加12个大小。

  • mGroupFlags

    viewGroup的内部标志值,viewgroup在创建时会有一些默认值

    initViewGroup会在构造函数里面调用。

private void initViewGroup() { 
    if (!isShowingLayoutBounds()) 
    { 
        setFlags(WILL_NOT_DRAW, DRAW_MASK); 
    } 
    mGroupFlags |= FLAG_CLIP_CHILDREN; 
    mGroupFlags |= FLAG_CLIP_TO_PADDING; 
    mGroupFlags |= FLAG_ANIMATION_DONE; 
    mGroupFlags |= FLAG_ANIMATION_CACHE; 
    mGroupFlags |= FLAG_ALWAYS_DRAWN_WITH_CACHE; 
    if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) 
    { 
        mGroupFlags |= FLAG_SPLIT_MOTION_EVENTS; 
    } 
    setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS); 
    mChildren = new View[ARRAY_INITIAL_CAPACITY]; //ARRAY_INITIAL_CAPACITY=12
    mChildrenCount = 0; 
    mPersistentDrawingCache = PERSISTENT_SCROLLING_CACHE; 
}
  1. 第二段
//运行布局动画
//FLAG_RUN_ANIMATION运行布局动画的flag
if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) {
    for (int i = 0; i < childrenCount; i++) {
        final View child = children[i];
        if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
            final LayoutParams params = child.getLayoutParams();
            attachLayoutAnimationParameters(child, params, i, childrenCount);
            bindLayoutAnimation(child);
        }
    }

    final LayoutAnimationController controller = mLayoutAnimationController;
    if (controller.willOverlap()) {
        mGroupFlags |= FLAG_OPTIMIZE_INVALIDATE;
    }

    controller.start();

    mGroupFlags &= ~FLAG_RUN_ANIMATION;
    mGroupFlags &= ~FLAG_ANIMATION_DONE;

    if (mAnimationListener != null) {
        mAnimationListener.onAnimationStart(controller.getAnimation());
    }
  • 在哪里设置的FLAG_RUN_ANIMATION?
startLayoutAnimation()//如果存在LayoutAnimationController则设置FLAG_RUN_ANIMATION,并执行requestLayout()重新布局
scheduleLayoutAnimation()//只是简单的将flags设置为FLAG_RUN_ANIMATION
setLayoutAnimation(LayoutAnimationController)//设置LayoutAnimationController,如果设置成功即不为null,则设置FLAG_RUN_ANIMATION
  • canAnimate()的作用是什么?
    //指示视图组是否能够在第一个布局后为其子项设置动画,也就是判断该动画能否启动
    protected boolean canAnimate() {
        return mLayoutAnimationController != null;
    }
  • 判断了半天,什么动画?

    就是viewGroup中子view出现的动画,可以为每一个view设置动画的延时事件。可重写 LayoutAnimationController中的getAnimationForView为不同view设置不同的动画效果,不重写的话就用统一的动画,只是动画的开始时间不同。

  • 最后一个是动画监听器

    可以通过这个函数设置setLayoutAnimationListener(Animation.AnimationListener animationListener)