android - 使用模糊 View 作为相对 View

标签 android android-layout

我目前正在使用从 BlurringView.java 文件 ( https://github.com/500px/500px-android-blur ) 获得的 BluringView XML 对象。它基本上只是一个自定义 View ,模糊了它下面的兄弟 View 。我遇到的问题是我无法用其他对象填充 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 类,以便可以像 RelativeView 或类似的东西一样使用 BlurringView xml 对象?我希望能够让 BlurringView 成为其他对象的父对象。

我需要这个,因为我将 BlurringView 与 SlidingUpPanelLayout ( https://github.com/umano/AndroidSlidingUpPanel ) 一起使用,而 SlidingUpPanelLayout 只允许两个子级运行。因此我不能只在 BlurringView 上叠加项目。我需要 BlurringView 成为他们的 parent 。

如果您需要说明,请告诉我。

-R

最佳答案

Blockquote Did you try to do an extract method of your constructor, implement the same methon in each of the three default constructors and extend from RelativeLayout?

The RelativeLayout actually have a onDraw method, maybe isn't being called because you didn't invoke the method setWillNotDraw(false), try using that method to trigger the onDraw or use an invalidate() at the end of the constructors.

@astinx 回答了这个问题。

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

-R

关于android - 使用模糊 View 作为相对 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30007257/

相关文章:

java.lang.RuntimeException : Unable to start service java. lang.NullPointerException

android - GCM 一段时间后停止工作

android - 如何使用 XML 在 Android 上放大我的图像?

Android 照片上传到 facebook 使用图形 api?

android - 膨胀类 com.paypal.checkout. paymentbutton.PaymentButtonContainer 时出错

android - 类型不匹配。必需 : Nothing Found: Callback<*>

java - 什么是 ArrayAdapter?

java - Android - 错误 list 合并失败

android - 如何删除android Ice Cream Sandwich 中的软按钮/菜单?

android-layout - Android 服务和 AlertDialog Activity