美文网首页
Android背景图填充不变形

Android背景图填充不变形

作者: 周_0717 | 来源:发表于2020-02-20 10:05 被阅读0次

  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;
            }
        });
    }
}

相关文章

网友评论

      本文标题:Android背景图填充不变形

      本文链接:https://www.haomeiwen.com/subject/bsbtqhtx.html