自定義View與Activity的生命周期

背景

最近項(xiàng)目需求自定義了一個(gè)View,用來(lái)繪制簽名。
本來(lái)想著在用戶繪制之前,在View上設(shè)置一個(gè)自定義的文本,為了保證靈活性,要在Activity中調(diào)用自定義View的setHintText方法繪制文本。
而且,如果已經(jīng)簽過名的,要在Activity啟動(dòng)時(shí)調(diào)用drawImg回顯上次的簽名圖片。

問題:

當(dāng)在Activity的onCreate/onResume/onAttachedToWindow等方法調(diào)用上述2個(gè)方法,均不能正確繪制。
甚至在drawImg時(shí),會(huì)因?yàn)閣idth或height小于等于零而報(bào)錯(cuò)崩潰

    public void drawImg(Bitmap bitmap) {
        Matrix matrix = new Matrix();
        //bitmapWidth 與bitmapHeight 為自定義View 的寬高
        matrix.setScale((float) bitmapWidth / bitmap.getWidth(), (float) bitmapHeight / bitmap.getHeight());
        cachebBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
        cacheCanvas = new Canvas(cachebBitmap);
        postInvalidate();
    }

原因

我們來(lái)看看Activity的生命周期與View的繪制過程混合起來(lái)是怎樣的過程


自定義View與Activity生命周期.png
PS:
1.View 列里,綠色框中,因?yàn)槲磮?zhí)行onMeasure,所以View的準(zhǔn)確大小無(wú)法獲取,調(diào)用getMeasuredWidth/getMeasuredHeight,返回的結(jié)果是0;
2.View列里,橙色框?yàn)槟苷_獲取View的大小的方法
3.onWindowFocusChanged true/false 即是否hasFoucus
4.M1LD M2LD,即onMeasure 1次或2次,onLayout 一次,onDraw 一次。
5.onVisibilityChanged 4,為不可見INVISIBLE, 0為可見 VISIBLE
6.虛線框的,可能并不會(huì)被調(diào)用!

如上圖所示,在Activity的生命周期中,并沒有合適的時(shí)機(jī)能夠正確給自定義View設(shè)置要繪制的內(nèi)容。過早(onAttachedToWindow及之前)的設(shè)置,因?yàn)樽远xView的大小還未測(cè)量,不能繪制。又不能再onPause或者onStop中設(shè)置。
所以,我們考慮在Activity的onAttachedToWindow或之前的任意生命周期函數(shù)里將要繪制的內(nèi)容交給自定義View,如果還未測(cè)量大小就不立即繪制,讓自定義View 自己選擇合適的時(shí)機(jī)進(jìn)行繪制。
在自定義View的方法中,只有onSizeChanged里已經(jīng)完成View大小的測(cè)量且只調(diào)用了一次,所以我們?cè)谶@里進(jìn)行一點(diǎn)自己的設(shè)置。

    //判斷是否已經(jīng)執(zhí)行了onSizeChanged;
    private boolean sizeAlreadyChanged = false;
    private String mHint;
    public void setHintText(String hint) {
        mHint = hint;
        if (sizeAlreadyChanged) {
            drawText(hint);//繪制文本
        }
    }
    ...
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //已經(jīng)執(zhí)行了onSizeChanged 設(shè)置為true
        sizeAlreadyChanged=true;
        if (mHint != null)
            drawText(mHint);//繪制文本
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容