Skip to content

Instantly share code, notes, and snippets.

@JohnyDays
Last active October 5, 2017 21:59
Show Gist options
  • Save JohnyDays/ab352c6bab57683a2db5 to your computer and use it in GitHub Desktop.
Save JohnyDays/ab352c6bab57683a2db5 to your computer and use it in GitHub Desktop.
Waterfall view solution
'use strict'
var React = require('react-native')
var {
View,
StyleSheet,
} = React
var {StyleSheetRegistry} = StyleSheet
class Waterfall extends React.Component {
constructor(){
this.state = {}
}
render() {
return (
<View {...this.props} ref = "__waterfallView" style = {this.getStyles()}>
{this.mapViews(this.props.children)}
</View>
);
}
mapViews(views){
return views.map((view, index) => {
var key;
if(view.props.key){
key = view.props.key
}else{
key = index
}
var style;
if(this.state[key]){
style = {
left:this.state[key].x,
top:this.state[key].y,
width:this.state[key].width,
height:this.state[key].height,
position:'absolute',
}
}else{
style = {
opacity:0
}
}
if(view.props.style){
style = [view.props.style, style]
}
var props = {
ref:key,
key,
style,
}
var element = React.cloneElement(view, props)
return element
}
)
}
componentDidMount(){
requestAnimationFrame(()=> {
var layouts = []
for(var key in this.refs){
var view = this.refs[key];
((view, key) => {
layouts.push(new Promise((resolve, reject) => view.measure((x, y, width, height) => {resolve({key, value:{width, height}})}, reject)))
})(view, key)
}
console.log(layouts)
Promise.all(layouts).then((results) => {
results = keyedArrayToObject(results);
var containerWidth = results.__waterfallView.width
var containerHeight = results.__waterfallView.height
delete results.__waterfallView
var columnWidth = results[Object.keys(results)[0]].width
var columnAmount = Math.floor(containerWidth /columnWidth)
var padding = (containerWidth - (columnWidth * columnAmount)) / 2
var layout = {...results, __waterfallView:{padding: padding}}
var columnHeights = []
for (var i = columnAmount - 1; i >= 0; i--) {
columnHeights.push(0)
}
for(var key in results){
var itemHeight = results[key].height
var lowestHeight = columnHeights[0]
for(var height of columnHeights){
if(height < lowestHeight){
lowestHeight = height
}
}
var column = columnHeights.indexOf(lowestHeight)
layout[key].y = lowestHeight
layout[key].x = (column * columnWidth) + padding
columnHeights[column] = columnHeights[column] + itemHeight
}
var lowestHeight = columnHeights[0]
for(var height of columnHeights){
if(height < lowestHeight){
lowestHeight = height
}
}
layout.__waterfallView.height = lowestHeight
this.setState(layout)
}).done()
})
}
getStyles(){
if(this.state.__waterfallView){
var styles = {paddingLeft: this.state.__waterfallView.padding, paddingRight: this.state.__waterfallView.padding, height: this.state.__waterfallView.height }
if(this.props.style){
styles = [styles, this.props.style]
if(this.props.style.padding){
styles.paddingLeft = this.props.style.padding + styles.paddingLeft
styles.paddingRight = this.props.style.padding + styles.paddingRight
}
}
return styles
}else{
return this.props.style;
}
}
}
var keyedArrayToObject = (array) => {
var object = {}
for(var item of array){
object[item.key] = item.value
}
return object
}
module.exports = Waterfall;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment