Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/alan-eu/react-native-fast-shadow

Fast and high quality Android shadows for React Native
https://github.com/alan-eu/react-native-fast-shadow

android react-native shadow

Last synced: about 2 months ago
JSON representation

Fast and high quality Android shadows for React Native

Awesome Lists containing this project

README

        

# 🌖 react-native-fast-shadow

[![npm package](https://img.shields.io/npm/v/react-native-fast-shadow?color=brightgreen&label=npm%20package)](https://www.npmjs.com/package/react-native-fast-shadow)

**Fast and high quality** Android shadows for React Native

## Why

React Native only supports shadows on Android through the [elevation](https://reactnative.dev/docs/view-style-props#elevation-android) prop but achieving the desired effect is often impossible as it only comes with very few presets. Third-party libraries have been created to circumvent this but when used on many views, they can make you app slower or significantly increase its memory consumption.

## Features
* 💆‍♀️ **Easy to use:** Drop-in replacement for the `` component
* ⚡️ **Performant:** Shadows can be applied to a large number of views without any signicant performance impact. It has been optimized for low memory consumption and fast rendering
* 🎛 **Customizable:** Supports all the regular shadow props, `shadowRadius`, `shadowColor`, `shadowOpacity` and `shadowOffset`
* 📱 **Universal:** Works on all platforms. On iOS and Web, `` is just an alias of ``

## Getting started

```sh
npm install react-native-fast-shadow
# or
yarn add react-native-fast-shadow
```

**Usage:**

```jsx
import { ShadowedView } from 'react-native-fast-shadow';

```

**shadowStyle():**

The `shadowStyle()` utility can also be used to make it easier to create shadow styles and to **keep shadows consistent** accross platforms.
It will create the same `style` prop as above, but will divide the shadow radius by 2 on iOS (as for some reasons, iOS shadows are too large by a factor of 2 when compared to design tools or to CSS's box-shadows):

```jsx
import { ShadowedView, shadowStyle } from 'react-native-fast-shadow';

```

## How it works under the hood

On Android, shadow drawables are generated with the following process (see [ShadowFactory.java](https://github.com/alan-eu/react-native-fast-shadow/blob/main/android/src/main/java/com/reactnativefastshadow/ShadowFactory.java) for more details):
1. The shape of the view (rectangle with rounded corners) is painted in black on a canvas
2. A gaussian blur is applied to the canvas with the given `shadowRadius` using the Renderscript API
3. The drawable is then converted to a [NinePatchDrawable](https://developer.android.com/reference/android/graphics/drawable/NinePatchDrawable) to ensure that corners of the shadow won't be distorted when the view is resized. This way, we can generate only a small shadow drawable and **reuse it** for all views with the same border and blur radii.
4. Finally, the drawable is rendered behind the view content: it is tinted with `shadowColor`/`shadowOpacity` and offseted according to `shadowOffset`

**How NinePatchDrawable works** (notice how the corners are not streched when the drawable is resized):

## Troubleshooting

React-native-fast-shadow comes with the following limitations:
* **It only works with rounded rectangles:** Unlike the iOS `` implementation, `` won't work with freeform views. It expects its direct descendant view to be a rounded rectangle (up to a circle). **Solutions:** For shadowed `` elements, you can use [textShadowRadius](https://reactnative.dev/docs/text-style-props.html#textshadowradius). For complex shapes, [react-native-androw](https://github.com/folofse/androw) is your best option.
* **\ expects its child view to fill it:** It's up to you to make sure that `` and its children have the same size, otherwise the shadow will be larger than the content (you can think of `` as a view with a background color).
* **Corner radii can be inferred incorrectly:** We use ``'s style or the style of its direct child to infer the corner radii to apply. If your view hierarchy is more complex, corner radii might not be inferred correctly. **Solution:** rework your view hierarchy or pass the `borderRadius` directly to the `style` prop of ``.
* **Shadow radius is limited to 25 or below:** This limitation comes from Renderscript's [blur effect](https://developer.android.com/reference/android/renderscript/ScriptIntrinsicBlur). **Solution:** Let us know if this is an issue for you. This can probably be worked around by downscaling the shadow bitmap before applying the blur effect.

## Benchmark

The following table compares the memory consumption of `react-native-fast-shadow`, [react-native-androw](https://github.com/folofse/androw) and [react-native-shadow-2](https://github.com/SrBrahma/react-native-shadow-2) when rendering 100 150x200pt `` on a Pixel 2 with a 12pt radius shadow. The app was built using the debug variant and Hermes.

| No shadow | react-native-shadow-2 | react-native-androw | react-native-fast-shadow |
|-|-|-|-|
| 117MB (ref) | 430MB **(+313MB)** | 403MB **(+286MB)** | 123MB **(+6MB)** |