国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android ViewGroup onDraw為什么沒調(diào)用

這篇具有很好參考價(jià)值的文章主要介紹了Android ViewGroup onDraw為什么沒調(diào)用。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

ViewGroup,它本身并沒有任何可畫的東西,它是一個(gè)透明的控件,因些并不會觸發(fā)onDraw,但是你現(xiàn)在給LinearLayout設(shè)置一個(gè)背景色,其實(shí)這個(gè)背景色不管你設(shè)置成什么顏色,系統(tǒng)會認(rèn)為,這個(gè)LinearLayout上面有東西可畫了,因此會調(diào)用onDraw方法。
android代碼一直在優(yōu)化,我看了幾個(gè)版本的源碼,目前,我用的是API30的源碼,再去看ViewGroup為什么不走onDraw()的時(shí)候,已經(jīng)不是一句 if (!dirtyOpaque) 就能決定是否執(zhí)行onDraw()的事了。
原因詳解
在API27中,還是我們熟悉的那個(gè) if 判斷決定 onDraw()的執(zhí)行
Android ViewGroup onDraw為什么沒調(diào)用,android

在API27以后,你會發(fā)現(xiàn)在draw()方法里找不到 上面這個(gè) if 語句,那么問題來了:他是如何控制 ViewGroup 不執(zhí)行 onDraw() 的呢?

這個(gè)時(shí)候,我們的目光該放在這兩個(gè)片段上了,還是在 View 這個(gè)類里面
片段一:

view.java 
/**
     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
     *
     * This is where the View specializes rendering behavior based on layer type,
     * and hardware acceleration.
     */
      boolean draw(Canvas canvas, ViewGroup parent, long drawingTime)方法
                ...
                // Fast path for layouts with no backgrounds
                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                    dispatchDraw(canvas);
                } else {
                    draw(canvas);
                }
                ...

從這一段我們能獲取兩個(gè)信息:
注釋:

  • ViewGroup.drawChild()調(diào)用此方法,使每個(gè)子視圖都繪制自己。這是視圖根據(jù)圖層類型專門處理渲染行為的地方,硬件加速。
  • 是否走draw()方法由兩個(gè)標(biāo)志決定 mPrivateFlags & PFLAG_SKIP_DRAW

片段二 :

public RenderNode updateDisplayListIfDirty() {
       // Fast path for layouts with no backgrounds
                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                        dispatchDraw(canvas);
                        drawAutofilledHighlight(canvas);
                        if (mOverlay != null && !mOverlay.isEmpty()) {
                            mOverlay.getOverlayView().draw(canvas);
                        }
                        if (isShowingLayoutBounds()) {
                            debugDrawFocus(canvas);
                        }
                    } else {
                        draw(canvas);
                    }
}

從這一段我們能獲取這么個(gè)信息:是否走draw()方法由兩個(gè)標(biāo)志決定 mPrivateFlags & PFLAG_SKIP_DRAW

硬件加速

現(xiàn)在Android默認(rèn)開啟硬件加速,什么是硬件加速呢?為了加快Android繪制速度,適當(dāng)解放cpu資源,Android將一部分繪制放到gpu執(zhí)行。而對應(yīng)的Android里面的canvas,也分為是否支持硬件加速,因此繪制流程也有所差異,流程圖簡示如下:
Android ViewGroup onDraw為什么沒調(diào)用,android

[]表示該調(diào)用該類里的對應(yīng)方法。
()表示方法里的參數(shù)
從上圖可以看出,不管是否開啟硬件加速,都會經(jīng)歷“跳過繪制”的邏輯判斷,而該判斷的分支就決定了viewGroup的ondraw()方法是否執(zhí)行。如果“跳過繪制”成立,那么調(diào)用dispatchDraw()方法,繼而調(diào)用子view進(jìn)行繪制(如果有子view)。如果“跳過繪制”不成立,那么調(diào)用draw(x1),該方法上面分析過了:會調(diào)用dispatchDraw()和ondraw()方法。

