Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using with Jetpack Compose #157

Closed
LorenzoFerri opened this issue Oct 12, 2021 · 24 comments
Closed

Using with Jetpack Compose #157

LorenzoFerri opened this issue Oct 12, 2021 · 24 comments

Comments

@LorenzoFerri
Copy link

Hi, I would like to use this library in a Jetpack Compose project however I'm not finding any success. Could you provide a simple Composable component that with an AndroidView or a AndroidViewBinding wrap your library? Thank you

@Dimezis
Copy link
Owner

Dimezis commented Oct 13, 2021

Not sure if I understand what problem you're having exactly.
Why can't you wrap it into AndroidView yourself?

@LorenzoFerri
Copy link
Author

LorenzoFerri commented Oct 13, 2021

Hi, thank you for the reply. I'm trying to create a blurred effect in the TopBar of my app. The app is entirely written in Jetpack Compose.
I tried to wrap everything like this, however I did not understand what should I pass to the method setupWith since I don't have a rootView (or I don't know how to get it).

@Composable
fun TopBar() {
    AndroidView(
        modifier = Modifier
            .fillMaxWidth()
            .height(56.dp),
        factory = { context ->
            BlurView(context).apply {
                this.setupWith(this) // <- Here
                    .setBlurAlgorithm(RenderScriptBlur(context))
                    .setBlurRadius(20f)
                    .setBlurAutoUpdate(true)
            }
        }
    )
}

If it's helpful, since it's a TopBar, the content behind is scrollable.
Thank you again.

@Dimezis
Copy link
Owner

Dimezis commented Oct 13, 2021

If your composable is written within the Activity, just get a reference to it and do

val decorView = activity.window.decorView
val rootView = decorView.findViewById<ViewGroup>(android.R.id.content)

If you don't have a reference to the Activity, you can cast the context to Activity, though that's a bit hacky and I'm not sure if the preview in AS will be rendered correctly.

You can also just pass the Activity reference to your TopBar Composable

@LorenzoFerri
Copy link
Author

I tried both with casting and passing the MainActivity to my TopBar, but in both cases the application crashes with this error:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: io.dachain.dachain, PID: 3146
    java.lang.IllegalStateException: Recording currently in progress - missing #endRecording() call?
        at android.graphics.RenderNode.beginRecording(RenderNode.java:372)
        at android.graphics.RenderNode.beginRecording(RenderNode.java:391)
        at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:151)
        at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:243)
        at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:677)
        at android.view.View.draw(View.java:22353)
        at android.view.View.draw(View.java:22223)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.draw(View.java:22221)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.draw(View.java:22353)
        at eightbitlab.com.blurview.BlockingBlurController.updateBlur(BlockingBlurController.java:122)
        at eightbitlab.com.blurview.BlockingBlurController.draw(BlockingBlurController.java:164)
        at eightbitlab.com.blurview.BlurView.draw(BlurView.java:51)
        at android.view.View.updateDisplayListIfDirty(View.java:21226)
        at android.view.View.draw(View.java:22081)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.draw(View.java:22353)
        at androidx.compose.ui.platform.AndroidViewsHandler.drawView(AndroidViewsHandler.android.kt:72)
        at androidx.compose.ui.platform.AndroidComposeView.drawAndroidView(AndroidComposeView.android.kt:481)
        at androidx.compose.ui.viewinterop.AndroidViewHolder$layoutNode$1$coreModifier$1.invoke(AndroidViewHolder.android.kt:235)
        at androidx.compose.ui.viewinterop.AndroidViewHolder$layoutNode$1$coreModifier$1.invoke(AndroidViewHolder.android.kt:232)
        at androidx.compose.ui.draw.DrawBackgroundModifier.draw(DrawModifier.kt:101)
        at androidx.compose.ui.node.ModifiedDrawNode.performDraw(ModifiedDrawNode.kt:102)
        at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:244)
        at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performDraw(DelegatingLayoutNodeWrapper.kt:68)
        at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:244)
        at androidx.compose.ui.node.DelegatingLayoutNodeWrapper.performDraw(DelegatingLayoutNodeWrapper.kt:68)
        at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:244)
        at androidx.compose.ui.node.ModifiedLayoutNode.performDraw(ModifiedLayoutNode.kt:98)
        at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:244)
        at androidx.compose.ui.node.ModifiedLayoutNode.performDraw(ModifiedLayoutNode.kt:98)
        at androidx.compose.ui.node.LayoutNodeWrapper$invoke$1.invoke(LayoutNodeWrapper.kt:255)
        at androidx.compose.ui.node.LayoutNodeWrapper$invoke$1.invoke(LayoutNodeWrapper.kt:254)
        at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:1776)
        at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:123)
        at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:75)
        at androidx.compose.ui.node.LayoutNodeWrapper.invoke(LayoutNodeWrapper.kt:254)
        at androidx.compose.ui.node.LayoutNodeWrapper.invoke(LayoutNodeWrapper.kt:54)
        at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:156)
        at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:243)
        at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:677)
        at android.view.View.draw(View.java:22353)
        at android.view.View.draw(View.java:22223)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.draw(View.java:22221)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4516)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4277)
        at android.view.View.draw(View.java:22353)
        at eightbitlab.com.blurview.BlockingBlurController.updateBlur(BlockingBlurController.java:122)
        at eightbitlab.com.blurview.BlockingBlurController$1.onPreDraw(BlockingBlurController.java:56)
        at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:1093)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3089)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
        at android.view.Choreographer.doCallbacks(Choreographer.java:796)
        at android.view.Choreographer.doFrame(Choreographer.java:731)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
I/Process: Sending signal. PID: 3146 SIG: 9

My updated code looks like this:

@Composable
fun TopBar(activity: MainActivity) {
    val decorView = activity.window.decorView
    val rootView = decorView.findViewById<ViewGroup>(android.R.id.content)
    val windowBackground = decorView.background;
    AndroidView(
        modifier = Modifier
            .fillMaxWidth()
            .height(56.dp),
        factory = { context ->
            BlurView(context).apply {
                this.setupWith(rootView)
                    .setFrameClearDrawable(windowBackground)
                    .setBlurAlgorithm(RenderScriptBlur(context))
                    .setBlurRadius(20f)
                    .setBlurAutoUpdate(true)
            }
        }
    )
}

@Dimezis
Copy link
Owner

Dimezis commented Oct 13, 2021

Then I guess the BlurView is not compatible with Composable hierarchies.
I'm slightly interested in why it happens, so I might check it out later, but most likely this won't be fixed

@rabross
Copy link

rabross commented Nov 9, 2021

@LorenzoFerri If you are interested Modifier.blur() is available in Compose 1.1.0-alpha03 on Android 12

@LorenzoFerri
Copy link
Author

@LorenzoFerri If you are interested Modifier.blur() is available in Compose 1.1.0-alpha03 on Android 12

I tried that Modifier, but it doesn’t achieve what I need, blurring only the composable itself and not what's behind it.

@ComposeDesigner
Copy link

@LorenzoFerri
Did you get this to work using Compose? I am stuck with the same issue!

@jakub-cosmose
Copy link

I've spent some time trying to achieve the blurring effect in Compose using this library and anything else that I was able to find, but I haven't found any solution. So, currently, migrating my project to Compose is put on hold indefinitely.

@ComposeDesigner
Copy link

ComposeDesigner commented Jan 27, 2022

I haven't found a solution either. But I noticed that using @LorenzoFerri's code stops throwing an error if I don't use a Modifier in the AndroidView section however the blur itself is pretty weird and not the desired effect. So I wonder if it has something to do with that. I'd love to find a solution to this.

@tengyeekong
Copy link

It would be really great if BlurView can be used in Jetpack Compose :')

@HasanHaghniya
Copy link

Any updates?

@Dimezis
Copy link
Owner

Dimezis commented May 15, 2022

@SecretKeeper
I've opened an issue here - https://issuetracker.google.com/issues/232625913
I don't think there's anything reasonable I can do to fix this crash on my side.
The Compose's behavior doesn't look right to me in this case.

Star it if you'd like to help

@tengyeekong
Copy link

I tried moving the setupWith into update block and it works, but it only renders for the first time..
Screenshot 2022-05-15 at 11 27 40 PM

@Dimezis
Copy link
Owner

Dimezis commented May 15, 2022

I tried moving the setupWith into update block and it works

Unfortunately, it's probably some (un)lucky quirk of your particular setup, because there's a fundamental problem preventing it from working correctly.
Also, it still crashes for me even with this delayed setup

@Dimezis
Copy link
Owner

Dimezis commented Jul 18, 2022

Version 2.0.2 should fix this problem, but I'm not sure it's going to be working in every scenario.
But you can try and let me know how it went

