Android 9.0 Adaptive Icon 圓形圖標剪切不全問題(上下左右部分被裁減)

 一、繼上一篇講過設置圓形圖標爲默認後,發現圓形圖標四周有被裁減的問題,如下圖:

二、開始懷疑是launcher3中的圖標設置大小出了問題,但是通過修改 launcher3中device_profiles.xml中的配置,如:

<profile
        launcher:name="Super Short Stubby"
        launcher:minWidthDps="255"
        launcher:minHeightDps="300"
        launcher:numRows="2"
        launcher:numColumns="3"
        launcher:numFolderRows="2"
        launcher:numFolderColumns="3"
        launcher:iconSize="48"
        launcher:iconTextSize="13.0"
        launcher:numHotseatIcons="3"
        launcher:defaultLayoutId="@xml/default_workspace_3x3"
        />

將iconSize改小,發現並不能解決問題,依然會有被剪切的情況。由此可以排除是Launcher3的問題了。

三、通過進一步跟中代碼發現AdaptiveIcon的生成機制,是通過AdaptiveDrawable來解析xml文件,所以把重點放在AdaptiveDrawable上,frameworks/base/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java,

通過分析代碼,發現裏面有個方法,updateMaskBoundsInternal ,大概意思就是更新掩碼區域,具體代碼如下:

 private void updateMaskBoundsInternal(Rect b) {
        mMaskMatrix.setScale(b.width() / MASK_SIZE, b.height() / MASK_SIZE);
        sMask.transform(mMaskMatrix, mMask);

        if (mMaskBitmap == null || mMaskBitmap.getWidth() != b.width() ||
            mMaskBitmap.getHeight() != b.height()) {
            mMaskBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ALPHA_8);
            mLayersBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ARGB_8888);
        }
        // mMaskBitmap bound [0, w] x [0, h]
        mCanvas.setBitmap(mMaskBitmap);
        mPaint.setShader(null);
        mCanvas.drawPath(mMask, mPaint);

        // mMask bound [left, top, right, bottom]
        mMaskMatrix.postTranslate(b.left, b.top);
        mMask.reset();
        sMask.transform(mMaskMatrix, mMask);
        // reset everything that depends on the view bounds
        mTransparentRegion.setEmpty();
        mLayersShader = null;
    }

可以發現,mMaskMatrix.setScale就是對掩碼進行了縮放處理,懷着試一試的心態,將其縮放比例改小,裁剪區域是減小了,但是得到的最終圖標並不是圓形,猜測是mMaskMatrix.setScale沒有設置中心點,於是mMaskMatrix.setScale加了一箇中心點,mMaskMatrix.setScale(b.width() / MASK_SIZE,getBounds().centerX(), getBounds().centerY()),但是得到的結果也不是圓形。通過簡單的修改scale發現並不能達到目的。

四、 只有從其它角度來分析了,首先,我們可以明確知道Adaptive icon的大小是用戶默認都配置好了的,不能隨意改變,但是裁減規則我們是可以改的,AdaptiveDrawable 中仔細分析,可以發現,adaptive icon 是由兩部分組成,前景層和背景層,他們都統一依賴於Rect來裁減,具體形狀是通過mask path來決定,比如說圓形,就是用的圓形mask來確定。其中Rect的大小又是根據原始drawable寬高決定的,回想之前出現的問題,感覺像是rect大了一點,drawable偏小導致四周出現了裁減不夠。

終上所述,問題基本原因已經分析清楚了,目的就是取藥修改rect的大小,通過分析代碼,其中有個一個方法onBoundsChange,意思就是有區域發生改變就會調用該方法,這裏應該就是最初調用到rect的地方,具體修改如下:

 @Override
    protected void onBoundsChange(Rect bounds) {
        if (bounds.isEmpty()) {
            return;
        }

        //hpe add start, adjust adaptive icon size
        Log.i("hpe-icon", " bounds, width= " + bounds.width() + ", height= " + bounds.height());
        if(bounds.width() > 50){// If the width is less than 50, don't handle it
            int scale = Math.round(bounds.width() * 0.1f / 2);
            bounds.left = bounds.left + scale;
            bounds.top = bounds.top + scale;
            bounds.right = bounds.right - scale;
            bounds.bottom = bounds.bottom -scale;
            setBounds(bounds);//to make it effective
            Log.i("hpe-icon", " bounds, width= " + bounds.width() + ", height= " + bounds.height());
        }
        //hpe add end

        updateLayerBounds(bounds);
    }

編譯驗證,ok。

該修改大致意思就是拿到了rect,稍微縮小rect的大小,如果圖標太小就不用了處理,然後重新設置一遍rect。這樣就整體修改了rect,達到了目的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章