GithubHelp home page GithubHelp logo

chrisbanes / haze Goto Github PK

View Code? Open in Web Editor NEW
937.0 8.0 25.0 72.05 MB

A blurring modifier for Compose Multiplatform / Jetpack Compose

Home Page: https://chrisbanes.github.io/haze/

License: Apache License 2.0

Kotlin 98.46% Shell 1.54%
blur compose-multiplatform jetpack-compose

haze's Introduction

Maven Central Build status

Haze

Check out the website for more information: https://chrisbanes.github.io/haze

License

Copyright 2023 Chris Banes
 
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

haze's People

Contributors

almozavr avatar chrisbanes avatar dev-weiqi avatar dynaruid avatar jorgedotcom avatar lhoyong avatar mikepenz avatar mohamedrejeb avatar nevrozza avatar qdsfdhvh avatar renovate[bot] avatar simonlebras avatar twyatt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

haze's Issues

Ignoring bottom windows insets

Information

  • Haze version: 0.4.1
  • Platform: Android

Expected Behavior

video 2 = haze_without_nav.webm

Actual Behavior

video 1 = haze.webm

project where you can test the issue:
Haze.zip

Steps to Reproduce the Problem

Simple edge-to-edge project with top and bottom bar(with HAZE) blur

  1. create simple Scaffold with:
image

2.1. this provide issue like on video 1:
image

2.2. this case works like needs if remove NavHost:
image

  1. using the debugger note next moment:

3.1. default start of the app:
image
HazeArea[1](bottom bar) -> Size(1080,210)

3.2. recomposition after changing theme:
image
HazeArea[1](bottom bar) -> Size(1080, 147)

So it looks like it ignore the height of navigation bar during recomposition(after changing theme).
P.s. if change orientation - works well

Blur frozen on Android API 31

On Android 12 (API 31) the blur is frozen while scrolling.
Only when the bottom navigation appears or disappears the blur quickly updates and is then frozen again.

Seems like HazeNode31.onObservedReadsChanged() is not called. Probably a bug in Compose or can we do something about it?

See attached video of the android-jetpack sample on API 31. It is working as expected on API 32.

haze-api31.mp4

Support for older Android systems

Many thanks to you Chris and other contributors for this awesome library! It works like charm, unlike numerous fancy, but intangible solutions available out there.
This is not an issue, but rather a feature request. How likely it is that this library may support RenderScript-based blur for the older Android versions (pre-Android 12)? Is a pull request to add such functionality something that you guys would consider?

uses-sdk:minSdkVersion 21 cannot be smaller than version 24 declared in library

Manifest merger failed : uses-sdk:minSdkVersion 21 cannot be smaller than version 24 declared in library [dev.chrisbanes.haze:haze-jetpack-compose:0.4.1] /Users/yd-sz-dn0588/.gradle/caches/transforms-3/b2ddb0cf5d948a8541195c91900041ce/transformed/haze-jetpack-compose-0.4.1/AndroidManifest.xml as the library might be using APIs not available in 21
Suggestion: use a compatible library with a minSdk of at most 21,
or increase this project's minSdk version to at least 24,
or use tools:overrideLibrary="dev.chrisbanes.haze.jetpackcompose" to force usage (may lead to runtime failures)

Shape visual issue

Information

  • Haze version: 0.5.3
  • Platform: Android13
  • Compose version: 1.6.0

Expected Behavior

Correct rounded corners without white lines.

Actual Behavior

The rounded corners have white lines.
82f8537e02f1434d9c89d49b192b394
72b678ad9c8f1c0ea63edab7f1d035e

Steps to Reproduce the Problem

Box {
  Image(
      modifier = Modifier
          .fillMaxSize()
          .haze(
              state = hazeState
          ),
      painter = painterResource(
          id = R.drawable.test
      ),
      contentDescription = "",
      contentScale = ContentScale.Crop
  )

  Box(
      modifier = Modifier
          .align(Alignment.Center)
          .padding(horizontal = 14.dp)
          .height(80.dp)
          .fillMaxWidth()
          .hazeChild(
              state = hazeState,
              shape = RoundedCornerShape(20.dp),
              style = HazeStyle(noiseFactor = 0f, tint = Color.Black.copy(.6f))
          ),
  )
}

Wasm Support Request

Can you add Wasm support? Or just add the Wasm target without applying the blur effect. Thank you!

Haze offsets when using a TopAppbar with a scroll behavior

Information

  • Haze version: 0.6.2
  • Platform: iOS 17.3

Expected Behavior

Haze remains in place.

Actual Behavior

Haze offsets when using a TopAppBar with a scroll behavior

Steps to Reproduce the Problem

I took one of your samples from the documentation and modified it a bit:
https://gist.github.com/artsmvch/e0a3c2b25714f48de2e938b653b6eb42

The difference is that the TopAppBar has a scroll behaviour connected to the list.

  1. Launch the app
  2. Scroll the list
  3. Observe the bottom haze offsets

Please check the video attached

Untitled.mp4

[Skiko] Edges are not blurred

This is a spin-off from #109 for Skiko platforms.

The Skiko platforms (iOS and Desktop) are trickier to fix, as we don't have the same control over the drawing pipeline (no RenderNode). The problem is that we use ImageFilter.makeMerge() to composite all of our filters together, including the source content. The filters tend to include transparent/translucent pixels, which means that the effects drawn on top will nearly always be translucent. The source content is drawn behind all of the filters, so the non-blurred parts you see is actually just translucent blurred effects with the content drawn again behind.

The fix for Android (#113) is to clipPath() the source content, so that only the effect OR content is drawn at a given coordinate. There might be some clever stuff we can do with BlendMode to achieve similar with Skiko, but it needs some thought.

Blur happens also in children

Hey :)

