Last active
October 5, 2017 21:59
-
-
Save JohnyDays/ab352c6bab57683a2db5 to your computer and use it in GitHub Desktop.
Waterfall view solution
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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