Material Shadows for android : A library for supporting convex material shadows

Overview

MaterialShadows

Platform API License: MIT

A library for seamlessly integrating Material shadows. The library takes existing material shadows to next level by adding the following features :

  • Convex shadows : The shadows are not only rectangular or circular, they can take any convex shape depending on the view and its content.
  • Support for shadow offsets : The library allows developers to set X and Y offset for the shadows.
  • Support for shadow intensity : The library also has support for setting shadow intensity via shadowAlpha attribute.
  • Shadows for semi-transparent views : The library allows shadows for semi-transparent views.
  • Support for Async Shadow calculations : The library allows the operations to be async to avoid blocking the UI thread for long calculations.
  • Shadow animations : The library supports fade out animation for shadow.

Usage

Just add the following dependency in your app's build.gradle

dependencies {
      implementation 'com.sdsmdg.harjot:materialshadows:1.2.5'
}

Third Party Bindings

React Native
You may now use this library with react-native via the module here, built by Pranav Raj Singh Chauhan.

How does this work ?

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 :

  1. First a bitmap is generated from the drawing cache of the view.
  2. The bitmap is traversed pixel by pixel to remove all transparent pixels and get a list of points corresponding to the actual outline of the content of the view.
  3. Since the points corresponding to outline may give a concave path, hence GrahamScan algorithm is used to generate a convex hull of the outline points.
  4. A path is created from the points of the resulting convex hull.
  5. This path is passed to a CustomViewOutlineProvider object that is later attached to the view itself.
  6. Hence we get a convex shadow for any type of view based on its content.

P.S. : All the calculations related to graham scan are done asynchronously by default. This behavior can be controlled by calculateAsync parameter. (Thanks Yaroslav!)

Example Usage 1 (Simple)

XML

<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>

Result

Example Usage 2 (Offset)

XML

<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>

Result

Example Usage 3 (Shadow intensity)

XML

<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>

Result

Example Usage 4 (Semi-transparent views)

XML

<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>

Result

Using MaterialShadows with custom ViewGroups

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.

Documentation

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

Limitations

  1. Since the bitmap is traversed pixel by pixel, the performance for large views is bad. Hence the use of the library is limited to small views.
  2. Currently the shadow is generated only for direct children of the 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.
  3. Each child of 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.

Credits

  1. Yaroslav : Implementation of asynchronous calculations and shadow animations.
  2. Pranav Raj Singh Chauhan : Building react-native bridge plugin for the library.

License

MaterialShadows is licensed under MIT license. View license.

Comments
  • crash

    crash

    java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@299a81b rejected from java.util.concurrent.ThreadPoolExecutor@c86fdb8[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1] at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2085) at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:848) at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1394) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118) at com.sdsmdg.harjot.materialshadows.shadowutils.ShadowGenerator.calculateAndRenderShadowAsync(ShadowGenerator.java:208) at com.sdsmdg.harjot.materialshadows.shadowutils.ShadowGenerator.generate(ShadowGenerator.java:140) at com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper.onLayout(MaterialShadowViewWrapper.java:91) at android.view.View.layout(View.java:20672) at android.view.ViewGroup.layout(ViewGroup.java:6194) at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1915)

    opened by linyaDev 4
  • Extend FrameLayout

    Extend FrameLayout

    RelativeLayout always performs view measurement twice. Since this widget is intended for small views FrameLayout is more efficient and covers most simple use cases e.g. an image with an overlay in one corner.

    opened by consp1racy 4
  • Async calculations

    Async calculations

    Aside from minor changes like moving from Stack to ArrayDeque or removing unnecessary Manifest tag, I added an option to calculate shadows asynchronously. I think most often developers can't afford to freeze the main thread.

    opened by yarolegovich 4
  • any similar iOS compatible library?

    any similar iOS compatible library?

    Hi @harjot-oberai

    First of all I would like to appreciate for open sourcing such a nice library.

    Do you any similar library for iOS platform as well?

    Thanks Pranav

    opened by prscX 2
  • implementation problem

    implementation problem

    my gradel:

    buildscript {
        repositories {
            maven { url 'https://maven.fabric.io/public' }
        }
    
        dependencies {
            classpath 'io.fabric.tools:gradle:1.+'
        }
    }
    apply plugin: 'com.android.application'
    apply plugin: 'io.fabric'
    
    repositories {
        maven { url 'https://maven.fabric.io/public' }
    }
    
    
    android {
        compileSdkVersion 27
        defaultConfig {
            applicationId "com.AllegorIT.fiura2018"
            minSdkVersion 15
            targetSdkVersion 27
            versionCode 1
            versionName "1.0"
            multiDexEnabled true
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'com.android.support:appcompat-v7:27.0.2'
        implementation 'com.android.support.constraint:constraint-layout:1.1.2'
        implementation 'com.android.support:design:27.0.2'
        implementation 'com.google.android.gms:play-services-maps:15.0.1'
        implementation 'com.squareup.picasso:picasso:2.71828'
        implementation 'de.hdodenhof:circleimageview:2.2.0'
    
        implementation 'com.facebook.android:facebook-login:4.33.0'
    
        //cilinder slide
        implementation 'me.relex:circleindicator:1.2.2@aar'
    
        //youtube
    
        implementation('com.google.apis:google-api-services-youtube:v3-rev198-1.23.0')
        implementation 'com.google.http-client:google-http-client-android:1.23.0'
        implementation 'com.google.api-client:google-api-client-android:1.23.0'
        implementation 'com.google.api-client:google-api-client-gson:1.20.0'
        implementation 'com.android.support:multidex:1.0.3'
        implementation('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') {
            transitive = true
        }
        //2version
        implementation project(':NavTab')
        implementation 'com.sdsmdg.harjot:longshadows:1.0.1'
    }
    

    and I got Unable to resolve dependency

    Dunno where its the problem

    opened by oscarshaitan 1
  • Added Support for React Native Projects

    Added Support for React Native Projects

    Hi @harjot-oberai

    First of all I would like to appreciate for creating such a nice, cool library

    I have created a React Native bridge plugin for using this library with React Native projects

    I have added the same in README. Can you please merge this request so that if someone is looking to use this library for React Native projects can easily do the same

    Please let me know in case any changes are required

    react-native-material-shadows

    Thanks Pranav

    opened by prscX 1
  • minSdkVersion must be 21+?

    minSdkVersion must be 21+?

    I use minSdkVersion is 19, The system is then prompted to add the following statement to the registry: tools:overrideLibrary="com.sdsmdg.harjot.materialshadows". But the system hints are still there.

    opened by FynnJason 1
  • No shdows on implimentation and App crashes when Re-Render All

    No shdows on implimentation and App crashes when Re-Render All

    I am using android studio 4.1.1

    Steps to recreate the crash:

    1. Create empty activity
    2. added implementation 'com.sdsmdg.harjot:materialshadows:1.2.5'
    3. copied "activity_main.xml" and "MainActivity.java" from sample app App doesn't show any shadow when i run the application
    4. uncheck the check box and select "Re-Render All" App crashes here
    E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.neuroflares.flares, PID: 19607
        java.lang.AssertionError
            at com.sdsmdg.harjot.materialshadows.utilities.GrahamScan.<init>(GrahamScan.java:45)
            at com.sdsmdg.harjot.materialshadows.shadowutils.ShadowGenerator.calculateAndRenderShadow(ShadowGenerator.java:258)
            at com.sdsmdg.harjot.materialshadows.shadowutils.ShadowGenerator.generate(ShadowGenerator.java:142)
            at com.sdsmdg.harjot.materialshadows.MaterialShadowViewWrapper.onLayout(MaterialShadowViewWrapper.java:91)
            at android.view.View.layout(View.java:24475)
            at android.view.ViewGroup.layout(ViewGroup.java:7383)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
            at android.view.View.layout(View.java:24475)
            at android.view.ViewGroup.layout(ViewGroup.java:7383)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
            at android.view.View.layout(View.java:24475)
            at android.view.ViewGroup.layout(ViewGroup.java:7383)
            at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:536)
            at android.view.View.layout(View.java:24475)
            at android.view.ViewGroup.layout(ViewGroup.java:7383)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
            at android.view.View.layout(View.java:24475)
            at android.view.ViewGroup.layout(ViewGroup.java:7383)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
            at android.view.View.layout(View.java:24475)
            at android.view.ViewGroup.layout(ViewGroup.java:7383)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
            at com.android.internal.policy.DecorView.onLayout(DecorView.java:1225)
            at android.view.View.layout(View.java:24475)
            at android.view.ViewGroup.layout(ViewGroup.java:7383)
            at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:4212)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3647)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2575)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9910)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1010)
            at android.view.Choreographer.doCallbacks(Choreographer.java:809)
            at android.view.Choreographer.doFrame(Choreographer.java:744)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:995)
            at android.os.Handler.handleCallback(Handler.java:938)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:246)
            at android.app.ActivityThread.main(ActivityThread.java:8506)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
    
    
    opened by Surakshaajith 0
  • Crashing while adding in the adapter view

    Crashing while adding in the adapter view

    #17 occures, when added in an adapter for recyclerview

    Java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@e12688a rejected from java.util.concurrent.ThreadPoolExecutor@e6cbefb[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 1]

    opened by technyx-ali-rehman 1
  • Prevent RejectedExecutionException in async mode

    Prevent RejectedExecutionException in async mode

    Thanks for this excellent library! I've noticed on some devices that use of the back button results in a RejectedExceutionException. It appears that the onDetachedFromWindow method is invoked which releases resources for the underlying shadowGenerator. The shadowGenerator shuts down its thread pool. If this wrapper is reused afterwards in async mode, a crash occurs when tasks are submitted to this thread pool. A simple fix seems to be simply nulling out this underlying shadowGenerator so that a new one will be constructed if needed.

    opened by shwilliamson 0
