Skip to content

Instantly share code, notes, and snippets.

@f0rr0
Created June 5, 2019 06:40
Show Gist options
  • Save f0rr0/d79a89dcc345cc5d19528dbc880c4a76 to your computer and use it in GitHub Desktop.
Save f0rr0/d79a89dcc345cc5d19528dbc880c4a76 to your computer and use it in GitHub Desktop.
import React, { Component } from 'react';
import { View, Text, Dimensions, Button, TouchableOpacity, FlatList, StyleSheet } from 'react-native';
import chunk from 'lodash.chunk';
import { FluidNavigator, Transition } from 'react-navigation-fluid-transitions';
import { createAppContainer } from 'react-navigation';
import Image from 'react-native-fast-image';
const styles = StyleSheet.create({
container: {
flex: 1,
},
detailsImage: {
width: Dimensions.get('window').width,
height: Dimensions.get('window').width / 2 * 3,
},
detailsView: {
padding: 10,
backgroundColor: '#FFFFFF',
flex: 1,
},
buttonContainer: {
flex: 1,
justifyContent: 'flex-end',
},
text: {
paddingBottom: 40,
},
row: {
flexDirection: 'row',
},
cell: {
margin: 2,
},
imageContainer: {
flexDirection: 'row',
}
});
class ImageListScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
};
}
componentWillMount() {
const items = [];
const max = 39;
const randMax = 100;
for (let i = 0; i < max; i++) {
let randomNumber = Math.floor((Math.random() * randMax) + 1);
const idExists = (e) => e.id === randomNumber;
while (items.findIndex(idExists) > -1) {
randomNumber = Math.floor((Math.random() * randMax) + 1);
}
items.push({ url: `https://picsum.photos/950/1425?image=${randomNumber}`, id: randomNumber });
}
this.setState({ ...this.state, items });
}
render() {
return (
<View style={styles.container}>
<ImageGrid
images={this.state.items}
imageSelected={(image) => this.props.navigation.navigate('imageDetails', { url: image.url })}
/>
</View>);
}
}
class ImageDetailsScreen extends React.Component {
render() {
const { navigation } = this.props;
const { url: uri = '' } = navigation.state.params;
return (
<View style={styles.container}>
<View style={styles.imageContainer}>
<Transition shared={uri}>
<Image style={styles.detailsImage} source={{ uri }} />
</Transition>
</View>
<Transition anchor={uri}>
<View style={styles.detailsView}>
<View style={styles.buttonContainer}>
<Button title="Back" onPress={() => navigation.goBack()} />
</View>
</View>
</Transition>
</View>
);
}
}
class ImageGrid extends Component {
constructor(props) {
super(props);
this._colCount = 2;
const { width: windowWidth } = Dimensions.get('window');
this._margin = 2;
this._photoSize = (windowWidth - this._margin * this._colCount * 2) / this._colCount;
this.state = { chunkedImages: chunk(props.images, this._colCount) };
}
_colCount
_photoSize
_margin
_chunkedImages
componentWillReceiveProps(nextProps) {
this.setState({ ...this.state, chunkedImages: chunk(nextProps.images, this._colCount) });
}
render() {
return (
<FlatList
data={this.state.chunkedImages}
keyExtractor={this.keyExtractor}
renderItem={this.renderItem.bind(this)}
/>);
}
keyExtractor(_, index) {
return `key_${index}`;
}
renderItem(item) {
return (
<View style={styles.row}>
{item.item.map(this.renderCell.bind(this))}
</View>
);
}
renderCell(image) {
return (
<TouchableOpacity onPress={() => this.props.imageSelected(image)} key={image.url}>
<View style={styles.cell}>
<Transition shared={image.url}>
<Image
resizeMode="cover"
source={{ uri: image.url }}
style={{ width: this._photoSize, height: this._photoSize / 2 * 3 }}
/>
</Transition>
</View>
</TouchableOpacity>
);
}
}
const Navigator = createAppContainer(FluidNavigator({
imageList: { screen: ImageListScreen },
imageDetails: { screen: ImageDetailsScreen },
}, {
style: { backgroundColor: '#FFFFFF' },
defaultNavigationOptions: {
gesturesEnabled: true,
},
}));
class App extends React.Component {
static router = Navigator.router;
render() {
const { navigation } = this.props;
return (
<Navigator navigation={navigation} />
);
}
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment