-
Notifications
You must be signed in to change notification settings - Fork 5
Drawable
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.
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.
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.
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.
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.
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.
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.