Skip to content

Drawable

zed-alpha edited this page Feb 27, 2026 · 15 revisions

Package: com.zedalpha.shadowgadgets.view.drawable


ShadowDrawable is a thin wrapper around the core classes and functions that allows the user to draw the library's shadows manually without having to mess with the core module directly. Like all of the library's tools, a hardware-accelerated Canvas is required for this to be able to draw.

The class's constructor includes a parameter to choose between clipped or unclipped versions, for the same reason that an unclipped View option is available: to allow shadows that require only color compat to skip the expensive clip operation.


Bounds

ShadowDrawable's bounds function as they normally do, but the shadow is not clipped to them by default. The clipToBounds: Boolean property is available to change that behavior as needed. Any time colorCompat is enabled, however, the drawable employs a compositing layer sized to the bounds, and the shadow is necessarily clipped to that layer since composition happens in an offscreen buffer.


Invalidation

The user is responsible for invalidating the drawable anytime a relevant property changes. That is, if its rotation is changed, for example, the current draw needs to be invalidated. If the drawable's callback is set appropriately - e.g., like it would be when acting as a View's background – then a call to invalidateSelf() is likely all that is necessary. Otherwise, the current View will need to be invalidated, or whatever is the analogous action for the given context.

Depending on the current internal configuration, the drawable could simply not redraw at all until it's next invalidated, or it could possibly end up with a worse artifact than the clip is meant to fix, if the draw goes out of sync while that's in use.


Clip path provider

Like with Views, on API levels 30 and above, if a clipped shadow is not shaped as a circle, plain rectangle, or a regular rounded rectangle, the shape Path must be provided manually. That's done here through the drawable's setClipPathProvider() function, which is analogous to setting a ViewPathProvider on a target View.


Color compat

Like the other tools, the drawable supports the color compat feature, which is realized here with a simple var colorCompat: Int property. Its default value is black – specifically, #FF000000 – and if any other value is set, the color compat mechanism takes over to tint the shadow manually, ignoring the ambientColor and spotColor values.

For colorCompat to work here, it is necessary to use the constructor that takes a View, and it must be one that is attached to the on-screen hierarchy; usually, just the one in which the drawable is used. If one is not provided, no tint will be applied, and the shadow will draw in the default black.

Drawable's required setColorFilter() override is a no-op.


Disposal

It is rather important to dispose() of these drawables when appropriate – e.g., in a Fragment's onDestroyView(). This is technically not necessary if the drawable was created with the @RequiresApi(29) constructor that doesn't take a View, but it is still safe to call dispose() on those instances. Use after disposal is not an automatic Exception but it's not advised, and there is no guaranteed behavior.


Examples

The demo app has a Drawable page that demonstrates the defect possible if the drawable is not invalidated properly after being modified.

The second color compat page shows that mechanism in a custom ShadowDrawable that automatically centers its content, along with some controls to fiddle with the color and rotation and such.