{"id":15036236,"url":"https://github.com/harjot-oberai/long-shadows","last_synced_at":"2025-05-16T05:00:17.669Z","repository":{"id":38712412,"uuid":"119167625","full_name":"harjot-oberai/Long-Shadows","owner":"harjot-oberai","description":"Long Shadows for android!","archived":false,"fork":false,"pushed_at":"2018-04-18T12:27:33.000Z","size":1885,"stargazers_count":1068,"open_issues_count":2,"forks_count":104,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-05-11T15:17:58.462Z","etag":null,"topics":["android","concave-hull","library","longshadows"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/harjot-oberai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-27T13:39:35.000Z","updated_at":"2025-03-07T05:33:42.000Z","dependencies_parsed_at":"2022-09-16T11:31:12.267Z","dependency_job_id":null,"html_url":"https://github.com/harjot-oberai/Long-Shadows","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harjot-oberai%2FLong-Shadows","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harjot-oberai%2FLong-Shadows/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harjot-oberai%2FLong-Shadows/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harjot-oberai%2FLong-Shadows/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/harjot-oberai","download_url":"https://codeload.github.com/harjot-oberai/Long-Shadows/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254471028,"owners_count":22076582,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","concave-hull","library","longshadows"],"created_at":"2024-09-24T20:30:35.936Z","updated_at":"2025-05-16T05:00:17.586Z","avatar_url":"https://github.com/harjot-oberai.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\u003cimg src=\"/screens/cover.png\"/\u003e\u003c/div\u003e\n\n# \u003cdiv align=\"center\"\u003eLong-Shadows\u003c/div\u003e\n\u003cdiv align=\"center\"\u003eA library for efficiently generating and rendering beautiful long shadows in Android.\u003c/div\u003e\u003cbr\u003e\n\n\u003cdiv align=\"center\"\u003e\n\t\u003ca href=\"https://www.android.com\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/platform-Android-brightgreen.svg?style=flat-square\"\n      alt=\"Platform\" /\u003e\n  \u003c/a\u003e\n\t\u003ca href=\"https://android-arsenal.com/api?level=15\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/API-15%2B-blue.svg?style=flat-square\"\n      alt=\"API\" /\u003e\n  \u003c/a\u003e\n\t\u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/License-MIT-red.svg?style=flat-square\"\n      alt=\"License: MIT\" /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\u003cbr\u003e\n\n# Table of contents\n\n  * [Features](#features)\n  * [Usage](#usage)\n  * [Examples](#examples)\n    * [Example 1 (Basic)](#example-1-basic)\n  \t* [Example 2 (Shadow Angle)](#example-2-shadow-angle)\n  \t* [Example 3 (Shadow Length)](#example-3-shadow-length)\n  \t* [Example 4 (Shadow Blur) ](#example-4-shadow-blur)\n  \t* [Example 5 (Shadow Color)](#example-5-shadow-color)\n  \t* [Example 6 (Single View, Multiple Shadows)](#example-6-single-view-multiple-shadows)\n  \t* [Example 7 (Non-Transparent background)](#example-7-non-transparent-background)\n  * [Dynamically updating shadows](#dynamically-updating-shadows)\n  * [Custom Views and ViewGroups](#using-long-shadows-with-custom-views-and-custom-viewgroups)\n  * [How does this work ?](#how-does-this-work-)\n  * [Documentation](#documentation)\n  * [Limitations](#limitations)\n  * [Credits](#credits)\n  * [License](#license)\n\n# Features\n\n- \u003cb\u003eAny Type of views\u003c/b\u003e : Long-Shadows can render shadow for any type of view, even custom views.\n- \u003cb\u003eHeavy calculation in Native\u003c/b\u003e : Long-Shadows shifts the load of heavy calculations to native, to reduce overhead in Java. Thus the rendering is very fast and efficient.\n- \u003cb\u003ePrecise control over shadow of every View\u003c/b\u003e : The library supports fine control over shadows of a view, so two views in same ViewGroup can have different shadow parameters.\n- \u003cb\u003eMultiple Shadows for a View\u003c/b\u003e : The library support rendering multiple long shadows for a single view, simulating multiple light sources.\n- \u003cb\u003eAsync Calculations\u003c/b\u003e : The library allows the operations to be asynchronous to avoid blocking the UI thread for long calculations.\n- \u003cb\u003eShadow animations\u003c/b\u003e : The library supports fade out animation while rendering the shadow.\n\n# Usage\nJust add the following dependency in your app's `build.gradle`\n```groovy\ndependencies {\n      implementation 'com.sdsmdg.harjot:longshadows:1.0.1'\n}\n```\n\n# Examples\nHere are some examples to provide you a head start with using this library. The examples are selected to demonstrate almost all the basic features provided by the library. So lets start !\n\n## Example 1 (Basic)\n\n\u003cb\u003eLongShadowsImageView\u003c/b\u003e\n\n\u003cimg src=\"/screens/example_1_1.png\" align=\"right\" width=\"350\"\u003e\n\n```xml\n\u003ccom.sdsmdg.harjot.longshadows.LongShadowsWrapper\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#F5362C\"\u003e\n\n    \u003ccom.sdsmdg.harjot.longshadows.LongShadowsImageView\n        android:layout_width=\"100dp\"\n        android:layout_height=\"100dp\"\n        android:layout_centerInParent=\"true\"\n        android:src=\"@drawable/ic_slack_1\" /\u003e\n\n\u003c/com.sdsmdg.harjot.longshadows.LongShadowsWrapper\u003e\n```\n\n\u003cb\u003eLongShadowsTextView\u003c/b\u003e\n\n\u003cimg src=\"/screens/example_1_2.png\" align=\"right\" width=\"350\"\u003e\n\n```xml\n\u003ccom.sdsmdg.harjot.longshadows.LongShadowsWrapper\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#40476D\"\u003e\n\n    \u003ccom.sdsmdg.harjot.longshadows.LongShadowsTextView\n        android:layout_width=\"200dp\"\n        android:layout_height=\"200dp\"\n        android:text=\"Hello\"\n        android:textColor=\"#FFFFFF\" /\u003e\n\n\u003c/com.sdsmdg.harjot.longshadows.LongShadowsWrapper\u003e\n```\n\n## Example 2 (Shadow Angle)\n\n#### XML\n```xml\n\u003ccom.sdsmdg.harjot.longshadows.LongShadowsWrapper \n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#AD5D4E\"\u003e\n\n    \u003ccom.sdsmdg.harjot.longshadows.LongShadowsImageView\n        android:layout_width=\"100dp\"\n        android:layout_height=\"100dp\"\n        android:src=\"@drawable/ic_circle\"\n        app:shadow_angle=\"90\" /\u003e\n\n\u003c/com.sdsmdg.harjot.longshadows.LongShadowsWrapper\u003e\n```\n\n#### Result\n\n\u003cimg src=\"/screens/example_2.png\"\u003e\n\n## Example 3 (Shadow Length)\n\n#### XML\n```xml\n\u003ccom.sdsmdg.harjot.longshadows.LongShadowsWrapper \n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#AEC5EB\"\u003e\n\n    \u003ccom.sdsmdg.harjot.longshadows.LongShadowsImageView\n        android:layout_width=\"100dp\"\n        android:layout_height=\"150dp\"\n        android:src=\"@drawable/ic_rocket\"\n        app:shadow_angle=\"90\"\n        app:shadow_length=\"100\" /\u003e\n\n\u003c/com.sdsmdg.harjot.longshadows.LongShadowsWrapper\u003e\n```\n\n#### Result\n\n\u003cimg src=\"/screens/example_3.png\"\u003e\n\n## Example 4 (Shadow Blur) \n\n#### XML\n```xml\n\u003ccom.sdsmdg.harjot.longshadows.LongShadowsWrapper\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#CFB1B7\"\u003e\n\n    \u003ccom.sdsmdg.harjot.longshadows.LongShadowsImageView\n        android:layout_width=\"70dp\"\n        android:layout_height=\"70dp\"\n        android:src=\"@drawable/ic_circle\"\n        app:shadow_blur_enabled=\"true\"\n        app:shadow_blur_radius=\"15\" /\u003e\n\n\u003c/com.sdsmdg.harjot.longshadows.LongShadowsWrapper\u003e\n```\n\n#### Result\n\n\u003cimg src=\"/screens/example_4.png\"\u003e\n\n## Example 5 (Shadow Color)\n\nShadows are filled by a linear gradient, so shadow color is built of two compontents `shadow_start_color`, which defines the start color of the gradient and `shadow_end_color`, which defines the end color of the gradient.\n\n\u003e **Tip** : To get a solid color shadow, just put the same value in `shadow_start_color` and `shadow_end_color` attributes.\n\n#### XML\n```xml\n\u003ccom.sdsmdg.harjot.longshadows.LongShadowsWrapper\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#90B494\"\u003e\n\n    \u003ccom.sdsmdg.harjot.longshadows.LongShadowsImageView\n        android:layout_width=\"70dp\"\n        android:layout_height=\"70dp\"\n        android:src=\"@drawable/ic_chrome\"\n        app:shadow_endColor=\"#00000000\"\n        app:shadow_startColor=\"#88000000\" /\u003e\n\n\u003c/com.sdsmdg.harjot.longshadows.LongShadowsWrapper\u003e\n```\n\n#### Result\n\n\u003cimg src=\"/screens/example_5.png\"\u003e\n\n## Example 6 (Single View, Multiple Shadows)\n\nThe library offers multiple long shadows for a single view. To use multiple shadows, just pass a comma separated string of shadow angles of you choice in the `shadow_angle` attribute.\n\n\u003e **e.g.** `app:shadow_angle=\"45, 90, 135\"`. This will create 3 shadows at angle *45*, *90* and *135* degrees.\n\n\u003e You can also specify different lengths for each shadow in a similar way, by passing a comma separated string of shadow lengths in the `shadow_length` attribute.\u003cbr\u003e\u003cbr\u003e **e.g.** \u003cbr\u003e `app:shadow_angle=\"45, 90, 135\"` \u003cbr\u003e`app:shadow_length=\"200, 300, 400\"`\u003cbr\u003e\u003cbr\u003e This will create 3 shadows at angles *45*, *90* and *135*, with shadows lengths, *200*, *300* and *400* respectively.\n\n#### XML\n```xml\n\u003ccom.sdsmdg.harjot.longshadows.LongShadowsWrapper\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#D8D4F2\"\u003e\n\n    \u003ccom.sdsmdg.harjot.longshadows.LongShadowsImageView\n        android:layout_width=\"70dp\"\n        android:layout_height=\"70dp\"\n        android:src=\"@drawable/ic_circle\"\n        app:shadow_angle=\"45, 90, 135\"\n        app:shadow_length=\"200, 300, 400\" /\u003e\n\n\u003c/com.sdsmdg.harjot.longshadows.LongShadowsWrapper\u003e\n```\n\n#### Result\n\n\u003cimg src=\"/screens/example_6.png\"\u003e\n\n## Example 7 (Non-Transparent background)\n\nSo far we have seen that the library generates long shadows for all non-transparent parts in an image, but what if we want the image to have a non-transparent background, but only create shadow for what is inside the image and not the background. This is where `background_transparent` and `background_color_to_ignore` attributes come into play.\n\nIf your image has say a white background, with some character in the middle and we only want the shadow for the middle character and completely avoid shadow for the white background, you can set `background_transparent` as `false`, indicating the background contains some color other that 0 (transparent), and `background_color_to_ignore` as `#FFFFFF`, indicating that we need to treat all white pixels as background and not generate shadow for them.\n\n\u003e **Note** : Transparent pixels are always counted as background and never generate any shadow of their own. This is useful in cases where the background of your image's background is a circle or a rounded-rectangle with white color, where we have to count both transparent pixels and white pixel as background.\n\n\u003cimg src=\"/screens/example_7_google_icon.png\" align=\"right\" width=\"100\"\u003e\n\n**e.g.** Lets say we want to display the google icon which has a white rectangle that acts as the background of the letter `G`.\u003cbr\u003e Lets see how can we generate long shadow only for the letter and avoid building the shadow for the rectangular white background.\n\n\u003e For this example we will create a rectangular drawable `rectangular_white_background.xml` which will act as the background to icon vector `ic_google_icon_colored.xml`. You can find these resource files [here](/app/src/main/res/drawable/)\n\n#### XML\n```xml\n\u003ccom.sdsmdg.harjot.longshadows.LongShadowsWrapper\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#DD6E42\"\u003e\n\n    \u003ccom.sdsmdg.harjot.longshadows.LongShadowsImageView\n        android:layout_width=\"100dp\"\n        android:layout_height=\"100dp\"\n        android:background=\"@drawable/rectangular_white_background\"\n        android:padding=\"20dp\"\n        android:src=\"@drawable/ic_google_icon_colored\"\n        app:background_color_to_ignore=\"#FFFFFF\"\n        app:background_transparent=\"false\" /\u003e\n\n\u003c/com.sdsmdg.harjot.longshadows.LongShadowsWrapper\u003e\n```\n\n#### Result\n\n\u003cimg src=\"/screens/example_7.png\"\u003e\n\n\u003e **Note** : As much as I want people to use this feature, I should warn that this won't work in several cases as android internally applies anti alias on images/bitmaps while scaling and this leads to some random colors around the boundaries. Since the algorithm checks for only one particular color, these new colors will be treated as contours and shadow will be generated, leading to unexpected results.\u003cbr\u003e\u003cbr\u003e\nSo if you want to have a background, I would suggest to draw the background in a different View and overlay this View with `LongShadowsView`/`LongShadowsImageView`/`LongShadowsTextView`, containing only the part you want to generate the shadow for.\u003cbr\u003e\u003cbr\u003e\nIf you are creating a custom view and want to draw a bitmap and use this feature, you may set `Paint#setFilterBitmap()` to `false`. This will disable anti aliasing for the bitmap.\n\n# Dynamically updating shadows\n\nAll the shadow parameters can be updated dynamically through java. Here is a small example : \n\n```java\n\n    LongShadowsImageView longShadowsImageView = (LongShadowsImageView) findViewById(R.id.long_shadows_image_view);\n\n    longShadowsImageView.setShadowAngle(\"135\");\n\n    // Set various paramters here\n\n    // Call the update method at the end, for the changes to take effect\n    longShadowsImageView.update();\n\n```\n\n\u003e **Note** : You need to call `update()` method at the end for the changes to take effect. This is done to avoid updating views again and again as the parameters are changed. This approach ensures that the views are updated only when the user is done with changing the parameters.\n\n# Custom Views and ViewGroups\n\n### Custom View\nIf you want your own custom view to be able to generate long shadows, just extend `LongShadowsView` instead of `View` while creating the custom view.\u003cbr\u003eThat's it :)\n```java\npublic class CustomLongShadowsView extends LongShadowsView {\n\n    public CustomLongShadowsView(Context context) {\n        super(context);\n    }\n\n    public CustomLongShadowsView(Context context, @Nullable AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    public CustomLongShadowsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        super.onDraw(canvas);\n\n        /*\n        * Draw whatever you want.\n        */\n\n    }\n}\n```\n\n\u003e **Note** : The custom view must be inside `LongShadowsWrapper` or `LongShadowsFrameLayoutWrapper` for the shadow to be generated.\n\n### Custom View Group\n\n`LongShadowsWrapper` and `LongShadowsFrameLayoutWrapper` are two custom view groups provided by library that extend `RelativeLayout` and `FrameLayout` respectively. These custom view groups recursively search for eligible views for long shadow generation, even inside nested view groups.\u003cbr\u003e\nSo if you have a custom view group, inside which you want to place your `LongShadowsImageView` or `LongShadowsTextView`, then you can just make this view group a direct child of `LongShadowsWrapper` or `LongShadowsFrameLayoutWrapper` and the library will take care of everything else.\n\nSee the example below : \n\n```xml\n\u003ccom.sdsmdg.harjot.longshadows.LongShadowsFrameLayoutWrapper\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\u003e\n\n    \u003ccom.example.abc.YourCustomViewGroup\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\u003e\n\n        \u003c!-- Place your views here --\u003e\n\n    \u003c/com.example.abc.YourCustomViewGroup\u003e\n\n\u003c/com.sdsmdg.harjot.longshadows.LongShadowsFrameLayoutWrapper\u003e\n```\n\n# How does this work ?\n\nThe `LongShadowsWrapper` is an extension of `Relative Layout`. The `LongShadowsFrameLayoutWrapper` is an extension of `FrameLayout`. Use any one of them as per your convenience.\n\nFirstly, eligible child views (`LongShadowsImageView`, `LongShadowsTextView` or extensions of `LongShadowsView`) are found using a recursive strategy. Once an eligible view is found it goes through the following process to generate the long shadow.\n\n1. First a bitmap is generated from the drawing cache of the View. The bitmap is converted into an integer array of pixels and passed on to the native function `getShadowPaths(...)` along with width, height and some other parameters.\n\n2. The native function first generates contours using the `contours` function. The `contours` function returns vector points which are on the boundary of an object. This is achieved by doing BFS(Breath First Search) on the grid and marking the points which are on the boundary and were encountered in the BFS run.\n \n3. Each of the contour is then passed to `getShadowPathsFromContour` function, which internally calls `boundaryPath` function. The `boundaryPath` function returns the **Front Polar Path** of the object. **Front Polar Path** is the set of points which will be directly visible from the Light Source, in polar order. We need the points in Polar Order, so that we can remove darkening of some regions due to overlapping, which will result in some dark regions during rendering due to alpha blending.\n \n    3.1. To find the **Front polar order**, we first extract the outer boundary of an object because for objects like 'O', there are two boundaries. This is done through `getOuterBoundary` function. In this function, we do BFS travesal from a point on outer boundary. So all the points which are not visited/marked after the BFS travesal belong to the inner boundary.\n \n    3.2. Now we have the Outer Boundary of the object. Now we will seperate the Boundary which will be visible by the Light source(lets name this boundary as Front Path) from the Overall Boundary. Also, notice that the Front Path will begin from the Upper tangent to the Lower tangent (If tangents are drawn from the Light Source to the Object). So we again apply BFS from Upper Tangent to Lower Tangent. This is done in the function `getPath`.\n \n    3.3. We still cannot be sure that the path returned by getPath is the Front Path, as there are 2 paths from the Upper Tangent to the Lower Tangent. So we compare the Area formed by the Light Source and the 2 Paths. The one with the less area will be the Front Path. `getArea` function calculates the area of the figure formed by the Light Source and the path by using Shoelace Formulae.\n \n    3.4. Corner Cases handling - We have used `atan` function to get the angle, inorder to sort the points in Polar Order. But `atan` function is discountinuos. So we have carefully handled the discountinuity of the function in the `getPolarOrder` function.\n\n4. Once we have the **Front Polar Path**, we translate its end points according to the `shadow length` and `shadow angle`.\n\n5. Now all these points are collected and converted into a structure `ShadowPath`. The `getShadowPathsFromContour` functions returns one `ShadowPath` object for every contour.\n\n6. All `ShadowPath` objects are passed back to Java, where `Path` objects are created using the points.\n\n7. Finally the `Path` object created is rendered and filled with a `LinearGradient` with starting and end points as defined in the `ShadowPath` object.\n\n**P.S.** : All the algorithms used in the native code have been implemented by my friend [Piyush Mehrotra](https://github.com/hm98).\n\n# Documentation\n\nAttributes for `LongShadowsWrapper` and `LongShadowsFrameLayoutWrapper`\n\n|XML attribute         |Java set methods               |Description                                 | Default Value     |\n|----------------------|-------------------------------|--------------------------------------------|-------------------|\n|shouldClipChildren    |setShouldClipChildren(...)     |Set whether to clip children to bounds      |false              |\n|shouldClipToPadding   |setShouldClipToPadding(...)    |Set whether to clip children to padding     |false              |\n|calculateAsync        |setShouldCalculateAsync(...)   |Set the flag for async shadow calculations. |true               |\n|showWhenAllReady      |setShowShadowsWhenAllReady(...)|Set the flag for showing all shadows after all calculations are over|true|\n|animateShadow         |setShouldAnimateShadow(...)    |Set the flag for shadow animation           |true               |\n|animationDuration     |setAnimationDuration(...)      |Set the value of shadow animation duration. |300ms              |\n\nAttributes for `LongShadowsImageView`, `LongShadowsTextView` and `LongShadowsView`\n\n|XML attribute         |Java set methods              |Description                                | Type          | Default Value     |\n|----------------------|------------------------------|-------------------------------------------|---------------|-------------------|\n|shadow_angle           |setShadowAngle(...)          |Set the shadow angle for the view          |String         |\"45.0f\"            |\n|shadow_length          |setShadowLength(...)         |Set the shadow length for the view         |String         |\"400\"              |\n|shadow_startColor      |setShadowStartColor(...)     |Set the start color of the shadow gradient |Color          |#88000000          |\n|shadow_endColor        |setShadowEndColor(...)       |Set the end color of the shadow gradient   |Color          |#00000000          |\n|shadow_blur_enabled    |setShadowBlurEnabled(...)    |Set the flag for enabling shadow blur      |boolean        |true               |\n|shadow_blur_radius     |setShadowBlurRadius(...)     |Set the shadow blur radius                 |int            |1                  |\n|shadow_alpha           |setShadowAlpha(...)          |Set the shadow alpha                       |int            |255                |\n|background_transparent |setBackgroundTransparent(...)|Set the flag for background transparency   |boolean        |true               |\n|background_color_to_ignore|setBackgroundColorToIgnore(...)|Set the background color to ignore    |Color          |#00000000          |\n\n# Limitations\n\n1. The library uses native code to make calculations faster. This will result in a larger apk size if `unversalApk` is built (APK for all architectures). So to reduce apk size, you may need to build separate apks for different architecture using ABI filters in `build.gradle` of your app. See [build.gradle](/app/build.gradle) for more details.\n\n# Credits\n\n1. **Piyush Mehrotra** ( [Codeforces](http://codeforces.com/profile/hm_98), [CodeChef](https://www.codechef.com/users/hm_98), [Github](https://github.com/hm98) ) : Implementation of algorithm to find the shadow paths from pixel array. This library would not have been possible without his talent and hard work.\n\n2. [Yaroslav](https://github.com/yarolegovich) : Implementation of asynchronous calculations and shadow animations in [MaterialShadows](https://github.com/harjot-oberai/MaterialShadows), which was directly reused in this library.\n\n3. [Feather Icons](https://feathericons.com/) : For providing the vectors used in examples.\n\n4. [WorldVectorLogo](https://worldvectorlogo.com/) : For providing some more vectors for the examples.\n\n5. [StackOverflow](https://stackoverflow.com/) : Nobody knows everything :)\n\n# License\n\u003cb\u003eLong-Shadows\u003c/b\u003e is licensed under `MIT license`. View [license](LICENSE.md).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharjot-oberai%2Flong-shadows","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fharjot-oberai%2Flong-shadows","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharjot-oberai%2Flong-shadows/lists"}