Dimezis / BlurView

Dynamic iOS-like blur of underlying Views for Android
Apache License 2.0
3.5k stars 333 forks source link

the blurview draw the overlayColor is incorrect #203

Open ncwuguowei opened 1 year ago

ncwuguowei commented 1 year ago

Please include: 1) Library version master branch 2). the blurview draw the overlayColor is incorrect. PreDrawBlurController#public boolean draw(Canvas canvas) { .... canvas.restore(); // NOTE: need delete there, because only draw overlayColor to blurView content. // current canvas.drawColor(overlayColor) will cause the whole canvas(decorView) draw the overlayColer if (overlayColor != TRANSPARENT) { canvas.drawColor(overlayColor); } return true; }

and method blurAndSave() to add draw overlayColor ,mix to bulred bitmap

private void blurAndSave() {
    internalBitmap = blurAlgorithm.blur(internalBitmap, blurRadius);
    if (!blurAlgorithm.canModifyBitmap()) {
        internalCanvas.setBitmap(internalBitmap);
    }
    //NOTE: modify only draw overlayColor to blurView content
    if (overlayColor != TRANSPARENT) {
        internalCanvas.drawColor(overlayColor);
    }
}
Dimezis commented 1 year ago

Post your setup. Normally it shouldn't matter, since the bitmap from internalCanvas is then being drawn on the system canvas anyway. And drawing on canvas is also confined within the view bounds

ncwuguowei commented 1 year ago

Hi, I found the cause of the problem.

  1. the overlayColor should be mixed with the Gaussian blurred graph(note:internalBitmap or internalCanvas) because when the whole root view draw, current only change the bluredView by onPreDraw , but when draw blurView itself, draw(Canvas canvas) is return @Override public boolean draw(Canvas canvas) { if (!blurEnabled || !initialized) { return true; } // Not blurring itself or other BlurViews to not cause recursive draw calls // Related: https://github.com/Dimezis/BlurView/issues/110 if (canvas instanceof BlurViewCanvas) { return false; } ... if (overlayColor != TRANSPARENT) { canvas.drawColor(overlayColor); } }

canvas.drawColor(overlayColor) , here can not execute. so the overlayColor can not draw.

  1. canvas.drawColor(overlayColor) is no size specified, the whole canvas draw the color. commonly we can not find this bug because the parent setClipChildren(true) by default, but when set setClipChildren(false), you can see the error.

I set the overlayColor is RED for demo

when RN setClipChildren(false) default image

when setClipChildren(true) for example

blurView.postDelayed(new Runnable() {
  @Override
  public void run() {
    Log.i("AndroidBlurView", "blurView width = " + blurView.getWidth() +
            " ,blurView height = " + blurView.getHeight());
    ViewGroup parent = (ViewGroup) blurView.getParent();
    parent.setClipChildren(true);
  }
}, 10 * 1000);

image

3.the error exist in React Native project , but I can not find in normal andord project even I set setClipChildren(false), why it draw in correct whthin the view bounds?

  1. so we should draw overlayColor with correct size and draw in onPrewDraw() by updateBlur().

    this React Native project use BlurView in Android , you can see this https://github.com/Kureev/react-native-blur

ncwuguowei commented 1 year ago

Ha ha, I can show error in your demo ~~~ Only drop outline provider in MainActivity, and set clicpChildren(false)

  1. main_activity.xml , set root view clipChildren(false) image

  2. MainActivity.java
    drop the outline code , and to set overlayColor Red show clearly. private void initView() { viewPager = findViewById(R.id.viewPager); tabLayout = findViewById(R.id.tabLayout); bottomBlurView = findViewById(R.id.bottomBlurView); topBlurView = findViewById(R.id.topBlurView); // Rounded corners + casting elevation shadow with transparent background // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // topBlurView.setClipToOutline(true); // topBlurView.setOutlineProvider(new ViewOutlineProvider() { // @Override // public void getOutline(View view, Outline outline) { // topBlurView.getBackground().getOutline(outline); // outline.setAlpha(1f); // } // }); // } radiusSeekBar = findViewById(R.id.radiusSeekBar); root = findViewById(R.id.root); }

image

I think the outline affect the bulrView draw, so the demo usually can not find this bug.