Owner
Harjot Singh Oberai
Harjot Singh Oberai
📱Android Library to implement animated, 😍beautiful, 🎨stylish Material Dialog in android apps easily.

Material Dialogs for Android ?? ?? Android Library to implement animated, ?? beautiful, ?? stylish Material Dialog in android apps easily. 1. Material

Shreyas Patil 875 Dec 28, 2022
A library to bring fully animated Material Design components to pre-Lolipop Android.

Material MaterialLibrary is an Open Source Android library that back-port Material Design components to pre-Lolipop Android. MaterialLibrary's origina

Rey Pham 6k Dec 21, 2022
The flexible, easy to use, all in one drawer library for your Android project. Now brand new with material 2 design.

MaterialDrawer ... the flexible, easy to use, all in one drawer library for your Android project. What's included ?? • Setup ??️ • Migration Guide ??

Mike Penz 11.6k Dec 27, 2022
[] Android Library that implements Snackbars from Google's Material Design documentation.

DEPRECATED This lib is deprecated in favor of Google's Design Support Library which includes a Snackbar and is no longer being developed. Thanks for a

null 1.5k Dec 16, 2022
Default colors and dimens per Material Design guidelines and Android Design guidelines inside one library.

Material Design Dimens Default colors and dimens per Material Design guidelines and Android Design guidelines inside one library. Dimens Pattern: R.di

Dmitry Malkovich 1.4k Jan 3, 2023
A library support form with material design, construct same with Android UI Framework

SwingUI A slight Java Swing library support form with material design, construct same with Android UI Framework writen in Kotlin Supported: 1. Screen:

Cuong V. Nguyen 3 Jul 20, 2021
Library containing over 2000 material vector icons that can be easily used as Drawable or as a standalone View.

Material Icon Library A library containing over 2000 material vector icons that can be easily used as Drawable, a standalone View or inside menu resou

null 2.3k Dec 16, 2022
A Material Design ViewPager easy to use library

MaterialViewPager Material Design ViewPager easy to use library Sample And have a look on a sample Youtube Video : Youtube Link Download In your modul

Florent CHAMPIGNY 8.2k Jan 1, 2023
MaterialPickers-in-android - A simple android project that shows how to create material pickers for date and time

MaterialPickers-in-android A simple android project that shows how to create mat

Segun Francis 2 Apr 28, 2022
Floating Action Button for Android based on Material Design specification

FloatingActionButton Yet another library for drawing Material Design promoted actions. Features Support for normal 56dp and mini 40dp buttons. Customi

Zendesk 6.4k Dec 26, 2022
Implementation of Ripple effect from Material Design for Android API 9+

RippleEffect ExpandableLayout provides an easy way to create a view called header with an expandable view. Both view are external layout to allow a ma

Robin Chutaux 4.9k Dec 30, 2022
Android drawer icon with material design animation

LDrawer Android drawer icon with material design animation Note Basically same as appcompat_v7 version 21, you can use appcompat_v7 compile 'com.andro

Hasan Keklik 1.4k Dec 25, 2022
A material horizontal calendar view for Android based on RecyclerView

Horizontal Calendar A material horizontal calendar view for Android based on RecyclerView. Installation The library is hosted on jcenter, add this to

Mulham Raee 1.2k Dec 15, 2022
Android Sample Project with Material Design and Toolbar.

AndroidMaterialDesignToolbar -- PROJECT IS NOT SUPPORTED Android Sample Project with Material Design and Toolbar. Project use Appcompat library for ma

kemal selim tekinarslan 713 Nov 11, 2022
Material style circular progress bar for Android

Material CircularProgressView Indeterminate Determinate Description This CircularProgressView is a (surprisingly) circular progress bar Android View t

Rahat Ahmed 760 Nov 30, 2022
Android drawer icon with material design animation

LDrawer Android drawer icon with material design animation Note Basically same as appcompat_v7 version 21, you can use appcompat_v7 compile 'com.andro

Hasan Keklik 1.4k Dec 25, 2022
Floating Action Button for Android based on Material Design specification

FloatingActionButton Yet another library for drawing Material Design promoted actions. Features Support for normal 56dp and mini 40dp buttons. Customi

Zendesk 6.4k Jan 3, 2023
Material style morphing play-pause drawable for Android

Play There is no need to explain what this thing does, just take a look at the gif below. Including in your project Add to your root build.gradle: all

Alexey Derbyshev 58 Jul 11, 2022
Android Material Design Components

Android-Material-Design-Components Material design is a comprehensive guide for visual, motion, and interaction design across platforms and devices. G

Velmurugan Murugesan 3 Jun 10, 2022