draw(x1)的方法如下:

    public void draw(Canvas canvas) {

        //省略
        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
        if (!verticalEdges && !horizontalEdges) {
            // 繪制自身內(nèi)容
            onDraw(canvas);

            // 繪制子view
            dispatchDraw(canvas);

            //省略

            // we're done...
            return;
        }
        //省略
    }

viewGroup和View初始化時(shí)對于PFLAG_SKIP_DRAW標(biāo)記做了不同的處理。
Android ViewGroup onDraw為什么沒調(diào)用,android
viewGroup初始化的時(shí)候,默認(rèn)設(shè)置了WILL_NOT_DRAW,從字面意思來看是“不會繪制”標(biāo)記,這個(gè)標(biāo)記是否和PFLAG_SKIP_DRAW有聯(lián)系呢?繼續(xù)查看setFlags方法:

vew.java setFlags方法
        //省略
        if ((changed & DRAW_MASK) != 0) {
            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
                if (mBackground != null
                        || mDefaultFocusHighlight != null
                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
                } else {
                    mPrivateFlags |= PFLAG_SKIP_DRAW;
                }
            } else {
                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
            }
            requestLayout();
            invalidate(true);
        }
        //省略

到此處就比較明朗,將兩個(gè)標(biāo)記值聯(lián)系起來了:

1、如果設(shè)置了WILL_NOT_DRAW標(biāo)記,那么繼續(xù)檢查background、foreground(mDrawable字段)、focusHighLight是否有值,如果三者任意一個(gè)設(shè)置了,那么將PFLAG_SKIP_DRAW標(biāo)記清除,否則將該標(biāo)記加上。
2、如果沒有設(shè)置WILL_NOT_DRAW標(biāo)記,那么將PFLAG_SKIP_DRAW標(biāo)記清除。

如何讓viewGroup onDraw()執(zhí)行

既然知道了MyFrameLayout沒有繪制的原因,那么就有方法讓它執(zhí)行繪制流程。
先來看看WILL_NOT_DRAW

view.java
    /**
     * If this view doesn't do any drawing on its own, set this flag to
     * allow further optimizations. By default, this flag is not set on
     * View, but could be set on some View subclasses such as ViewGroup.
     *
     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
     * you should clear this flag.
     *
     * @param willNotDraw whether or not this View draw on its own
     */
    public void setWillNotDraw(boolean willNotDraw) {
        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
    }

    /**
     * Returns whether or not this View draws on its own.
     *
     * @return true if this view has nothing to draw, false otherwise
     */
    @ViewDebug.ExportedProperty(category = "drawing")
    public boolean willNotDraw() {
        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
    }

View類里暴露了設(shè)置WILL_NOT_DRAW標(biāo)記的接口:
setWillNotDraw(boolean willNotDraw),可以在viewgroups里使用setWillNotDraw(false)。
不想設(shè)置該標(biāo)記也是可行的,前面說過即使設(shè)置了WILL_NOT_DRAW,后面還是有判斷background、foreground、focusHighLight是否有值。
background:view背景
foreground(mDrawable字段):view前景
focusHighLight:view獲得焦點(diǎn)時(shí)高亮
我們只要設(shè)置了其中一個(gè)值,PFLAG_SKIP_DRAW標(biāo)記將會被清空。
來看看這三個(gè)值如何影響PFLAG_SKIP_DRAW標(biāo)記

view.java
public void setBackgroundDrawable(Drawable background) {
if (background != null) {
   if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
                requestLayout = true;
            }
     }
}

public void setForeground(Drawable foreground) {
        if (foreground != null) {
            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
            }
    }
}

private void setDefaultFocusHighlight(Drawable highlight) {
        mDefaultFocusHighlight = highlight;
        mDefaultFocusHighlightSizeChanged = true;
        if (highlight != null) {
            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
            }
      }
    }

總結(jié)

