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.
The clip tools use the same classes and methods that the native framework uses to render shadows, simply replacing the originals with clipped copies.
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.
Though the differences are noticeable when compared side by side, the compat results are likely sufficient for many cases.
-
The
viewpackage contains several extension properties and helper classes to apply the library's clip fix and color compat functionalities in Android's native framework. -
For the analogous features in the modern UI toolkit, the
composepackage comprises just two functions (and one overload) as direct replacements for the inbuilt shadow. -
Important information and caveats for each framework and the project overall.
-
Compiled artifacts are available through JitPack.
-
Note that inherited members are suppressed to prevent, for example, all of
ViewGroups visible members being listed for eachShadowsViewGroup. -
Please report bugs and any other problems encountered while using the library.
Subsections
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.BLUEThat'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: Booleanextension is simply a switch that toggles the clip fix on the receiverView. Whentrue, the intrinsic shadow is disabled and replaced with a clipped copy. -
The
View.outlineShadowColorCompat: Intproperty takes a@ColorIntwith 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.
-
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.The
ShadowPlaneenum 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. -
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 outlinePathfor the clip.This is done with the
ViewPathProviderinterface, details and examples for which are discussed on its wiki page.
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.
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.
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.
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.
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.
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.
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.