@Dimezis Dimezis closed this as completed Nov 24, 2022
@jianinz
Copy link

jianinz commented Jun 30, 2023

Hi @Dimezis, sorry to comment on the closed issue, but I found this is relavent to my question, I am curious about what if the root view is composable? Basically I have a composable that is ready to be used, I just want its background to be blured, I tried to embed BlurView into AndroidView, but how to integrate composable in this case? Could you shed some lights, thanks!


@Composable
fun HomeBottomBar(){
// Composable goes here
}


@Composable
fun AndroidViewBasedCompose(){
    val context = LocalContext.current
    val decorView = context.activity.window.decorView
    val rootView = decorView.findViewById<ViewGroup>(android.R.id.content). //Where can I get this??? It's a composable in my case
    val windowBackground = decorView.background;
    AndroidView(
        modifier = Modifier
            .fillMaxWidth()
            .height(56.dp),
        factory = { context ->
            BlurView(context).apply {
                this.setupWith(rootView)
                    .setFrameClearDrawable(windowBackground)
                    .setBlurAlgorithm(RenderScriptBlur(context))
                    .setBlurRadius(20f)
                    .setBlurAutoUpdate(true)
            }
        }
    )
}

// Utility function for getting activity ref
fun Context.getActivity(): AppCompatActivity? = when (this) {
    is AppCompatActivity -> this
    is ContextWrapper -> baseContext.getActivity()
    else -> null
}

@Dimezis
Copy link
Owner

Dimezis commented Jun 30, 2023

@jianinz I'm not sure if I understand your problem.

val rootView = decorView.findViewById(android.R.id.content). //Where can I get this??? It's a composable in my case

android.R.id.content can't be a composable. It's a default ViewGroup present in every Activity.

Your setup looks fine, though I didn't test it.
What's the problem exactly and what happens when you use AndroidViewBasedCompose?

@jianinz
Copy link

jianinz commented Jun 30, 2023

@Dimezis Thanks for your quick response! In the example here https://github.com/Dimezis/BlurView#how-to-use, BlurView will have any child view which will not be blured. In my case, the child view will be a composable, I wonder how to integrate that composable into BlurView?

Should I just do something like:

              Box {
                HomeBottomBar(
                )
                AndroidViewBasedCompose()
              }

@jianinz
Copy link

jianinz commented Jun 30, 2023

If I use code below

@Composable
fun AndroidViewBasedCompose(){
    val context = LocalContext.current
    val decorView = context.activity.window.decorView
    val rootView = decorView.findViewById<ViewGroup>(android.R.id.content)
    val windowBackground = decorView.background
    AndroidView(
        modifier = Modifier
            .fillMaxWidth()
            .height(56.dp),
        factory = { context ->
            BlurView(context).apply {
                this.setupWith(rootView)
                    .setFrameClearDrawable(windowBackground)
                    .setBlurAlgorithm(RenderScriptBlur(context)) // No longer available in the version 2.0.3
                    .setBlurRadius(20f)
                    .setBlurAutoUpdate(true)
            }
        }
    )
}
              Box {
                HomeBottomBar(
                )
                AndroidViewBasedCompose()
              }

I don't see the blured view, instead I see the mono background colored bottom bar, no blur effect takes into place

@Dimezis
Copy link
Owner

Dimezis commented Jun 30, 2023

Should I just do something like:
...

Yes, although I think the order should be

Box {
    AndroidViewBasedCompose()
    HomeBottomBar()                
}

And the HomeBottomBar has to have a transparent background for the BlurView to be visible.

Edit:
On second thought, in this case, the BlurView would also include the bottom bar into its blurred content, so that might not be doable in the end.

@jianinz
Copy link

jianinz commented Jun 30, 2023

On second thought, in this case, the BlurView would also include the bottom bar into its blurred content, so that might not be doable in the end.

Yeah, just tried changing order, in the end the blur view does not show up, is there any ways to include the bottom bar into its blurred content?

@Dimezis
Copy link
Owner

Dimezis commented Jun 30, 2023

in the end the blur view does not show up

As I said, the bottom bar composable has to have a transparent background. I don't know if it's adjustable though

@jianinz
Copy link

jianinz commented Jun 30, 2023

As I said, the bottom bar composable has to have a transparent background. I don't know if it's adjustable though

I set HomeBottomBar's background color as transparent and blur view as purple, unfortunately the result is just transparent HomeBottomBar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants