模糊仅模糊图像而不是文本或其他内容

时间:2015-01-06 18:38:07

标签: android

当我打开导航抽屉时,我有一个BlurActionBarDrawerToggle来模糊我的背景:

public class BlurActionBarDrawerToggle extends ActionBarDrawerToggle {
    public static int DEFAULT_BLUR_RADIUS = 25;
    public static float DEFAULT_DOWNSCALEFACTOR = 8.0f;
    private Context context = null;
    private DrawerLayout drawerLayout = null;
    private ImageView blurredImageView = null;
    private int blurRadius = DEFAULT_BLUR_RADIUS;
    private float downScaleFactor = DEFAULT_DOWNSCALEFACTOR;
    private boolean prepareToRender = true;
    private boolean isOpening = false;

    public BlurActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, int openDrawerContentDescRes, int closeDrawerContentDescRes) {
        super(activity, drawerLayout, openDrawerContentDescRes, closeDrawerContentDescRes);

        this.context = activity.getBaseContext();
        this.drawerLayout = drawerLayout;

        this.init();
    }

    public BlurActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, Toolbar toolbar, int openDrawerContentDescRes, int closeDrawerContentDescRes) {
        super(activity, drawerLayout, toolbar, openDrawerContentDescRes, closeDrawerContentDescRes);

        this.context = activity.getBaseContext();
        this.drawerLayout = drawerLayout;

        this.init();
    }

    private void init() {
        this.blurredImageView = new ImageView(context);
        this.blurredImageView.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        this.blurredImageView.setClickable(false);
        this.blurredImageView.setVisibility(View.GONE);
        this.blurredImageView.setScaleType(ImageView.ScaleType.FIT_XY);

        this.drawerLayout.setScrimColor(this.context.getResources().getColor(android.R.color.transparent));
        this.drawerLayout.post(new Runnable() {
            @Override
            public void run() {
                drawerLayout.addView(blurredImageView, 1);
            }
        });
    }

    @Override
    public void onDrawerSlide(final View drawerView, final float slideOffset) {
        super.onDrawerSlide(drawerView, slideOffset);

        if (slideOffset == 0.f) {
            this.isOpening = false;
        } else {
            this.isOpening = true;
        }

        this.render();
        this.setAlpha(this.blurredImageView, slideOffset, 100);
    }

    @Override
    public void onDrawerClosed(View view) {
        this.prepareToRender = true;
        this.blurredImageView.setVisibility(View.GONE);
    }

    @Override
    public void onDrawerStateChanged(int newState) {
        super.onDrawerStateChanged(newState);

        if (newState == DrawerLayout.STATE_IDLE && !this.isOpening) {
            this.handleRecycle();
        }
    }

    private void render() {
        if (this.prepareToRender) {
            this.prepareToRender = false;

            Bitmap bitmap = loadBitmapFromView(this.drawerLayout);
            bitmap = scaleBitmap(bitmap);
            bitmap = Blur.fastblur(this.context, bitmap, this.blurRadius, false);

            this.blurredImageView.setVisibility(View.VISIBLE);
            this.blurredImageView.setImageBitmap(bitmap);
        }

    }

    public void setRadius(int radius) {
        this.blurRadius = radius < 1 ? 1 : radius;
    }

    public void setDownScaleFactor(float downScaleFactor) {
        this.downScaleFactor = downScaleFactor < 1 ? 1 : downScaleFactor;
    }

    private void setAlpha(View view, float alpha, long durationMillis) {
        final AlphaAnimation animation = new AlphaAnimation(alpha, alpha);

        animation.setDuration(durationMillis);
        animation.setFillAfter(true);

        view.startAnimation(animation);
    }

    private Bitmap loadBitmapFromView(View view) {
        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(bitmap);

        view.draw(canvas);

        return bitmap;
    }

    private Bitmap scaleBitmap(Bitmap myBitmap) {
        int width = (int) (myBitmap.getWidth() / this.downScaleFactor);
        int height = (int) (myBitmap.getHeight() / this.downScaleFactor);

        return Bitmap.createScaledBitmap(myBitmap, width, height, false);
    }

    private void handleRecycle() {
        Drawable drawable = this.blurredImageView.getDrawable();

        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = ((BitmapDrawable) drawable);
            Bitmap bitmap = bitmapDrawable.getBitmap();

            if (bitmap != null) {
                bitmap.recycle();
            }

            this.blurredImageView.setImageBitmap(null);
        }

        this.prepareToRender = true;
    }
}

使用此Blur方法:

public class Blur {

    public static Bitmap fastblur(Context context, Bitmap sentBitmap, int radius, boolean canReuseInBitmap) {
        Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);

        final RenderScript renderScript = RenderScript.create(context);
        final Allocation input = Allocation.createFromBitmap(renderScript, sentBitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);

        final Allocation output = Allocation.createTyped(renderScript, input.getType());
        final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));

        script.setRadius(radius);
        script.setInput(input);
        script.forEach(output);

        output.copyTo(bitmap);

        return bitmap;
    }
}

不幸的是,这只是背景图像等图像的模糊视图。 下图显示了带有图像背景的视图的模糊:

enter image description here

第二张图片显示了相同的导航抽屉和actionbardrawertoggle 在没有任何图像的视图上:

enter image description here

你可以看到这里什么都没有。有人能告诉我这里出了什么问题吗?

1 个答案:

答案 0 :(得分:4)

这实际上是三个因素的组合:

  1. 在模糊之前,图像会缩小尺寸(默认情况下为8倍)。这意味着非常薄的文本被缩小到非常小的尺寸
  2. 模糊然后将这些少数彩色像素“分散”到更大的区域(因子为25),这意味着模糊文本几乎难以察觉
  3. ImageView背景是透明的,因此在模糊图像后面仍然可以看到“真正的”TextView(由于1和2,该区域中大部分是透明的)。
  4. 最简单的解决方法是使用与活动背景颜色相同的值为blurredImageView设置背景颜色。没有其他更改,这意味着将隐藏其他UI元素(文本,行和&amp; c)。例如,在render()

    this.blurredImageView.setVisibility(View.VISIBLE);
    this.blurredImageView.setImageBitmap(bitmap);
    this.blurredImageView.setBackgroundColor(Color.RED);  // added
    

    如果您想使它们模糊但仍然隐约可见,请缩小缩小系数和半径,例如:

    mDrawerToggle.setDownScaleFactor(2);
    mDrawerToggle.setRadius(10);
    

    但是,请注意,这也会减少图像的模糊(以及为位图消耗更多内存)。