Reputation: 5167
It is said that onDraw() will be called when invalidate() is called. However, when I look at the android source code. I didn't find where the onDraw() gets called in invalidate(). So I am still confused about how the onDraw() method is called for a view. Who can help me figuring this out?
Upvotes: 2
Views: 7375
Reputation: 5167
I have to call setWillNotDraw(false). It is set to true by default for all subclasses of ViewGroup.
Upvotes: 1
Reputation: 133560
Drawing
Drawing is handled by walking the tree and rendering each view that intersects the invalid region. Because the tree is traversed in-order, this means that parents will draw before (i.e., behind) their children, with siblings drawn in the order they appear in the tree. If you set a background drawable for a View, then the View will draw it for you before calling back to its onDraw() method.
Note that the framework will not draw views that are not in the invalid region.
To force a view to draw, call invalidate()
.
Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, call postInvalidate().
10340 public void invalidate() {
10341 invalidate(true);
10342 }
Source
This is where the invalidate() work actually happens. A full invalidate() causes the drawing cache to be invalidated, but this function can be called with invalidateCache set to false to skip that invalidation step for cases that do not need it (for example, a component that remains at the same dimensions with the same content).
Parameters:
invalidateCache Whether the drawing cache for this view should be invalidated as well. This is usually true for a full invalidate, but may be set to false if the View's contents or dimensions have not changed.
10354
10355 void invalidate(boolean invalidateCache) {
10356 if (skipInvalidate()) {
10357 return;
10358 }
10359 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10360 (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
10361 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
10362 mLastIsOpaque = isOpaque();
10363 mPrivateFlags &= ~PFLAG_DRAWN;
10364 mPrivateFlags |= PFLAG_DIRTY;
10365 if (invalidateCache) {
10366 mPrivateFlags |= PFLAG_INVALIDATED;
10367 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10368 }
10369 final AttachInfo ai = mAttachInfo;
10370 final ViewParent p = mParent;
10371 //noinspection PointlessBooleanExpression,ConstantConditions
10372 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10373 if (p != null && ai != null && ai.mHardwareAccelerated) {
10374 // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10375 // with a null dirty rect, which tells the ViewAncestor to redraw everything
10376 p.invalidateChild(this, null);
10377 return;
10378 }
10379 }
10380
10381 if (p != null && ai != null) {
10382 final Rect r = ai.mTmpInvalRect;
10383 r.set(0, 0, mRight - mLeft, mBottom - mTop);
10384 // Don't call invalidate -- we don't want to internally scroll
10385 // our own bounds
10386 p.invalidateChild(this, r);
10387 }
10388 }
10389 }
Upvotes: 8
Reputation: 3309
According to View | Android Developers:
Drawing is handled by walking the tree and rendering each view that intersects the invalid region. Because the tree is traversed in-order, this means that parents will draw before (i.e., behind) their children, with siblings drawn in the order they appear in the tree. If you set a background drawable for a View, then the View will draw it for you before calling back to its onDraw() method.
Note that the framework will not draw views that are not in the invalid region.
To force a view to draw, call invalidate().
Which mean when the UI thread gets to it (the invalid region) it will call onDraw() for that region.
Upvotes: 0
Reputation: 1346
Take a look at this post. This explains you exactly when onDraw() will be called.
Upvotes: 0
Reputation: 36035
Invalidate
won't call onDraw()
directly. It schedules a draw pass to the system which says that the Views need to draw at some point in the future which is usually almost immediately. If the UI thread is blocked, it can take some time though.
Upvotes: 8
Reputation: 25143
A View's onDraw() is called when:
Upvotes: -1