Skip to content

zed-alpha/shadow-gadgets

Repository files navigation

Shadow Gadgets

A utility library for Android with various tools to help remedy a couple of shortcomings in the native material shadows.


Visual artifacts

Unsightly draw defects are visible on Views and Composables with see-through backgrounds.

Examples of various translucent UI elements showing the artifacts.

The clip tools use the same classes and methods that the native framework uses to render shadows, simply replacing the originals with clipped copies.

The above examples with the clip fix applied to each.

Color support

Shadow colors were not added to the SDK until API level 28 (Pie). Before that, the only relevant adjustment available was the alpha value of plain black.

Like the clip feature, color compat uses the same native classes and methods, replacing the originals with tinted copies. Only one color can be applied with this technique, however, as it's not possible to separate the ambient and spot shadows at this level.

A shadow with native colors, and another tinted with color compat.

Though the differences are noticeable when compared side by side, the compat results are likely sufficient for many cases.


Contents

  • Views

    The view package contains several extension properties and helper classes to apply the library's clip fix and color compat functionalities in Android's native framework.

  • Compose

    For the analogous features in the modern UI toolkit, the compose package comprises just two functions (and one overload) as direct replacements for the inbuilt shadow.

  • Notes

    Important information and caveats for each framework and the project overall.

  • Download

    Compiled artifacts are available through JitPack.

  • Documentation ↗

    Note that inherited members are suppressed to prevent, for example, all of ViewGroups visible members being listed for each ShadowsViewGroup.

  • Issues

    Please report bugs and any other problems encountered while using the library.


Views

Subsections

Overview

Nobody wants to mess with a whole library for such small issues that should've been handled already in the native framework and its support packages, so these tools have been designed to be as simple and familiar as possible.

view.clipOutlineShadow = true
view.outlineShadowColorCompat = Color.BLUE

That's it. Unless your setup requires that a sibling View overlap a target of the fix, or it involves a target with an irregular shape on Android R and above, that's possibly all you need.

  • The View.clipOutlineShadow: Boolean extension is simply a switch that toggles the clip fix on the receiver View. When true, the intrinsic shadow is disabled and replaced with a clipped copy.

  • The View.outlineShadowColorCompat: Int property takes a @ColorInt with which to tint replacement shadows on versions before Pie. A separate extension is available to force it on newer versions, and it can be used with or without the clip feature. The particulars can be found on its wiki page.

Though the library's shadow is actually being handled and drawn in the parent ViewGroup, these properties can be set on the target View at any point, even while it's unattached, so there's no need to worry about timing. Additionally, the shadow automatically animates and transforms along with its target, and it will handle moving itself to any new parents, should the target be moved.

It is hoped that the base features will cover most cases. For those setups that might be problematic, the library offers a couple of other configuration properties as possible remedies.

Limitations and recourses

  • Overlapping sibling Views

    To accomplish its effect, the library disables a target's intrinsic shadow and draws a modified replacement in its parent ViewGroup's overlay by default, in front of all the children. This can cause a problem when a sibling with a higher elevation overlaps the target.

    A View's clipped shadow incorrectly drawn atop a higher sibling.

    The ShadowPlane enum defines other options for different points in the hierarchy's draw routine where the library shadow can be inserted. Specifics and requirements are given on its wiki page.

  • Irregular shapes on Android R+

    Starting with API level 30, Views that are not shaped as circles, plain rectangles, or single-radius rounded rectangles require that the user provide the outline Path for the clip.

    A View in the shape of a puzzle piece with its shadow clipped.

    This is done with the ViewPathProvider interface, details and examples for which are discussed on its wiki page.

ViewGroups

Several specialized subclasses of common ViewGroups are included mainly as helpers that allow shadow properties to be set on Views from attributes in layout XML, without the need for extra code.

The library's features work rather well in Android Studio's layout preview, so even if you don't intend to use them at runtime, these groups may still be useful during design.

Android Studio's layout editor showing library effects.

Information on the two general types of groups – Regular and Recycling – along with descriptions of their behaviors and usage in layout XML can be found on the ViewGroups wiki page.

Drawable

ShadowDrawable is a thin wrapper around the core classes that allows these shadows to be drawn manually without having to mess with the core module. Information on requirements and usage, and links to examples are available on the Drawable wiki page.

Experimental New!

A new ExperimentalShadowGadgets annotation has been added along with a few helpers that are mainly concerned with logging and Exception behavior, and providing a fallback mechanism for error states. Details can be found on the Experimental wiki page.

These will likely be promoted to stable rather quickly, after just a short time to allow users an opportunity to report any issues before they're made permanent.


Compose

Important

If you need only the clip fix in this one framework, you might be able to avoid the library overhead. Recent improvements to Compose have made it possible to create a Modifier purely within the framework, and it may be preferable to simply copy the short example given in this Stack Overflow post, or the longer one in the linked gist if supporting API levels 24..28.

Since Compose already allows shadows to be handled and manipulated as discrete UI elements, employing the library's features here is straightforward and routine.

The base clippedShadow is a drop-in replacement for Compose's shadow function, with the exact same signature and defaults, and identical usage. For example:

Box(
    Modifier
        .clippedShadow(
            elevation = 10.dp,
            shape = CircleShape
        )
    …
)

Color compat is handled with additional parameters in an overload.

Box(
    Modifier
        .clippedShadow(
            elevation = 10.dp,
            shape = CircleShape,
            colorCompat = Color.Blue,
            forceColorCompat = true
        )
    …
)

For those cases where you need only color compat without the clip, shadowCompat is a more performant option.

Box(
    Modifier
        .shadowCompat(
            elevation = 10.dp,
            shape = CircleShape,
            ambientColor = Color.Blue,
            spotColor = Color.Cyan,
            colorCompat = Color.Blue
        )
    …
)

Details and examples for both functions can be found on the Compose wiki page.


Download

The library is available as a compiled dependency through the very handy service JitPack. To enable download in a modern Gradle setup, add their Maven URL to the repositories block inside the dependencyResolutionManagement in the root project's settings.gradle.kts file; e.g.:

dependencyResolutionManagement {
    …
    repositories {
        …
        maven { url = uri("https://jitpack.io") }
    }
}

Then add a dependency for the latest release of whichever module is required, view or compose:

dependencies {
    …
    implementation("com.github.zed-alpha.shadow-gadgets:view:[latest-release]")
    implementation("com.github.zed-alpha.shadow-gadgets:compose:[latest-release]")
}

There is no longer a shared :core module. Compose updates have obviated the need for it in that framework, so it's all been moved into :view.


License

MIT License

Copyright (c) 2026 zed-alpha

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

A utility library for Android's material shadows, with tools to fix their draw artifacts and to add color on older versions.

Resources

License

Stars

Watchers

Forks