├── LICENSE
├── PhotoGrid.js
├── Photos.json
├── README.md
└── package.json
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Srish
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PhotoGrid.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Sivaraj Nagaraj
3 | */
4 | import React, { Component } from 'react';
5 | import PropTypes from 'prop-types';
6 | import { View, Image, Dimensions, Modal, TouchableOpacity } from 'react-native';
7 | import * as _ from 'lodash';
8 |
9 | class PhotoGrid extends Component {
10 |
11 | constructor(props) {
12 | super(props)
13 | this.state = {
14 | modalVisible: false,
15 | photoUrl: '',
16 | };
17 |
18 | }
19 |
20 | photoPopupToggle(item, index) {
21 | if (this.props.onPressItem) {
22 | this.props.onPressItem(index);
23 | } else {
24 | this.setState({ modalVisible: !this.state.modalVisible, photoUrl: item && item.url });
25 | }
26 | }
27 |
28 | renderChunk() {
29 | let chunk = _.chunk(this.props.PhotosList, 9);
30 |
31 | return chunk.map(
32 | (chunkItem, index) => {
33 | let row = _.chunk(chunkItem, 3);
34 |
35 | return row.map(
36 | (rowItem, rowIndex) => {
37 |
38 | return this.renderPhotoRow(rowItem, rowIndex, index * 9 + rowIndex * 3);
39 | }
40 | )
41 |
42 | }
43 | )
44 |
45 |
46 | }
47 |
48 | renderItem(item, index, expanded) {
49 | const { children, imageProps, ImageComponent } = this.props;
50 | return (
51 |
52 | { this.photoPopupToggle(item, index) }}>
53 |
63 | {children && children(item)}
64 |
65 |
66 | );
67 | }
68 |
69 | renderPhotoRow(rowItem, rowIndex, index) {
70 |
71 | if (rowIndex == 0) {
72 | return this.renderPhotoRow1(rowItem, index);
73 | }
74 | else if (rowIndex == 1) {
75 | return this.renderPhotoRow2(rowItem, index);
76 | }
77 | else if (rowIndex == 2) {
78 | return this.renderPhotoRow3(rowItem, index);
79 | }
80 |
81 | }
82 | renderPhotoRow1(row, index) {
83 | return (
84 |
85 | {
86 | row.map(
87 | (item, i) => {
88 | return this.renderItem(item, index + i, false);
89 | }
90 |
91 | )
92 | }
93 |
94 |
95 | )
96 | }
97 | renderPhotoRow2(row, index) {
98 | if (row.length == 1) {
99 | return (
100 |
101 | {this.renderItem(row[0], index, true)}
102 |
103 | )
104 | }
105 | else if (row.length == 2) {
106 | return (
107 |
108 | {this.renderItem(row[0], index, true)}
109 |
110 | {this.renderItem(row[1], index + 1, false)}
111 |
112 |
113 | )
114 |
115 | }
116 | else if (row.length == 3) {
117 | return (
118 |
119 | {this.renderItem(row[0], index, true)}
120 |
121 | {this.renderItem(row[1], index + 1, false)}
122 | {this.renderItem(row[2], index + 2, false)}
123 |
124 |
125 | )
126 |
127 | }
128 |
129 | }
130 | renderPhotoRow3(row, index) {
131 | if (row.length == 1) {
132 | return (
133 |
134 |
135 | {this.renderItem(row[0], index, false)}
136 |
137 |
138 | )
139 | }
140 | else if (row.length == 2) {
141 | return (
142 |
143 |
144 | {this.renderItem(row[0], index, false)}
145 | {this.renderItem(row[1], index + 1, false)}
146 |
147 |
148 | )
149 |
150 | }
151 | else if (row.length == 3) {
152 | return (
153 |
154 |
155 |
156 | {this.renderItem(row[0], index, false)}
157 | {this.renderItem(row[1], index + 1, false)}
158 |
159 | {this.renderItem(row[2], index + 2, true)}
160 |
161 | )
162 |
163 | }
164 |
165 | }
166 |
167 | renderGrid() {
168 | return (
169 |
170 | {this.renderChunk()}
171 |
172 | )
173 | }
174 |
175 | render() {
176 |
177 | return (
178 |
179 | {this.renderGrid()}
180 |
181 |
182 | { }}
186 | visible={this.state.modalVisible}>
187 |
188 | { this.photoPopupToggle() }}>
189 | { this.photoPopupToggle() }}
192 | style={{
193 | width: Dimensions.get('window').width,
194 | height: Dimensions.get('window').height,
195 | resizeMode: 'contain',
196 | alignSelf: 'center',
197 | }} />
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 | )
207 | }
208 |
209 | }
210 |
211 | /*Styles*/
212 |
213 | const styles = {
214 |
215 | container: {
216 | flex: 1,
217 | paddingTop: 20,
218 | alignItems: 'center',
219 | justifyContent: 'center'
220 | },
221 | ImageStyle: {
222 | width: View.width,
223 | height: 120,
224 | resizeMode: 'cover'
225 | },
226 |
227 | flexCol: {
228 | flexDirection: 'column',
229 | flex: 1
230 | },
231 | alignCenter: {
232 | flexDirection: 'row',
233 | flexWrap: 'wrap',
234 | flex: 1,
235 | alignItems: 'center',
236 | justifyContent: 'center',
237 | width: Dimensions.get('window').width - 20,
238 | paddingRight: 5
239 | },
240 |
241 | photoView: {
242 | height: 120,
243 | flex: 2,
244 | backgroundColor: 'gray',
245 | marginHorizontal: 5,
246 | marginVertical: 5,
247 | justifyContent: 'center'
248 | },
249 | expandedView: {
250 | height: 249,
251 | backgroundColor: 'gray',
252 | marginHorizontal: 5,
253 | marginVertical: 5,
254 | flex: 2
255 | },
256 | expandedImage: {
257 | height: 249,
258 | },
259 |
260 | }
261 |
262 | PhotoGrid.propTypes = {
263 | PhotosList: PropTypes.array,
264 | borderRadius: PropTypes.number,
265 | children: PropTypes.func,
266 | imageProps: PropTypes.object,
267 | onPressItem: PropTypes.func,
268 | ImageComponent: PropTypes.elementType
269 | };
270 |
271 | PhotoGrid.defaultProps = {
272 | ImageComponent: Image
273 | };
274 |
275 | export { PhotoGrid };
--------------------------------------------------------------------------------
/Photos.json:
--------------------------------------------------------------------------------
1 | [
2 | {"url":"http://lorempixel.com/400/400/fashion"},
3 | {"url":"http://lorempixel.com/400/400/city"},
4 | {"url":"http://lorempixel.com/400/400/people"},
5 | {"url":"http://lorempixel.com/400/400/nature"},
6 | {"url":"http://lorempixel.com/400/400/business"},
7 | {"url":"http://lorempixel.com/400/400/cats"},
8 | {"url":"http://lorempixel.com/400/400/food"},
9 | {"url":"http://lorempixel.com/400/400/nightlife"},
10 | {"url":"http://lorempixel.com/400/400/people"},
11 | {"url":"http://lorempixel.com/400/400/technics"},
12 | {"url":"http://lorempixel.com/400/400/transport"},
13 | {"url":"http://lorempixel.com/400/400/sports"},
14 | {"url":"http://lorempixel.com/400/400/fashion"},
15 | {"url":"http://lorempixel.com/400/400/city"},
16 | {"url":"http://lorempixel.com/400/400/people"},
17 | {"url":"http://lorempixel.com/400/400/nature"},
18 | {"url":"http://lorempixel.com/400/400/business"},
19 | {"url":"http://lorempixel.com/400/400/cats"},
20 | {"url":"http://lorempixel.com/400/400/food"},
21 | {"url":"http://lorempixel.com/400/400/nightlife"},
22 | {"url":"http://lorempixel.com/400/400/people"},
23 | {"url":"http://lorempixel.com/400/400/technics"},
24 | {"url":"http://lorempixel.com/400/400/transport"},
25 | {"url":"http://lorempixel.com/400/400/sports"}
26 | ]
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-photo-grid-frame
2 | React Native component that builds a grid of photos with a Dynamic Photo Size and Popup the Photo on click.
3 |
4 | ## Install
5 |
6 | `npm install react-native-photo-grid-frame --save`
7 |
8 | ## Screenshots
9 | 
10 | 
11 | 
12 | 
13 |
14 | ## Usage
15 |
16 | ```
17 | /**
18 | * Sample React Native App
19 | * https://github.com/facebook/react-native
20 | * @flow
21 | */
22 | import React, { Component } from 'react';
23 | import {
24 | AppRegistry,
25 | ScrollView
26 | } from 'react-native';
27 | import { PhotoGrid } from 'react-native-photo-grid-frame';
28 | import Photos from './Photos';
29 |
30 |
31 | export default class photoGrid extends Component {
32 | render() {
33 | return (
34 |
35 |
36 |
37 | );
38 | }
39 | }
40 |
41 | AppRegistry.registerComponent('photoGrid', () => photoGrid);
42 | ```
43 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-photo-grid-frame",
3 | "version": "2.0.1",
4 | "description": "React Native component that builds a grid of photos with a Dynamic Photo Size",
5 | "main": "PhotoGrid.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "dependencies": {
10 | "lodash": "^4.17.4"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+ssh://git@github.com/sivarajng/react-native-photo-grid-frame.git"
15 | },
16 | "keywords": [
17 | "react-native",
18 | "photo",
19 | "grid",
20 | "frame"
21 | ],
22 | "author": "Sivaraj Nagaraj",
23 | "license": "MIT",
24 | "bugs": {
25 | "url": "https://github.com/sivarajng/react-native-photo-grid-frame/issues"
26 | },
27 | "homepage": "https://github.com/sivarajng/react-native-photo-grid-frame#readme"
28 | }
--------------------------------------------------------------------------------