若要ViewGroup onDraw()執(zhí)行,只需要setWillNotDraw(false)、設(shè)置背景、設(shè)置前景、設(shè)置焦點(diǎn)高亮,4個(gè)選項(xiàng)其中一項(xiàng)滿足即可。

當(dāng)然也可以重寫dispatchDraw()方法,在該方法里繪制自定義view的內(nèi)容。文章來源地址http://www.zghlxwxcb.cn/news/detail-588186.html

到了這里,關(guān)于Android ViewGroup onDraw為什么沒調(diào)用的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Android組件化架構(gòu)開發(fā)--為什么要使用組件化?組件分層?組件路由的簡單實(shí)現(xiàn)。

    Android組件化架構(gòu)開發(fā)--為什么要使用組件化?組件分層?組件路由的簡單實(shí)現(xiàn)。

    1.1 單工程項(xiàng)目結(jié)構(gòu) 一般我們都是一個(gè)業(yè)務(wù)建一個(gè)包 缺點(diǎn): 各種業(yè)務(wù)代碼混雜在同一個(gè)模塊里,開發(fā)人員在開發(fā)、調(diào)測過程的效率越來越低,定位某個(gè)業(yè)務(wù)問題,需要在多個(gè)業(yè)務(wù)代碼混合的模塊中尋找和跳轉(zhuǎn)。 需要了解各個(gè)業(yè)務(wù)的功能,避免代碼的改動(dòng)影響其它業(yè)務(wù)的功能

    2024年02月10日
    瀏覽(26)
  • android studio創(chuàng)建一個(gè)新的項(xiàng)目為什么默認(rèn)是kotlin語言而選擇不了java語言

    android studio創(chuàng)建一個(gè)新的項(xiàng)目為什么默認(rèn)是kotlin語言而選擇不了java語言

    關(guān)于android studio語言選擇的問題。 我在進(jìn)入android studio為什么創(chuàng)建一個(gè)新項(xiàng)目之后選擇不了java語言有什么辦法可以解決。 解決辦法:這個(gè)模式下選著一個(gè)Empty Activity模塊就可以使用java語言。 這對于剛剛接觸anaroid studio新手比較管用。 ?

    2024年02月11日
    瀏覽(24)
  • JavaScript——為什么靜態(tài)方法不能調(diào)用非靜態(tài)方法

    JavaScript——為什么靜態(tài)方法不能調(diào)用非靜態(tài)方法

    個(gè)人簡介 ?? 個(gè)人主頁: 前端雜貨鋪 ???♂? 學(xué)習(xí)方向: 主攻前端方向,正逐漸往全干發(fā)展 ?? 個(gè)人狀態(tài): 研發(fā)工程師,現(xiàn)效力于中國工業(yè)軟件事業(yè) ?? 人生格言: 積跬步至千里,積小流成江海 ?? 推薦學(xué)習(xí):??前端面試寶典 ??Vue2 ??Vue3 ??Vue2/3項(xiàng)目實(shí)戰(zhàn) ??Node.js??

    2024年02月11日
    瀏覽(26)
  • flask啟動(dòng)為什么會調(diào)用__call__

    先來看看__call__什么時(shí)候時(shí)候可以調(diào)用 不返回任何結(jié)果 有結(jié)果返回 注意這個(gè)__call__必須要實(shí)例化之后才可以調(diào)用不然不會調(diào)用 無任何結(jié)果返回 內(nèi)置函數(shù)同樣可以用__call__()方法來調(diào)用 自定義函數(shù)也也可以通過__call__()方法來調(diào)用 接下來理解為什么 這個(gè)最后會調(diào)取Flask的__cal

    2024年02月16日
    瀏覽(20)
  • 為什么hooks不能在循環(huán)、條件或嵌套函數(shù)中調(diào)用

    為什么hooks不能在循環(huán)、條件或嵌套函數(shù)中調(diào)用

    hooks不能在循環(huán)、條件或嵌套函數(shù)中調(diào)用 為什么? // 20231120更新 我覺得還是先把答案說出來,再去看為什么比較合適。 其實(shí)就是一句話,因?yàn)楹瘮?shù)組件渲染分兩種場景 一、首次渲染 二、更新組件 原因就是,函數(shù)組件在首次渲染的時(shí)候,碰到hook語句時(shí),是去創(chuàng)建一個(gè)空的

    2024年02月04日
    瀏覽(24)
  • 0062__對象指針為NULL,為什么還是可以調(diào)用成員函數(shù)

    對象指針為NULL,為什么還是可以調(diào)用成員函數(shù)_空對象指針為什么能調(diào)用函數(shù)_一顆石頭崽兒的博客-CSDN博客

    2024年02月10日
    瀏覽(16)
  • 【C++】 為什么多繼承子類重寫的父類的虛函數(shù)地址不同?『 多態(tài)調(diào)用匯編剖析』

    【C++】 為什么多繼承子類重寫的父類的虛函數(shù)地址不同?『 多態(tài)調(diào)用匯編剖析』

    ?? 樊梓慕: 個(gè)人主頁 ??? 個(gè)人專欄: 《C語言》 《數(shù)據(jù)結(jié)構(gòu)》 《藍(lán)橋杯試題》 《LeetCode刷題筆記》 《實(shí)訓(xùn)項(xiàng)目》 《C++》 《Linux》《算法》 ?? 每一個(gè)不曾起舞的日子,都是對生命的辜負(fù) 本篇文章主要是為了解答有關(guān)多態(tài)的那篇文章那塊的一個(gè)奇怪現(xiàn)象,大家還記得這張

    2024年02月19日
    瀏覽(26)
  • 面試官:Feign 第一次調(diào)用為什么會很慢?大部分人都答不上來!

    面試官:Feign 第一次調(diào)用為什么會很慢?大部分人都答不上來!

    作者:Lxlxxx 鏈接:https://juejin.cn/post/7249624466150408250 首先要了解Feign是如何進(jìn)行遠(yuǎn)程調(diào)用的,這里面包括,注冊中心、負(fù)載均衡、FeignClient之間的關(guān)系,微服務(wù)通過不論是eureka、nacos也好注冊到服務(wù)端,F(xiàn)eign是靠Ribbon做負(fù)載的,而Ribbon需要拿到注冊中心的服務(wù)列表,將服務(wù)進(jìn)行負(fù)

    2024年02月12日
    瀏覽(17)
  • 已經(jīng)安裝了 python 庫,但是為什么調(diào)用不了;ModuleNotFoundError: No module named ‘xxx庫名‘

    已經(jīng)安裝了 python 庫,但是為什么調(diào)用不了;ModuleNotFoundError: No module named ‘xxx庫名‘

    ModuleNotFoundError: No module named ‘a(chǎn)utox’ 但是通過 pip list 查看是可以發(fā)現(xiàn)這個(gè)庫的?。。。?最近在嘗試一些 自動(dòng)機(jī)器學(xué)習(xí)方面的內(nèi)容Auto ML,于是就裝了一下 autox 這個(gè)庫。將 github 上的倉庫克隆下來之后,進(jìn)入該倉庫的主文件目錄,使用 下面的指令進(jìn)行安裝。 通過 pip list 查看

    2024年02月12日
    瀏覽(20)
  • Android基礎(chǔ)到進(jìn)階UI祖父級 ViewGroup介紹+實(shí)用

    Android基礎(chǔ)到進(jìn)階UI祖父級 ViewGroup介紹+實(shí)用

    int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); int modeWidth = MeasureSpec.getMode(widthMeasureSpec); int modeHeight = MeasureSpec.getMode(heightMeasureSpec); // 如果是warp_content情況下,記錄寬和高 int width = 0; int height = 0; //記錄每一行的寬度,width不斷取最大寬度 int lineWidth = 0; //每一行的高度,累加至h

    2024年04月16日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包