使用blurview作为相对视图

时间:2015-05-02 20:42:14

标签: android android-layout

我目前正在使用从BlurringView.java文件(https://github.com/500px/500px-android-blur)获取的BluringView XML对象。它基本上只是一个自定义视图,模糊了它下面的兄弟视图。我遇到的问题是我不能用其他对象填充BlurringView。这是代码:

package com.fivehundredpx.android.blur;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.support.v8.renderscript.Allocation;
import android.support.v8.renderscript.Element;
import android.support.v8.renderscript.RenderScript;
import android.support.v8.renderscript.ScriptIntrinsicBlur;
import android.util.AttributeSet;
import android.view.View;

/**
 * A custom view for presenting a dynamically blurred version of another view's content.
 * <p/>
 * Use {@link #setBlurredView(android.view.View)} to set up the reference to the view to be blurred.
 * After that, call {@link #invalidate()} to trigger blurring whenever necessary.
 */
public class BlurringView extends View {

public BlurringView(Context context) {
    this(context, null);
}

public BlurringView(Context context, AttributeSet attrs) {
    super(context, attrs);

    final Resources res = getResources();
    final int defaultBlurRadius = res.getInteger(R.integer.default_blur_radius);
    final int defaultDownsampleFactor = res.getInteger(R.integer.default_downsample_factor);
    final int defaultOverlayColor = res.getColor(R.color.default_overlay_color);

    initializeRenderScript(context);

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PxBlurringView);
    setBlurRadius(a.getInt(R.styleable.PxBlurringView_blurRadius, defaultBlurRadius));
    setDownsampleFactor(a.getInt(R.styleable.PxBlurringView_downsampleFactor,
            defaultDownsampleFactor));
    setOverlayColor(a.getColor(R.styleable.PxBlurringView_overlayColor, defaultOverlayColor));
    a.recycle();
}

public void setBlurredView(View blurredView) {
    mBlurredView = blurredView;
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (mBlurredView != null) {
        if (prepare()) {
            // If the background of the blurred view is a color drawable, we use it to clear
            // the blurring canvas, which ensures that edges of the child views are blurred
            // as well; otherwise we clear the blurring canvas with a transparent color.
            if (mBlurredView.getBackground() != null && mBlurredView.getBackground() instanceof ColorDrawable){
                mBitmapToBlur.eraseColor(((ColorDrawable) mBlurredView.getBackground()).getColor());
            }else {
                mBitmapToBlur.eraseColor(Color.TRANSPARENT);
            }

            mBlurredView.draw(mBlurringCanvas);
            blur();

            canvas.save();
            canvas.translate(mBlurredView.getX() - getX(), mBlurredView.getY() - getY());
            canvas.scale(mDownsampleFactor, mDownsampleFactor);
            canvas.drawBitmap(mBlurredBitmap, 0, 0, null);
            canvas.restore();
        }
        canvas.drawColor(mOverlayColor);
    }
}

public void setBlurRadius(int radius) {
    mBlurScript.setRadius(radius);
}

public void setDownsampleFactor(int factor) {
    if (factor <= 0) {
        throw new IllegalArgumentException("Downsample factor must be greater than 0.");
    }

    if (mDownsampleFactor != factor) {
        mDownsampleFactor = factor;
        mDownsampleFactorChanged = true;
    }
}

public void setOverlayColor(int color) {
    mOverlayColor = color;
}

private void initializeRenderScript(Context context) {
    mRenderScript = RenderScript.create(context);
    mBlurScript = ScriptIntrinsicBlur.create(mRenderScript, Element.U8_4(mRenderScript));
}

protected boolean prepare() {
    final int width = mBlurredView.getWidth();
    final int height = mBlurredView.getHeight();

    if (mBlurringCanvas == null || mDownsampleFactorChanged
            || mBlurredViewWidth != width || mBlurredViewHeight != height) {
        mDownsampleFactorChanged = false;

        mBlurredViewWidth = width;
        mBlurredViewHeight = height;

        int scaledWidth = width / mDownsampleFactor;
        int scaledHeight = height / mDownsampleFactor;

        // The following manipulation is to avoid some RenderScript artifacts at the edge.
        scaledWidth = scaledWidth - scaledWidth % 4 + 4;
        scaledHeight = scaledHeight - scaledHeight % 4 + 4;

        if (mBlurredBitmap == null
                || mBlurredBitmap.getWidth() != scaledWidth
                || mBlurredBitmap.getHeight() != scaledHeight) {
            mBitmapToBlur = Bitmap.createBitmap(scaledWidth, scaledHeight,
                    Bitmap.Config.ARGB_8888);
            if (mBitmapToBlur == null) {
                return false;
            }

            mBlurredBitmap = Bitmap.createBitmap(scaledWidth, scaledHeight,
                    Bitmap.Config.ARGB_8888);
            if (mBlurredBitmap == null) {
                return false;
            }
        }

        mBlurringCanvas = new Canvas(mBitmapToBlur);
        mBlurringCanvas.scale(1f / mDownsampleFactor, 1f / mDownsampleFactor);
        mBlurInput = Allocation.createFromBitmap(mRenderScript, mBitmapToBlur,
                Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
        mBlurOutput = Allocation.createTyped(mRenderScript, mBlurInput.getType());
    }
    return true;
}

protected void blur() {
    mBlurInput.copyFrom(mBitmapToBlur);
    mBlurScript.setInput(mBlurInput);
    mBlurScript.forEach(mBlurOutput);
    mBlurOutput.copyTo(mBlurredBitmap);
}

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    if (mRenderScript != null){
        mRenderScript.destroy();
    }
}

private int mDownsampleFactor;
private int mOverlayColor;

private View mBlurredView;
private int mBlurredViewWidth, mBlurredViewHeight;

private boolean mDownsampleFactorChanged;
private Bitmap mBitmapToBlur, mBlurredBitmap;
private Canvas mBlurringCanvas;
private RenderScript mRenderScript;
private ScriptIntrinsicBlur mBlurScript;
private Allocation mBlurInput, mBlurOutput;

}

有没有办法修改BlurringView.java类,所以BlurringView xml对象可以像RelativeView或类似的东西一样使用?我希望能够让BlurringView成为其他对象的父级。

我需要这个,因为我正在使用BlurringView和SlidingUpPanelLayout(https://github.com/umano/AndroidSlidingUpPanel),而SlidingUpPanelLayout只允许两个子节点才能运行。因此,我不能只在BlurringView上叠加项目。我需要BlurringView作为他们的父母。

如果您需要澄清,请告诉我。

-R

1 个答案:

答案 0 :(得分:2)

  

Blockquote您是否尝试对构造函数执行提取方法,在三个默认构造函数中实现相同的方法并从RelativeLayout扩展?

     

RelativeLayout实际上有一个onDraw方法,可能没有被调用因为你没有调用方法setWillNotDraw(false),尝试使用该方法来触发onDraw或使用invalidate()构造函数的结尾。

@astinx回答了这个问题。

我所要做的就是更改BlurringView类以扩展RelativeLayout而不是View。然后我调用了setWillNotDraw(false)方法以及构造函数中的invalidate()方法,现在我可以用子项填充BlurringView了!魔法。

-R