UNPKG

@cawfree/react-native-masonry

Version:

A bare-bones masonry layout for react-native.

146 lines (137 loc) 4.07 kB
# react-native-masonry A bare-bones masonry layout for react-native. <p align="center"> <img src="./raw/anim.gif" alt="@cawfree/react-native-masonry" /> </p> ## 🚀 Getting Started You can integrate with your project using [npm](https://www.npmjs.com/package/@cawfree/sofia): ``` npm install --save @cawfree/react-native-masonry ``` Alternatively, you can use [yarn](https://www.npmjs.com/package/@cawfree/sofia): ``` yarn add @cawfree/react-native-masonry ``` ## ✏️ Example In this example, we animate an infinite number of red boxes... but in your application, you can place and animate whatever and however you want. :) ```javascript import React from 'react'; import { Animated, View, StyleSheet, ScrollView, } from 'react-native'; import PropTypes from 'prop-types'; import Masonry from '@cawfree/react-native-masonry'; const styles = StyleSheet.create({ masonry: { flex: 1, backgroundColor: 'blue', }, }); export default class App extends React.Component { constructor(nextProps) { super(nextProps); this.state = ({ fetching: false, // XXX: Initialize the layout with some values. items: [ { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, ], }); this.__renderItem = this.__renderItem.bind(this); this.__onScroll = this.__onScroll.bind(this); this.__onItemPlaced = this.__onItemPlaced.bind(this); } // XXX: Render anything you want! __renderItem(item) { const height = (item.key * 500) + 100; const { opacity, } = item; return ( <Animated.View style={{ flex: 1, borderWidth: 1, height, backgroundColor: 'red', opacity, }} /> ); } // XXX: Callback from Masonry when a brick has been placed. __onItemPlaced(item) { const { opacity, } = item; Animated.timing( opacity, { toValue: 1, duration: 1000, useNativeDriver: true, }, ) .start(); } __onScroll(e) { const { layoutMeasurement, contentOffset, contentSize, } = e.nativeEvent; const { onEndReachedThreshold, } = this.props; const { fetching, } = this.state; const thresholdIsReached = (layoutMeasurement.height + contentOffset.y) >= (contentSize.height - onEndReachedThreshold); if (thresholdIsReached && !fetching) { this.setState({ // XXX: Add some more items to the list! items: ([ ...this.state.items, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, { key: `${Math.random()}`, opacity: new Animated.Value(0) }, ]), }); } } render() { const { items, } = this.state; return ( <Masonry style={styles.masonry} items={items} renderItem={this.__renderItem} onItemPlaced={this.__onItemPlaced} ScrollComponent={ScrollView} useNativeDriver scrollEventThrottle={400} onScroll={this.__onScroll} /> ); } } ``` ## ✌️ License [MIT](https://opensource.org/licenses/MIT)