Android背景圖填充不變形


  android設置背景圖片默認會被拉伸至填滿視圖大小,試過使用.9圖,但在線性布局不生效,最后找到一種解決方式,將圖片縮放以保證在一個方向充滿,另一方向使用空白像素填充,注意*圖片拉伸方向邊界一定要為透明或背景色。

  首先使用BitmapFactory.decodeResource生成背景圖Drawable(沒如果不是資源文件使用其他對應方法),設定BitmapFactory.Options在生成圖片的同時完成圖片的縮放。Options中默認只能通過inSampleSize設定縮小的倍速(2的整數倍),顯然無法滿足需求,在inScaled屬性的注釋上可以看到:

  當此標識位設定為true時,如果inDensity和inTargetDensity屬性值均不為0,bitmap將在加載時進行縮放,適配inTargetDensity大小,而不是在每次繪制時進行縮放。若使用BitmapRegionDecoder則會忽略這個標記,不會基於密度縮放(雖然支持通過inSampleSize設置縮小)。當此標識默認為true,如果需要,應該關閉。點9圖將忽略此標示,總是進行縮放。如果inPremultiply設置為false,且圖像有alpha值,則將此標識設置為true可能導致錯誤的顏色。

  因為通過一下兩步完成縮放計算:

  ①:設置Options中inDensity為系統densityDpi(context.getgetResources().getDisplayMetrics().densityDpi);

  ②:根據縮放計算Options中inTargetDensity的值(目標視圖寬度 /圖片寬度) * inDensity值)

  此時通過public static BitmapdecodeResource(Resources res, int id, Options opts)方法完成背景圖片的創建,下一步,設置背景圖填充模式--->Shader.TileMode。

  Shader.TileMode枚舉類一共分為3種:

  1、CLAMP (0),使用圖片邊界像素填充視圖空白部分,默認為右邊界和下邊界;

   2、REPEAT (1),重復圖片填充空白;

  3、MIRROR (2),使用圖片鏡像填充空白;

  根據前面確定的解決方案,調用BitmapDrawable的public void setTileModeXY(Shader.TileMode xmode, Shader.TileMode ymode)方法,設置拉伸模式均為 Shader.TileMode.CLAMP。

  完整實現代碼如下:

public static void setClampBgDrawable(final View targetView, int resId, Resources res, boolean clampX) {
    setClampBgDrawable(targetView, resId, res, clampX, true);
}
private static void setClampBgDrawable(final View targetView, final int resId, final Resources res,
                                       final boolean clampX, boolean tryOnPreDraw) {
    int targetWidth = 0;
    if (targetView instanceof RecyclerView) {
        RecyclerView.LayoutManager manager = ((RecyclerView) targetView).getLayoutManager();
        if (manager != null) {
            targetWidth = manager.getWidth();
        }
    } else {
        targetWidth = targetView.getWidth();
    }
    if (targetWidth > 0) {
        //測量圖片實際大小
        BitmapFactory.Options measureOpts = new BitmapFactory.Options();
        measureOpts.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, measureOpts);
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inDensity = res.getDisplayMetrics().densityDpi;
        opts.inTargetDensity = targetWidth * opts.inDensity / measureOpts.outWidth;
        Bitmap bitmap = BitmapFactory.decodeResource(res, resId, opts);
        //不能使用過時的構造方法,否則可能會不生效
        BitmapDrawable bgDrawable = new BitmapDrawable(res, bitmap);
        //設置填充模式,由於X軸充滿視圖,所以TileMode可以為null
        if (clampX) {
            bgDrawable.setTileModeXY(Shader.TileMode.CLAMP, null);
        } else {
            bgDrawable.setTileModeXY(null, Shader.TileMode.CLAMP);
        }
        bgDrawable.setDither(true);
        targetView.setBackground(bgDrawable);
    } else if (tryOnPreDraw) {
        targetView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                targetView.getViewTreeObserver().removeOnPreDrawListener(this);
                setClampBgDrawable(targetView, resId, res, clampX, false);
                return false;
            }
        });
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM