Material Shadows for android : A library for supporting convex material shadows
A library for seamlessly integrating Material shadows. The library takes existing material shadows to next level by adding the following features :
shadowAlpha
attribute.Just add the following dependency in your app's build.gradle
dependencies {
implementation 'com.sdsmdg.harjot:materialshadows:1.2.5'
}
React Native
You may now use this library with react-native
via the module here, built by Pranav Raj Singh Chauhan.
The MaterialShadowViewWrapper
is an extension of Relative Layout
. The MaterialShadowFrameLayoutWrapper
is an extension of FrameLayout
. Use any one of them as per your convenience.
All the child views go through the same process of generating shadow as given below :
CustomViewOutlineProvider
object that is later attached to the view itself.P.S. : All the calculations related to graham scan are done asynchronously by default. This behavior can be controlled by calculateAsync
parameter. (Thanks Yaroslav!)
<com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:elevation="5dp"
android:src="@drawable/poly" />
</com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper>
<com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper
android:layout_width="match_parent"
android:layout_height="match_parent"
app:shadowOffsetX="-15"
app:shadowOffsetY="30">
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:elevation="10dp"
android:src="@drawable/poly" />
</com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper>
<com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper
android:layout_width="match_parent"
android:layout_height="match_parent"
app:shadowOffsetX="15"
app:shadowOffsetY="30"
app:shadowAlpha="0.9">
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:elevation="10dp"
android:src="@drawable/poly" />
</com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper>
<com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper
android:layout_width="match_parent"
android:layout_height="match_parent"
app:shadowOffsetX="-30"
app:shadowOffsetY="30">
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:elevation="10dp"
android:background="#55000000" />
</com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper>
Since the ShadowGenerator.java
encapsulates all the code related to the generation of convex shadows, it is really easy to plug in convex shadows with any custom ViewGroup or some platform ViewGroup like LinearLayout
etc.
public class CustomShadowWrapper extends CustomViewGroup {
ShadowGenerator shadowGenerator;
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (shadowGenerator == null) {
shadowGenerator = new ShadowGenerator(this, offsetX, offsetY, shadowAlpha, shouldShowWhenAllReady, shouldCalculateAsync, shouldAnimateShadow, animationDuration);
}
shadowGenerator.generate();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (shadowGenerator != null) {
shadowGenerator.releaseResources();
}
}
}
Note : Make sure to define all the 7 parameters required for ShadowGenerator
, namely offsetX
, offsetY
, shadowAlpha
, shouldShowWhenAllReady
, shouldCalculateAsync
, shouldAnimateShadow
, animationDuration
in the custom wrapper and handle changes in their values.
In case any parameter value changes, say OffsetX
, add the following code inside the setter method for OffsetX
:
public void setOffsetX(float offsetX) {
this.offsetX = offsetX;
if (shadowGenerator != null) {
shadowGenerator.setOffsetX(offsetX);
}
}
If you want to add custom XML attributes with your CustomShadowWrapper
class, add this to attrs.xml
(here) and handle them in your CustomShadowWrapper
class accordingly.
<declare-styleable name="CustomShadowWrapper">
<attr name="shadowOffsetX" />
<attr name="shadowOffsetY" />
<attr name="shadowAlpha" />
<attr name="calculateAsync" />
<attr name="showWhenAllReady" />
<attr name="animateShadow" />
<attr name="animationDuration" />
</declare-styleable>
See MaterialShadowViewWrapper for more details.
XML attribute | Java set methods | Description | Default Value |
---|---|---|---|
shadowOffsetX | setOffsetX(...) | Set the X-offset of the shadow | 0.0f |
shadowOffsetY | setOffsetX(...) | Set the Y-offset of the shadow | 0.0f |
shadowAlpha | setShadowAlpha(...) | Set the value of shadow intensity (alpha) | 1.0f |
calculateAsync | setShouldCalculateAsync(...) | Set the flag for async shadow calculations. | true |
showWhenAllReady | setShowShadowsWhenAllReady(...) | Set the flag for showing all shadows after all calculations are over | true |
animateShadow | setShouldAnimateShadow(...) | Set the flag for shadow animation | true |
animationDuration | setAnimationDuration(...) | Set the value of shadow animation duration. | 300ms |
MaterialShadowViewWrapper
. Hence if the desired views are placed inside a Linear Layout or some other view group, then each view must be wrapped by a seperate MaterialShadowViewWrapper
or MaterialShadowFrameLayoutWrapper
or a custom view group wrapper may be implemented.MaterialShadowViewWrapper
or custom view group wrapper is assigned the same offset and shadow intensity. If fine control over every view's shadow is required then it must be wrapped inside its own MaterialShadowViewWrapper
or MaterialShadowFrameLayoutWrapper
.MaterialShadows is licensed under MIT license
. View license.