I'm trying to apply the blur effect on the below case:

Screenshot_20240104-171256

I have a face to face call, the feed is almost edge-to-edge with a control bar at the bottom. I'm trying to have Haze blur the rounded background but I get this effect instead.

I can still see the feed through, but the controls are being blurred instead.

Here is how I'm achieving this:

// On the root composable
val hazeState = remember { HazeState() }

BoxWithConstraints(
    contentAlignment = Alignment.Center,
    modifier = Modifier
        .fillMaxSize()
        .background(MyTheme.colors.background)
        .haze(
            state = hazeState,
            backgroundColor = MyTheme.colors.backgroundControls,
        )
// On the control background
Box(
    modifier = Modifier
        .matchParentSize()
        .padding(
            start = horizontalPadding,
            end = horizontalPadding,
            bottom = MyTheme.grid.unitFactor(2.5f),
         )
         .hazeChild(
             state = hazeState,
             shape = MyTheme.shapes.roundRad16,
         )
         .background(
             color = MyTheme.colors.backgroundControls,
             shape = MyTheme.shapes.roundRad16,
         )
         .padding(
             top = MyTheme.grid.unitFactor(2.5f),
             start = MyTheme.grid.unitFactor(3f),
             end = MyTheme.grid.unitFactor(3f),
             bottom = MyTheme.grid.unitFactor(2.5f),
          ),
 ) {}

Is it even possible to do it with haze? can you exclude children composables?
Is the SurfaceView underneath disrupting the modifier?

Why hazy not work?

Information

  • Haze version: 0.7.1
  • Platform: Android Jetpack Compose

Expected Behavior

TopAppBar blur the background

Actual Behavior

TopAppBar has no effect
Screenshot_2024-05-09-15-20-10-754_com wtkj app c

Steps to Reproduce the Problem

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Test() {
    val hazeState = remember { HazeState() }

    Box {
        LazyColumn(modifier = Modifier.fillMaxSize().haze(state = hazeState)) {
            item {
                Image(
                    painter = painterResource(id = R.drawable.main_bg),
                    contentDescription = null,
                    modifier = Modifier.fillMaxSize(),
                    contentScale = ContentScale.Crop,
                )
            }
        }
        LargeTopAppBar(
            colors = TopAppBarDefaults.largeTopAppBarColors(Color.Transparent),
            title = { Text(text = "Test Page") },
            modifier = Modifier.hazeChild(state = hazeState).fillMaxWidth(),
        )
    }
}

[0.4.5] Webview flashing when using with haze

Looks like haze is having issues with Webviews, Our QA's found this in our real app code we we had to revert for now, but I've created a simple example to reproduce here: Just a fork with a webview sample added. Had to drop toolchain to 17 but that's nothing to do with the issue just my current setup.

wezley98@82427ef

API 34 emulator

Screen_recording_20240115_105304.webm

For our usecase: most of the app is native which works fine with the bottombar and haze. But some screens are still been migrated away from webviews, when using haze with webviews we see this repeated flashing issue.

Haze background color differs from specified one

Description

The background behind the haze rectangle does not seem to honor the specified color.

Details

In version 0.2.0 the background color specified in the haze modifier does not appear to render correctly. In my use case the background is MaterialTheme.colorScheme.surface and I configure haze as shown here and below

.haze(
    headerSize.toRect(),
    backgroundColor = MaterialTheme.colorScheme.surface,
    tint = MaterialTheme.colorScheme.surface.copy(alpha = .5f),
    blurRadius = 16.dp,
)

The app background is defined as shown here

@Composable
private fun AppBackground(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    Box(
        modifier = modifier
            .background(
                Brush.verticalGradient(
                    BackgroundGradientStart to MaterialTheme.colorScheme.surface,
                    1f to MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp),
                ),
            ),
    ) {
        content()
    }
}

with BackgroundGradientStart set to .33f, so the top 1/3 of the screen is Surface color and the bottom 2/3 gradually ligtens said color.

Samples

In haze 0.1.0 the translucent pane blends with the background:
haze_0 1 0

In haze 0.2.0 the pane is visible as a lighter tone:
haze_0 2 0

For context, this is the pane with content behind:
Screenshot_1699026730

JS support request

Can you add JS support? Or just add the JS target without applying the blur effect. Thank you!

Regression in 0.5: Haze background shows different tint

Information

  • Haze version: 0.5
  • Platform: Android

Expected Behavior

The haze area should be indistinguishable when nothing is behind it.

Actual Behavior

On 0.5 using the defaults for the HazeStyle the haze background shows on a different color.

Steps to Reproduce the Problem

See this PR: https://github.com/fvilarino/Weather-Sample/pull/412/files

But basically I did the auto-replace for the deprecated haze method, changing

                     .haze(
                         state = hazeState,
                         backgroundColor = MaterialTheme.colorScheme.surface,
                          tint = MaterialTheme.colorScheme.surface.copy(alpha = .5f),
                         blurRadius = 16.dp,
                      ),

to

                     .haze(
                         state = hazeState,
                         style = HazeStyle(
                             tint = MaterialTheme.colorScheme.surface.copy(alpha = .5f),
                             blurRadius = 16.dp,
                             noiseFactor = HazeDefaults.noiseFactor,
                         ),
                     ),

Note that if the noise factor is set to 0f the problem goes away. so this seems reminiscent of this issue: #20

On 0.4.5:

Screenshot_1706804864

On 0.5:

Screenshot_1706804831

Position mismatch with scale transform

Information

  • Haze version: 0.7.1
  • Platform: Android

Position mismatch with android predictive back gesture. The blur moves along with the back animation while other UI elements are on their respective positions.

PS: I'm using decompose for navigation. The back animation code is similar to this - https://github.com/msasikanth/twine/blob/e5635d10afc3f4d0aea6310ed8c3c67af9a8d249/shared/src/androidMain/kotlin/dev/sasikanth/rss/reader/app/BackAnimation.kt#L42

Screen recording :

2024-05-05.01.06.04.mp4

Add screenshot testing

Screenshot testing will be useful in ensuring now regressions in the rendered effect. We'll need to use emulator/simulators due to the way that the effects are implemented, which makes it tricky on GitHub Actions.

Optional tint?

Supplying a transparent tint crashes (due to lack of alpha, I'm guessing?), so I'm currently supplying white with the lowest possible alpha value to achieve the effect I want (as close as I can).

My use case is a hazy bottom bar in a scaffold. Screens slide in and out of the scaffold. I'm animating the bottom bar to slide off screen when it's conditionally hidden. When a screen containing a haze child (scrollable content) slide-exits the scaffold while simultaneously hiding the bottom bar, the tint, although visually belonging to the bottom bar, can be sliding away with the exiting content. If tint were absent, I could just set a translucent background on the bottom bar. Was there a reason for requiring tint?

Expose "fallbck" tint logic

Information

  • Haze version: 0.5.0
  • Platform: Android

Context

If blur is not supported (e.g. <=31), Haze applies additional transformation to the tint color provided โ€“ boosts alpha.

private fun Color.boostAlphaForBlurRadius(blurRadius: Dp): Color {

Expected Behavior

The tint color provided to Haze should not change implicitly or this logic could be replaced adhoc.

Actual Behavior

The color (alpha) is not as provided.

Motivation

Our theme demands completely different background colors for blur-ready and non-blur states. As we already use haze, we don't want to introduce this then if(blurAvailable) Modifier.hazeChild(...) else Modifier.background(...) style but rather decide this on the color scheme level. Currently, we overcome boosting behaviour by setting blur radius on the theme-level local providable, but this is very implicit logic.

Blurring overlaying top content

Information

  • Haze version: 0.5.1
  • Platform: Android

Blurring the lower stacked content inside a box putting an overlay or blurring on the top stacked content in the box

val hazeState = remember { HazeState() }

Box(
  modifier = Modifier
    .fillMaxSize()
    .background(Color.White)
    .haze(hazeState)
) {
    Column(
        modifier = Modifier.align(Alignment.Center),
        verticalArrangement = Arrangement.spacedBy(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        repeat(3) {
            Text(
                modifier = Modifier
                    .background(
                        Color.Black,
                        MaterialTheme.shapes.medium,
                    )
                    .hazeChild(
                        state = hazeState,
                        shape = MaterialTheme.shapes.medium,
                        style = HazeStyle(
                            tint = Color.Transparent,
                            blurRadius = 4.dp,
                        )
                    )
                    .padding(8.dp),
                text = "$it Index",
                color = Color.White
            )
        }
    }
    Box(
        modifier = Modifier
            .align(Alignment.Center)
            .fillMaxWidth(0.7f)
            .height(18.dp)
            .background(Color.Green)
    )
}

image

Paparazzi Snapshot tests failing between 0.4.1 -> 0.4.2

As title, we integrated haze into our project at 0.4.1, but any version above 0.4.2/0.4.3/0.4.4 doesn't show the haze in our snapshots anymore.

0.4.4 Delta

delta-com sky sport group snapshots components_CarouselListComponentSnapshotTest_testCarouselListComponent NEXUS_5,1 0,10 Tile(layout=Hero, images=Images(sixt ,Light

Example Usage

Box(modifier = Modifier.clip(RoundedCornerShape(8.dp))) {
            val imageSizeModifier = Modifier
                .aspectRatio(ratio = AspectRatio.FOUR_BY_THREE.ratio)

            val hazeState = remember { HazeState() }

            UrlImage(
                modifier = imageSizeModifier.then(
                    if (tile.containsVideo) {
                        Modifier.haze(
                            state = hazeState,
                            backgroundColor = SkyTheme.skyColors.black.copy(alpha = 0.2f),
                            tint = SkyTheme.skyColors.black.copy(alpha = 0.2f)
                        )
                    } else {
                        Modifier
                    }
                ),
                url = tile.images.fourByThree ?: tile.images.sixteenByNine,
                mode = AspectRatio.FOUR_BY_THREE,
                imageCropsConfig = imageCropsConfig
            )

            if (tile.containsVideo) {
                TileVideoContentTimestampComponent(
                    tile = tile,
                    modifier = Modifier
                        .padding(start = 8.dp, bottom = 8.dp)
                        .hazeChild(state = hazeState, shape = RoundedCornerShape(2.dp))
                        .align(Alignment.BottomStart),
                    carouselTile = false
                )
                if (tile.contentLocked) {
                    LockedComponent(
                        contentTitle = tile.title,
                        modifier = imageSizeModifier
                    )
                }
            }
        }

HazyChild in scrollable won't move with the object when the overscroll effect gets triggered

Information

  • Haze version: 0.5.0
  • Platform: Android, Jetpack compose

Hi, I've just found your library and this is something we have been looking for in multiple projects but were never able to implement for Android. Thanks for building this. I did find a bug or maybe something that has not been implemented yet and wanted to let you know.

Expected Behavior

When using hazyChild in a scrollable it should move with the item when overscroll effect gets triggered.

Actual Behavior

When adding hazyChild to lazy column items and scrolling everything works as expected.
However when you pull a bit further and the overscroll effect gets triggered the blur stays in the same place while the item moves, showing the blur next to the item.

Steps to Reproduce the Problem

@Composable
private fun ListExample() {
    val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
    val hazeState = remember { HazeState() }

    Box(modifier = Modifier.fillMaxSize()) {
        Text(
            text = "Background text",
            style = MaterialTheme.typography.headlineLarge,
            modifier = Modifier
                .align(Alignment.Center)
                .haze(hazeState)
        )

        LazyColumn(verticalArrangement = Arrangement.spacedBy(24.dp)) {
            items(numbers) {
                Card(
                    colors = CardDefaults.cardColors(containerColor = Color.Blue.copy(alpha = 0.4f)),
                    modifier = Modifier
                        .padding(24.dp)
                        .hazeChild(hazeState, shape = RoundedCornerShape(16.dp))
                ) {
                    Box(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(vertical = 48.dp)
                    ) {
                        Text(text = "item $it", modifier = Modifier.align(Alignment.Center))
                    }
                }
            }
        }
    }
}
hazy-scroll-bug.mp4

Preview Fails to Render

The Preview in Android Studio for Jetpack Compose fails to render when using the .haze(...) Modifier:

java.lang.IllegalArgumentException: Software rendering doesn't support drawRenderNode
 ย ย at android.graphics.Canvas.drawRenderNode(Canvas.java:2329)
 ย ย at dev.chrisbanes.haze.HazeNode31.draw(HazeNode31.kt:125)

This could be solved by wrapping the haze modifier in a if (!LocalInspectionMode.current) { ... } but it's not the most elegant solution to repeat this over and over again on caller side.

Version: 0.4.1
Artifact: dev.chrisbanes.haze:haze-jetpack-compose

--

In general the Preview support could be improved.
We are facing the following issues challenges:

  1. Preview does not work at all
    (see exception above)

  2. Background for Preview of hazeChild
    When applying the haze Modifier only if !LocalInspectionMode.current, then the hazeChild has a transparent background in the preview, since the background/tint color is configured on haze Modifier side. Adding a background for Preview purposes, could be solved by using if (!LocalInspectionMode.current) { hazeChild(...) } else { background(backgroundColor) }. Which is not optimal since we need to duplicate the background color.

  3. Preview across components/files
    Sometimes we do have the haze Modifier in one file (e.g. the screen with a lazy column) and the hazeChild in another (e.g. the bottom navigation which is embedded in multiple screens). With this setup it is also difficult to provide a proper preview with a background for the hazeChild component. Currently we are passing the HazeState as a parameter to this component, provide a dummy state in the Preview and switch to a solid background if we are in inspection mode.

[0.6.0] Crash in Espresso UI Tests - Recording currently in progress - missing #endRecording() call?

Information

Tests are working fine in 0.5.4 so seems to be a regression in 0.6.0

  • Haze version: 0.6.0
  • Platform: Android/Compose v1.6

Expected Behavior

Espresso UI Test doesn't crash when ran, app runs ok it's only tests which are regressed. (Removing the haze view from the test allows it to pass.)

Actual Behavior

java.lang.IllegalStateException: Recording currently in progress - missing #endRecording() call?
at android.graphics.RenderNode.beginRecording(RenderNode.java:446)
at android.graphics.RenderNode.beginRecording(RenderNode.java:465)
at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:204)
at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:335)
at androidx.compose.ui.platform.RenderNodeLayer.drawLayer(RenderNodeLayer.android.kt:277)
at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:348)
at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:926)
at androidx.compose.ui.node.InnerNodeCoordinator.performDraw(InnerNodeCoordinator.kt:174)
at androidx.compose.ui.node.NodeCoordinator.drawContainedDrawModifiers(NodeCoordinator.kt:361)
at androidx.compose.ui.node.NodeCoordinator.draw(NodeCoordinator.kt:353)
at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:926)
at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:1231)
at android.view.View.draw(View.java:23892)
at android.view.View.updateDisplayListIfDirty(View.java:22756)
at android.view.View.draw(View.java:23620)
at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
at android.view.View.updateDisplayListIfDirty(View.java:22747)
at android.view.View.draw(View.java:23620)
at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
at android.view.View.updateDisplayListIfDirty(View.java:22747)
at android.view.View.draw(View.java:23620)
at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
at android.view.View.updateDisplayListIfDirty(View.java:22747)
at android.view.View.draw(View.java:23620)
at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
at android.view.View.updateDisplayListIfDirty(View.java:22747)
at android.view.View.draw(View.java:23620)
at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
at android.view.View.updateDisplayListIfDirty(View.java:22747)
at android.view.View.draw(View.java:23620)
at android.view.ViewGroup.drawChild(ViewGroup.java:4556)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4317)
at android.view.View.draw(View.java:23892)
at com.android.internal.policy.DecorView.draw(DecorView.java:809)
at android.view.View.updateDisplayListIfDirty(View.java:22756)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:694)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:700)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:798)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:4939)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4643)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3822)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2465)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9305)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1339)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1348)
at android.view.Choreographer.doCallbacks(Choreographer.java:952)
at android.view.Choreographer.doFrame(Choreographer.java:882)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1322)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8177)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)

Other Github issues which maybe related to the root cause.
software-mansion/react-native-screens#1287
software-mansion/react-native-screens#1406

As these are both related to a blur implementation causing the crash even though it's react-native.

Steps to Reproduce the Problem

  1. Create a sample Espresso UI Test
  2. Include a Haze View in the screen to be tested
  3. Run Test

Strange behaviour during scaling content with HAZE blur

Information

  • Haze version: 0.5.0
  • Platform: Android

Expected Behavior

Scaling without moving bottom blur bg

Actual Behavior

wrong_logic.webm

Steps to Reproduce the Problem

  1. make simple animation for scale all content:
image

2.Haze(blur) inside to HomeScreen():

image

It's debugger result for case if
scale 1x:
image

Scale: 0.8x:
image

p.s. if need can send project for fast testing

Glitched artifacts with blurred items inside a scrollable container

Information

  • Haze version: 0.7.0
  • Platform: Native Android (min sdk 23, target 34)

Expected Behavior

A HorizontalPager/LazyRow/Scrollable Row with items that have a background blur and clip applied

Actual Behavior

They do have background blur but also some glitchy effects, it occurs more often with a background image loaded with Coil and the blurred contained has shape applied.
When the items have background blur with Rectangle shape applied the same happens only on the background with a color, at least I was not able to replicate it when the background is an image and the shape is a Rectangle

Screen_recording_20240429_145551.webm
Screen_recording_20240429_145959.webm

Steps to Reproduce the Problem

The code I used to reproduce, with and empty new project:

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PageSize
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.example.hazehorizontalpager.ui.theme.HazeHorizontalPagerTheme
import dev.chrisbanes.haze.HazeState
import dev.chrisbanes.haze.haze
import dev.chrisbanes.haze.hazeChild
import dev.chrisbanes.haze.materials.HazeMaterials

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            HazeHorizontalPagerTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->

                    Column(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(innerPadding)
                    ) {
                        ShowcaseHorizontalPager(
                            modifier = Modifier
                                .fillMaxWidth()
                                .weight(1f)
                            ,
                            imgUrl = "https://picsum.photos/200/300",
                            showImg = true,
                        )

                        ShowcaseHorizontalPager(
                            modifier = Modifier
                                .fillMaxWidth()
                                .weight(1f)
                            ,
                            imgUrl = "https://picsum.photos/200/300",
                            showImg = false,
                        )
                    }

                }
            }
        }
    }
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ShowcaseHorizontalPager(
    modifier: Modifier = Modifier,
    imgUrl: String,
    showImg: Boolean,
) {

    val dropsHazeState = remember { HazeState() }

    val pagerState = rememberPagerState { 6 }

    val maxWidth = LocalConfiguration.current.screenWidthDp.dp
    val itemWidth = maxWidth * 0.78f

    Box(
        modifier = modifier
            .fillMaxSize()
        ,
        contentAlignment = Alignment.Center,
    ) {

        if (showImg) {
            AsyncImage(
                contentScale = ContentScale.Crop,
                modifier = Modifier
                    .fillMaxSize()
                    .background(Color.White)
                    .haze(
                        dropsHazeState,
                        HazeMaterials.regular(Color(0x80808080))
                    )
                ,
                model = ImageRequest.Builder(LocalContext.current)
                    .data(imgUrl)
                    .crossfade(true)
                    .build(),
                contentDescription = null
            )
        } else {
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .background(Color.Blue)
                    .haze(
                        dropsHazeState,
                        HazeMaterials.regular(Color(0x80808080))
                    )
            ) {

            }
        }

        Column(
            modifier = Modifier
                .fillMaxWidth()
                .align(Alignment.BottomCenter),
            verticalArrangement = Arrangement.spacedBy(20.dp)
        ) {

            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .horizontalScroll(rememberScrollState()),
                horizontalArrangement = Arrangement.spacedBy(20.dp),
            ) {

                Spacer(
                    modifier = Modifier.width(20.dp)
                )

                repeat(6) {
                    key(it) {
                        BoxItem(
                            modifier = Modifier
                                .width(itemWidth),
                            hazeState = dropsHazeState,
                            index = it
                        )
                    }
                }

                Spacer(
                    modifier = Modifier.width(20.dp)
                )
            }

            LazyRow(
                modifier = Modifier
                    .fillMaxWidth()
                ,
                contentPadding = PaddingValues(20.dp),
                horizontalArrangement = Arrangement.spacedBy(20.dp, alignment = Alignment.CenterHorizontally)
            ) {
                repeat(6) {
                    item(key = "$it") {
                        BoxItem(
                            modifier = Modifier.fillParentMaxWidth(0.78f),
                            hazeState = dropsHazeState,
                            index = it
                        )
                    }
                }
            }

            HorizontalPager(
                modifier = Modifier
                    .fillMaxWidth()
                ,
                state = pagerState,
                pageSize = PageSize.Fixed(itemWidth),
                pageSpacing = 20.dp,
                contentPadding = PaddingValues(20.dp),
            ) { index ->
                BoxItem(
                    modifier = Modifier.fillMaxWidth(),
                    hazeState = dropsHazeState,
                    index = index
                )
            }
        }

    }
}

@Composable
fun BoxItem(
    modifier: Modifier,
    hazeState: HazeState,
    index: Int,
) {
    Row(
        modifier = modifier
            .height(65.dp)
            .hazeChild(hazeState, RoundedCornerShape(12.dp))
        ,
        horizontalArrangement = Arrangement.Center,
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text(
            text = "$index",
            color = Color.White,
            fontSize = 18.sp,
            fontWeight = FontWeight.Bold,
        )
    }
}

Libraries and Versions:

From a clean project just added coil and haze

[versions]
agp = "8.4.0-rc02"
kotlin = "1.9.0"
coreKtx = "1.13.0"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
lifecycleRuntimeKtx = "2.7.0"
activityCompose = "1.9.0"
hazeVersion = "0.7.0"
coilVersion = "2.6.0"
composeBom = "2024.04.01"

[libraries]
coil = { module = "io.coil-kt:coil", version.ref = "coilVersion" }
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coilVersion" }
haze = { module = "dev.chrisbanes.haze:haze", version.ref = "hazeVersion" }
haze-materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = "hazeVersion" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

Applied:

implementation(libs.coil)
implementation(libs.coil.compose)
implementation(libs.haze)
implementation(libs.haze.materials)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)

Tint color can not be updated for HazeNodeBase on Android

When we try to dynamically change the tint color, the haze modifier does not reflect this change on Android < API 32 (the ones that use HazeNodeBase).

A change of the tint color correctly calls HazeNodeElement.update() and changes all properties and then calls node.onUpdate().
This then calls invalidateDraw(), so we end up in HazeNodeBase.ContentDrawScope.draw() which will again draw the paths.

โŒ However, the draw function will only update the paths, including their tint color, if the paths were marked as dirty with pathsDirty, which never happens in this process. So we are stuck with the old color.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

github-actions
.github/workflows/build.yml
  • actions/checkout v4
  • actions/setup-java v4
  • gradle/gradle-build-action v3
  • actions/upload-artifact v4
  • actions/checkout v4
  • actions/setup-java v4
  • gradle/gradle-build-action v3
  • macos 14
.github/workflows/publish-docs.yml
  • actions/checkout v4
  • actions/setup-java v4
  • actions/setup-python v5
  • actions/configure-pages v5
  • gradle/gradle-build-action v3
  • actions/upload-pages-artifact v3
  • actions/deploy-pages v4
gradle
gradle.properties
settings.gradle.kts
  • com.gradle.develocity 3.17.4
build.gradle.kts
gradle/libs.versions.toml
  • androidx.benchmark:benchmark-macro-junit4 1.2.4
  • androidx.core:core-ktx 1.13.1
  • androidx.collection:collection 1.4.1
  • androidx.activity:activity-compose 1.9.0
  • androidx.compose.ui:ui-test-manifest 1.6.8
  • androidx.profileinstaller:profileinstaller 1.3.1
  • androidx.test.ext:junit-ktx 1.2.1
  • androidx.test.uiautomator:uiautomator 2.3.0
  • androidx.compose.ui:ui 1.7.0-beta05
  • androidx.compose.foundation:foundation 1.7.0-beta05
  • io.coil-kt.coil3:coil-compose 3.0.0-alpha08
  • io.coil-kt.coil3:coil-network-ktor 3.0.0-alpha08
  • org.jetbrains.kotlinx:kotlinx-coroutines-swing 1.8.1
  • io.ktor:ktor-client-core 3.0.0-wasm2
  • io.ktor:ktor-client-cio 3.0.0-wasm2
  • org.robolectric:robolectric 4.13
  • io.github.takahirom.roborazzi:roborazzi 1.22.2
  • io.github.takahirom.roborazzi:roborazzi-compose 1.22.2
  • io.github.takahirom.roborazzi:roborazzi-compose-desktop 1.22.2
  • io.github.takahirom.roborazzi:roborazzi-junit-rule 1.22.2
  • com.android.tools.build:gradle 8.5.1
  • org.jetbrains.kotlin:kotlin-gradle-plugin 2.0.0
  • com.diffplug.spotless:spotless-plugin-gradle 6.25.0
  • org.jetbrains.compose:compose-gradle-plugin 1.7.0-alpha01
  • me.tylerbwong.gradle.metalava:plugin 0.3.5
  • com.android.application 8.5.1
  • com.android.library 8.5.1
  • com.android.lint 8.5.1
  • com.android.test 8.5.1
  • androidx.baselineprofile 1.2.4
  • org.gradle.android.cache-fix 3.0.1
  • org.jetbrains.kotlin.plugin.compose 2.0.0
  • org.jetbrains.compose 1.7.0-alpha01
  • org.jetbrains.dokka 1.9.20
  • org.jetbrains.kotlin.android 2.0.0
  • me.tylerbwong.gradle.metalava 0.3.5
  • dev.drewhamilton.poko 0.16.0
  • io.github.takahirom.roborazzi 1.22.2
  • com.diffplug.spotless 6.25.0
  • com.vanniktech.maven.publish 0.29.0
gradle/build-logic/gradle.properties
gradle/build-logic/settings.gradle.kts
gradle/build-logic/convention/build.gradle.kts
haze/gradle.properties
haze/build.gradle.kts
haze-materials/gradle.properties
haze-materials/build.gradle.kts
internal/benchmark/build.gradle.kts
internal/screenshot-test/build.gradle.kts
sample/android/build.gradle.kts
sample/desktop/build.gradle.kts
sample/shared/build.gradle.kts
sample/web/build.gradle.kts
gradle-wrapper
gradle/wrapper/gradle-wrapper.properties
  • gradle 8.9

  • Check this box to trigger a request for Renovate to run again on this repository

Merge :haze and :haze-jetpack-compose libraries

Currently we need to maintain 2 separate libraries due to Compose Multiplatform still targeting JC 1.5.x. To implement blurring on Android, we need access to a new drawing API added in Jetpack Compose Foundation 1.6.0 (currently in beta).

This is a tracking bug to perform that merge, once Compose Multiplatform is updated and we have access to that API (tracking issue: JetBrains/compose-multiplatform#4052).

multiple haze effects

I want to blur a screen with multiple Rects with different haze background colors.
I found it impossible to put multiple haze modifiers in one composable, but it works with wrapper layouts with only one haze modifier of each.

Is there convenient API that provides multiple complex haze effects in one modifier? For example:

haze(
  Haze(rect1, bg1, tint1),
  Haze(rect2, bg2, tint2),
)

Additionally, both Rect and RoundRect can be combined.

edge blending options and/or blur the edges

Information

  • Haze version: 0.5.3
  • Platform: Android

Hi Chris,
first, thanks to this amazing library that does an incredible job, and also thanks to all the other contributors for making the impossible - possible in Android Blur issues.
This is not a classic issue or issue at all it is more like a feature request, if I missed the doc about it (I hope not), I couldn't blend/level the corners, so when using shapes (unique or regular) the edges are very noticeable.
it would be great if the library could offer such a mechanic to make the edges less noticeable.
it will help a lot if it will be possible

thanks again for the amazing work :)

Crash at zero size composable with hazeChild(shape)

Information

  • Haze version: 0.6.0 (not reproducable on 0.5.4)
  • Platform: Android

Expected Behavior

hazeChild(shape = RoundedCornerShape(...) could be applied to component with zero size.

Actual Behavior

Crash


java.lang.IllegalArgumentException: Android does not support arbitrary transforms
	at androidx.compose.ui.graphics.AndroidMatrixConversions_androidKt.setFrom-EL8BTi8(AndroidMatrixConversions.android.kt:57)
	at androidx.compose.ui.graphics.AndroidPath.transform-58bKbWc(AndroidPath.android.kt:205)
	at dev.chrisbanes.haze.RenderNodeImpl.updatePaths(AndroidHazeNode.kt:455)
	at dev.chrisbanes.haze.RenderNodeImpl.getUpdatedContentClipPath(AndroidHazeNode.kt:443)
	at dev.chrisbanes.haze.RenderNodeImpl.access$getUpdatedContentClipPath(AndroidHazeNode.kt:253)
	at dev.chrisbanes.haze.RenderNodeImpl$draw$2$1$1.invoke(AndroidHazeNode.kt:290)
	at dev.chrisbanes.haze.RenderNodeImpl$draw$2$1$1.invoke(AndroidHazeNode.kt:289)
	at dev.chrisbanes.haze.AndroidHazeNodeKt.clipShape-SI_Vg3w(AndroidHazeNode.kt:534)
	at dev.chrisbanes.haze.AndroidHazeNodeKt.access$clipShape-SI_Vg3w(AndroidHazeNode.kt:1)
	at dev.chrisbanes.haze.RenderNodeImpl.draw(AndroidHazeNode.kt:289)
	at dev.chrisbanes.haze.AndroidHazeNode.draw(AndroidHazeNode.kt:135)
	at androidx.compose.ui.node.LayoutNodeDrawScope.drawDirect-x_KDEd0$ui_release(LayoutNodeDrawScope.kt:105)

Steps to Reproduce the Problem

Box(Modifier.hazeChild(state = hazeState, shape = RoundedCornerShape(16.dp)))

Dialog blur offset

Information

  • Haze version: 0.7.0
  • Platform: Native Android (min sdk 30, target 34)

Expected Behavior

Dialog is uniformly blurred

Screenshot_2024-04-29-13-36-48-091_ai datawise finstreet

This screenshot was generated by enabling the fullscreen mode
(activity.window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN)

Actual Behavior

Dialog's blur is offset by the top (or bottom) bar when not in fullscreen

Screenshot_2024-04-29-13-38-47-935_ai datawise finstreet

Steps to Reproduce the Problem

  1. Create a new native android project
  2. Copy-paste the sample code for the dialog preview
  3. Launch the app on the device

Unfortunately, I can't compile the source code to do any debugging (yet).

Wrong calculations using the new HazeState

Hi,
The new APIs are great and more friendly, but there's an issue when part of the parent gets invisible (When the parent is inside a LazyColumn for example), the boundsInRoot() that is being used to make the position calculations is not the best option for this case because it's ignoring the invisible area of the composable, I'll change it with positionInRoot() which fixes the issue.

Screen.Recording.2023-12-09.at.10.24.23.AM.mov

Can i use haze with Jetpack compose Popup?

Information

  • Haze version: 0.6.2
  • Platform: Android

Expected Behavior

image

Actual Behavior

Steps to Reproduce the Problem

Popup(
            properties = PopupProperties(
                dismissOnBackPress = true,
                dismissOnClickOutside = true,
                focusable = true,
                excludeFromSystemGesture = false
            ),
            popupPositionProvider = remember(traderLegendInformation.boundsInRoot) {
                LegendPopupOffsetPositionProvider(
                    traderLegendInformation.boundsInRoot,
                    triangleHeightInPx = triangleHeightInPx
                )
            },
            onDismissRequest = remember { { shouldShowTooltip = null } }
        ) {
            TooltipShowMoreLarge(
                text = traderLegendInformation.legend.title
            )
        }

Blur doesn't follow Dialog on Android 33

Not sure if this is due to Dialog window, but when displaying a compose Dialog containing a Surface, the haze doesn't follow the dialog, but remains frozen in the top left corner of the screen. .hazeChild() is set on the Surface.

Modifier.clip() has no effect on hazeChild

Given

In the sample, clip a half height of the card:

    val clippingShape = remember {
      GenericShape { size, _ ->
        lineTo(0f, size.height / 2)
        lineTo(size.width, size.height / 2)
        lineTo(size.width, 0f)
      }
    }
    val bgColor = remember { Color.Red.copy(alpha = 0.25f) }

    // Our card
    Box(
      modifier = Modifier
        .fillMaxWidth(0.7f)
        .aspectRatio(16 / 9f)
        .align(Alignment.Center)
        .offset { IntOffset(x = 0, y = cardOffset.value.toInt()) }
        .draggable(
          state = draggableState,
          orientation = Orientation.Vertical,
          onDragStopped = { velocity ->
            animate(
              initialValue = cardOffset.value,
              targetValue = 0f,
              initialVelocity = velocity,
              animationSpec = spring(Spring.DampingRatioLowBouncy, Spring.StiffnessLow),
            ) { value, _ ->
              cardOffset.value = value
            }
          },
        )
        .clip(clippingShape)
        .background(color = bgColor, shape = RoundedCornerShape(16.dp))
        .hazeChild(state = hazeState, shape = RoundedCornerShape(16.dp)),
    ) {
      Column(Modifier.padding(32.dp)) {
        Text("Bank of Haze")
      }
    }

Actual Result

image

Expected

clip affects hazeChild in the same way it affects background

Toggling blur doesn't work

Hello @chrisbanes, thank you for the very useful library.

I'm attempting to implement the logic for enabling and disabling the blur effect, but it doesn't seem to be functioning as expected.
Here's the simple code I'm using:

@Preview
@Composable
fun HazeDemo() {
    val context = LocalContext.current
    var enableBlur by remember { mutableStateOf(true) }
    val hazeState = remember { HazeState() }
    val hazeStyle = HazeDefaults.style(
        blurRadius = 15.dp,
        tint = Color.Black.copy(alpha = 0.5f)
    )

    LaunchedEffect(context) {
        (context as? ComponentActivity)?.enableEdgeToEdge()
    }

    Box(contentAlignment = Alignment.Center) {
        Image(
            painter = painterResource(R.drawable.donation_backdrop_1),
            contentDescription = null,
            contentScale = ContentScale.Crop,
            modifier = Modifier
                .fillMaxSize()
                .haze(hazeState)
        )

        Button(
            modifier = Modifier
                .align(Alignment.TopCenter)
                .padding(16.dp)
                .windowInsetsPadding(WindowInsets.safeContent),
            onClick = {
                enableBlur = !enableBlur
            }
        ) {
            Text(text = "Toggle blur")
        }

        Box(
            modifier = Modifier
                .size(200.dp)
                .then(
                    if (enableBlur) {
                        Modifier.hazeChild(state = hazeState, style = hazeStyle)
                    } else {
                        Modifier.background(Color.Red)
                    }
                )
        )
    }
}

Information

  • Haze version: 0.6.2
  • Platform: Android

Expected Behavior

After tapping the Toggle blur button, the blur should be disabled, and when tapped one more time, the blur should be enabled.

Actual Behavior

After tapping the Toggle blur button, the blur effect gets disabled, but when tapped again, nothing happens.

Steps to Reproduce the Problem

  1. Tap the Toggle blur button.
  2. The blur should now be disabled.
  3. Tap the Toggle blur button one more time.
  4. Nothing happens and the blur doesn't get enabled again.

[Skiko] Issue with multiple areas

I modified your sample like the following and only the last area is blurred. Both areas work good separately.
Am i doing something wrong?

P.S. Thanks for this amazing modifier!

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HazeSample(appTitle: String) {
  MaterialTheme {
    Scaffold(
      topBar = {
        LargeTopAppBar(
          title = { Text(text = appTitle) },
          colors = TopAppBarDefaults.largeTopAppBarColors(Color.Transparent),
          modifier = Modifier.fillMaxWidth(),
        )
      },
+      bottomBar = {
+          Box(Modifier.height(100.dp))
+      },
      modifier = Modifier.fillMaxSize(),
    ) { contentPadding ->
      BoxWithConstraints {
        val topBarBounds = with(LocalDensity.current) {
          Rect(
            Offset(0f, 0f),
            Offset(maxWidth.toPx(), contentPadding.calculateTopPadding().toPx()),
          )
        }
+        val bottomBarsBound = with(LocalDensity.current) {
+          Rect(
+            Offset(0f, maxHeight.toPx() - contentPadding.calculateBottomPadding().toPx()),
+            Offset(maxWidth.toPx(), maxHeight.toPx()),
+          )
+        }

        LazyVerticalGrid(
          columns = GridCells.Adaptive(128.dp),
          verticalArrangement = Arrangement.spacedBy(8.dp),
          horizontalArrangement = Arrangement.spacedBy(8.dp),
          contentPadding = contentPadding,
          modifier = Modifier
            .fillMaxSize()
            .haze(
              topBarBounds,
+              bottomBarsBound,
              backgroundColor = MaterialTheme.colorScheme.surface,
            ),
        ) {
          items(50) { index ->
            ImageItem(
              text = "${index + 1}",
              modifier = Modifier
                .fillMaxWidth()
                .aspectRatio(3 / 4f),
            )
          }
        }
      }
    }
  }
}

Importing haze library crashes on runtime when m3 CircularProgressIndicator starts spinning

Information

  • Haze version: 0.5.0
  • Platform: Android, Jetpack Compose
  • compose-bom = "2023.10.01"
  • material = "1.10.0" (also tested on 1.11.0)

Actual Behavior

When adding the haze dependency (without using it anywhere) and running my app with a CircularProgressIndicator being shown it crashes. After removing the dependency it doesn't crash. Tested it multiple times and same result.

Steps to Reproduce the Problem

java.lang.NoSuchMethodError: No virtual method at(Ljava/lang/Object;I)
Landroidx/compose/animation/core/KeyframesSpec$KeyframeEntity; in class
Landroidx/compose/animation/core/KeyframesSpec$KeyframesSpecConfig; or its super classes (declaration of 'androidx.compose.animation.core.KeyframesSpec$KeyframesSpecConfig' appears in /data/app/~~i_o5gVWscTtLwqcpHsHQ4Q==/
at androidx.compose.material3.ProgressIndicatorKt$CircularProgressIndicator$endAngle$1.invoke(ProgressIndicator.kt:371)
at androidx.compose.material3.ProgressIndicatorKt$CircularProgressIndicator$endAngle$1.invoke(ProgressIndicator.kt:369)

Use a bundled font in screenshot tests

Currently the tests will use the system default font, meaning that the results will be different on each platform. We should bundle a font in the tests and use that for consistency.

Support RoundedRect areas

Hi Chris,
Thanks for this amazing Modifier, it's really helpful.

I have similar use case but I need to add a border radius to the area, I'm working on implementing this feature and I will create a PR when it's ready.

I'm going to create a new public composable that accepts a List<RoundRect>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.