透明模糊的视图,它的下方模糊布局 [英] Transparent blurry view which blurs layout underneath

查看:156
本文介绍了透明模糊的视图,它的下方模糊布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我已经透明化了的LinearLayout,现在我正在寻找一种方式来给它一个模糊的效果,所以什么是有史以来在它之下变得模糊。就像Windows 7的Aero的外观(见截图)。

I've got a Linearlayout which I've made transparent, and now I'm looking for a way to give it a Blur effect, so what's ever underneath it gets blurry. Just like the Windows 7 Aero look (see screenshot).

我知道你可以做到这样的模糊效果:

I know you can do a blur effect like this:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

不过,这仅适用于喜欢模糊的背景会出现一个对话框时。

But this only applies to like blurring the background when a dialog appears.

我一直在谷歌上搜索了将近一个小时,我无法找到任何东西。有没有人对如何做到这一点有什么建议?

I've been googling for almost an hour, and I can't find anything. Does anyone have any suggestions on how to do this?

感谢

推荐答案

这是在我的脑海里有一段时间,我只是实现了它的感谢你的问题。

This was on my mind for some time, and I just implemented it thanks to your question.

要能够做到这一点,我们需要绘制的布局是我们模糊的布局成位图的下方。不是通过使用一个模糊算法,我们需要模糊的位图,最后得出模糊的位图作为我们的虚化布局的背景。

To be able to do this, we need to draw the layout that is beneath our blur layout into a bitmap. Than by using a blurring algorithm, we need to blur that bitmap and finally draw blurred bitmap as our blur layout's background.

幸运的是,Android已经缓存绘图机制,第一部分是容易的。我们可以简单地启用缓存布局绘制的下方我们并使用 getDrawingCache()从中获取位图。

Luckily android has cached drawing mechanism, so first part is easy. We can simply enable cached drawing for our beneath layout and use getDrawingCache() to acquire the bitmap from it.

现在,我们需要一个快速的模糊算法。我用这个<一href="http://stackoverflow.com/a/10028267/3133545">http://stackoverflow.com/a/10028267/3133545

Now we need a fast blurring algorithm. I used this http://stackoverflow.com/a/10028267/3133545

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;

import java.lang.ref.WeakReference;
import java.util.InputMismatchException;

/**
 * A drawable that draws the target view as blurred using fast blur
 * <p/>
 * <p/>
 * TODO:we might use setBounds() to draw only part a of the target view
 * <p/>
 * Created by 10uR on 24.5.2014.
 */
public class BlurDrawable extends Drawable {

    private WeakReference<View> targetRef;
    private Bitmap blurred;
    private Paint paint;
    private int radius;


    public BlurDrawable(View target) {
        this(target, 10);
    }

    public BlurDrawable(View target, int radius) {
        this.targetRef = new WeakReference<View>(target);
        setRadius(radius);
        target.setDrawingCacheEnabled(true);
        target.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_AUTO);
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
    }

    @Override
    public void draw(Canvas canvas) {
        if (blurred == null) {
            View target = targetRef.get();
            if (target != null) {
                Bitmap bitmap = target.getDrawingCache(true);
                if (bitmap == null) return;
                blurred = fastBlur(bitmap, radius);
            }
        }
        if (blurred != null && !blurred.isRecycled())
            canvas.drawBitmap(blurred, 0, 0, paint);
    }

    /**
     * Set the bluring radius that will be applied to target view's bitmap
     *
     * @param radius should be 0-100
     */
    public void setRadius(int radius) {
        if (radius < 0 || radius > 100)
            throw new InputMismatchException("Radius must be 0 <= radius <= 100 !");
        this.radius = radius;
        if (blurred != null) {
            blurred.recycle();
            blurred = null;
        }
        invalidateSelf();
    }


    public int getRadius() {
        return radius;
    }

    @Override
    public void setAlpha(int alpha) {
    }


    @Override
    public void setColorFilter(ColorFilter cf) {

    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    /**
     * from http://stackoverflow.com/a/10028267/3133545
     * <p/>
     * <p/>
     * <p/>
     * Stack Blur v1.0 from
     * http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
     * <p/>
     * Java Author: Mario Klingemann <mario at quasimondo.com>
     * http://incubator.quasimondo.com
     * created Feburary 29, 2004
     * Android port : Yahel Bouaziz <yahel at kayenko.com>
     * http://www.kayenko.com
     * ported april 5th, 2012
     * <p/>
     * This is a compromise between Gaussian Blur and Box blur
     * It creates much better looking blurs than Box Blur, but is
     * 7x faster than my Gaussian Blur implementation.
     * <p/>
     * I called it Stack Blur because this describes best how this
     * filter works internally: it creates a kind of moving stack
     * of colors whilst scanning through the image. Thereby it
     * just has to add one new block of color to the right side
     * of the stack and remove the leftmost color. The remaining
     * colors on the topmost layer of the stack are either added on
     * or reduced by one, depending on if they are on the right or
     * on the left side of the stack.
     * <p/>
     * If you are using this algorithm in your code please add
     * the following line:
     * <p/>
     * Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
     */
    private static Bitmap fastBlur(Bitmap sentBitmap, int radius) {


        Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);

        if (radius < 1) {
            return (null);
        }

        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        int[] pix = new int[w * h];
        Log.e("pix", w + " " + h + " " + pix.length);
        bitmap.getPixels(pix, 0, w, 0, 0, w, h);

        int wm = w - 1;
        int hm = h - 1;
        int wh = w * h;
        int div = radius + radius + 1;

        int r[] = new int[wh];
        int g[] = new int[wh];
        int b[] = new int[wh];
        int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
        int vmin[] = new int[Math.max(w, h)];

        int divsum = (div + 1) >> 1;
        divsum *= divsum;
        int dv[] = new int[256 * divsum];
        for (i = 0; i < 256 * divsum; i++) {
            dv[i] = (i / divsum);
        }

        yw = yi = 0;

        int[][] stack = new int[div][3];
        int stackpointer;
        int stackstart;
        int[] sir;
        int rbs;
        int r1 = radius + 1;
        int routsum, goutsum, boutsum;
        int rinsum, ginsum, binsum;

        for (y = 0; y < h; y++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            for (i = -radius; i <= radius; i++) {
                p = pix[yi + Math.min(wm, Math.max(i, 0))];
                sir = stack[i + radius];
                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);
                rbs = r1 - Math.abs(i);
                rsum += sir[0] * rbs;
                gsum += sir[1] * rbs;
                bsum += sir[2] * rbs;
                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }
            }
            stackpointer = radius;

            for (x = 0; x < w; x++) {

                r[yi] = dv[rsum];
                g[yi] = dv[gsum];
                b[yi] = dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (y == 0) {
                    vmin[x] = Math.min(x + radius + 1, wm);
                }
                p = pix[yw + vmin[x]];

                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);

                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + 1) % div;
                sir = stack[(stackpointer) % div];

                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];

                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];

                yi++;
            }
            yw += w;
        }
        for (x = 0; x < w; x++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            yp = -radius * w;
            for (i = -radius; i <= radius; i++) {
                yi = Math.max(0, yp) + x;

                sir = stack[i + radius];

                sir[0] = r[yi];
                sir[1] = g[yi];
                sir[2] = b[yi];

                rbs = r1 - Math.abs(i);

                rsum += r[yi] * rbs;
                gsum += g[yi] * rbs;
                bsum += b[yi] * rbs;

                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }

                if (i < hm) {
                    yp += w;
                }
            }
            yi = x;
            stackpointer = radius;
            for (y = 0; y < h; y++) {
                // Preserve alpha channel: ( 0xff000000 & pix[yi] )
                pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (x == 0) {
                    vmin[y] = Math.min(y + r1, hm) * w;
                }
                p = x + vmin[y];

                sir[0] = r[p];
                sir[1] = g[p];
                sir[2] = b[p];

                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + 1) % div;
                sir = stack[stackpointer];

                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];

                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];

                yi += w;
            }
        }

        bitmap.setPixels(pix, 0, w, 0, 0, w, h);

        return (bitmap);
    }

}

用法:

View beneathView = //the view that beneath blur view
View blurView= //blur View

BlurDrawable blurDrawable = new BlurDrawable(beneathView, radius);

blurView.setBackgroundDrawable(blurDrawable);

和我是如何测试应用程序看起来像:

And how my test application looked like:

我决定不使用这种寿,因为实在是太哈克并没有看的爽,因为我认为这将是摆在首位。

这篇关于透明模糊的视图,它的下方模糊布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