ViewGroup为什么不会调用onDraw

转载 2015年11月21日 13:48:58

正常情况下,我们重写LinearLayout的onDraw方法,它是不会被调用的,这篇文章就来分析一下原因和解决方法。 

一,现象

<com.test.demo.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/ll_absolute"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:background="#FF000000">

</com.test.demo.MyLinearLayout> 

大概的架构是,MyLinearLayout从LinearLayout派生出来,然后在程序中重载OnDraw(Canvas canvas)。但是,onDraw不会被调用。我们可能会遇到这个问题:如果不给LinearLayout设置一个背景,系统是不会调用onDraw时,也就是说,我们重写的onDraw是不会调用的。当设置一个背景后,onDraw就会被调用。 

二,原因 

造成这种现象的原因是继承自LinearLayout,而LinearLayout这是一个容器,ViewGroup嘛,它本身并没有任何可画的东西,它是一个透明的控件,因些并不会触发onDraw,但是你现在给LinearLayout设置一个背景色,其实这个背景色不管你设置成什么颜色,系统会认为,这个LinearLayout上面有东西可画了,因此会调用onDraw方法。 

我们可以仔细分析View的源码,它有一个方法View#draw(Canvas)方法,这里面有两个地方调用onDraw,它的条件都是:

if (!dirtyOpaque) onDraw(canvas); 

也就是说,如果dirtyOpaque是true的话,onDraw就不会调用,而dirtyOpaque的值的计算代码如下:

  1. final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&  
  2.                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);   
当View初始他时,它会调用一个私有方法:computeOpaqueFlags,这里面列出了不透明的三个条件:

        // Opaque if:

        //   - Has a background

        //   - Background is opaque

        //   - Doesn't have scrollbars or scrollbars are inside overlay

View还提供了一个重要的方法:setWillNotDraw,我们看一看它的实现: 

  1. /** 
  2.   * If this view doesn't do any drawing on its own, set this flag to 
  3.   * allow further optimizations. By default, this flag is not set on 
  4.   * View, but could be set on some View subclasses such as ViewGroup. 
  5.   * 
  6.   * Typically, if you override {@link #onDraw} you should clear this flag. 
  7.   * 
  8.   * @param willNotDraw whether or not this View draw on its own 
  9.   */  
  10.  public void setWillNotDraw(boolean willNotDraw) {  
  11.      setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);  
  12.   
  13.  }  

从这个方法的注释,我们可以看出,如果你想重写onDraw的话,你应该调用这个方法来清除flag,所以如果我们想要重写LinearLayout的onDraw的话,我们也可以在其构造方法中调用setWillNotDraw方法。 在ViewGroup初始他时,它调用了一个私有方法:initViewGroup,它里面会有一句setFlags(WILL_NOT_DRAW, DRAW_MASK); 相当于调用了setWillNotDraw(true),所以说,对于ViewGroup,它就认为是透明的了。如果我们想要重写onDraw,就需要调用setWillNotDraw(false)

三,总结一下:

1)ViewGroup默认情况下,会被设置成WILL_NOT_DRAW,这是从性能考虑,这样一来,onDraw就不会被调用了。

2)如果我们要重要一个ViweGroup的onDraw方法,有两种方法:

        1,在构造函数里面,给其设置一个颜色,如#00000000。

        2,在构造函数里面,调用setWillNotDraw(false),去掉其WILL_NOT_DRAW flag。


from:http://blog.csdn.net/leehong2005/article/details/7299471#0-tsina-1-40696-397232819ff9a47a7b7e80a40613cfe1

ViewGroup为什么不会调用onDraw

正常情况下,我们重写LinearLayout的onDraw方法,它是不会被调用的,这篇文章就来分析一下原因和解决方法。 一,现象     android:id="@+id/ll_abso...

ViewGroup为什么不会调用onDraw

转自 http://blog.csdn.net/leehong2005/article/details/7299471   正常情况下,我们重写LinearLayout的onDraw方法,它是不会...

ViewGroup为什么不会调用onDraw

目录(?)[+] 正常情况下,我们重写LinearLayout的onDraw方法,它是不会被调用的,这篇文章就来分析一下原因和解决方法。 一,现象     android:id="...

ViewGroup中含有子View的时候,子View会执行OnDraw()方法一次或两次。

前言:今天,在写自定义View的时候让我发现了这样一个秘密。当ViewGroup中含有子View的时候,子View会执行OnDraw()方法一次或者两次。怎么那么不确切呢?没有那么多为什么,现象就是如...

自定义ViewGroup ondraw方法不被调用解决办法

在我们自定义一个View, 继承自ViewGrop, 或其他某些ViewGroup的子类时, 若我们要在ViewGroup中进行一些绘制,我们会想到重写父类的ondraw, 但我们发现此时ondraw...

为什么自定义ViewGroup ondraw方法不会被调用

前言: 最近在自定义ViewGroup类型的控件时,通过复写View的OnDraw()方法来修改控件的背景,发现不论在onDraw()方法中怎么修改背景,都是不能成功,除非指定android...

为什么自定义ViewGroup ondraw方法不会被调用

转载地址:点击打开链接 viewgroup的绘制严格来说是在dispatchDraw中完成,作为一个容器,绘制自己的孩子该通过dispatchDraw(canvas)实现。但是你非要在ondra...

chromium:LoadUrl之后会发生那些事情之OnDraw

一 综述 自从Android系统WebView内核使用chromium以来,其渲染机制一直在持续不断演进,本文将以M42内核分析WebView的渲染架构以及相关代码分析。 先从代码流程进行分析,当...

View的onDraw函数不被调用 .

参考: http://blog.sina.com.cn/s/blog_4b50130d0100u0uk.html http://blog.csdn.net/hearrt/article/detai...
  • neiloid
  • neiloid
  • 2012年10月04日 12:29
  • 8691

requestLayout调用onDraw之谜

在上篇文章曾经说过,requestLayout如果没有改变l,t,r,b,那就不会触发onDraw,但是我今天写了个demo,发现居然触发了onDraw,这是怎么回事? 代码很简单,工程为Reque...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ViewGroup为什么不会调用onDraw
举报原因:
原因补充:

(最多只允许输入30个字)