美文网首页
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