├── .github
└── ISSUE_TEMPLATE.md
├── .gitignore
├── .npmignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── DesignPrinciples.md
├── EvenMoreExamples.md
├── LICENSE.md
├── README.md
├── UniversalPinterestLayout.md
├── UniversalTiles.md
├── package.json
└── src
├── components
├── Column.js
├── Grid.js
└── Row.js
├── index.js
└── lib
├── ScreenInfo.js
└── helpers.js
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | npm-debug.log
2 | node_modules/
3 | .vscode
4 | .DS_Store
5 | **/.DS_Store
6 | yarn.lock
7 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | tests/
2 | node_modules/
3 | CHANGELOG.md
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) with the minor addition of Breaking vs Non-Breaking sections under 'Changed.'
5 |
6 | This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Released]
9 |
10 | ## [0.41.0]
11 |
12 | ### Changed (breaking)
13 |
14 | - fixed break points (see Readme)
15 |
16 | ### Added (non-breaking)
17 |
18 | - setBreakPoints
19 |
20 | ## [0.40.0]
21 |
22 | ### Changed (breaking)
23 |
24 | - alignLines on Row now has 'stretch' as default value (consistent with CSS spec)
25 |
26 | ## [0.39.0]
27 |
28 | ### Changed (breaking)
29 |
30 | - Screen-size-specific _size_ and _hidden_ props now reference both the current screen width in case of Columns and the current screen height in case of Rows, both of which change with orientation. The _offset_ props only apply to Columns so they still refer to the current screen width.
31 |
32 | The following are the thresholds for these props:
33 |
34 | - SMALL_Width = 375
35 | - MEDIUM_Width = 414
36 | - LARGE_Width = 768
37 | - XLARGE_Width = 1024
38 |
39 | - SMALL_Height = 667
40 | - MEDIUM_Height = 736
41 | - LARGE_Height = 1024
42 | - XLARGE_Height = 1366
43 |
44 | ### Changed (non-breaking)
45 |
46 | - Rows and Cols can have position absolute (use for creating overlays, see Eample 2 for 2D positioning technique)
47 |
48 | ## [0.38.0]
49 |
50 | - Do not use this release (design regression fixed in 0.39.0)
51 |
52 | ## [0.37.0]
53 |
54 | ### Changed (breaking)
55 |
56 | - default value for vAlign on Row is now `stretch`
57 | - default value for hAlign on Col is now `stretch`
58 | - Grid is {flex: 1} by default and Grid's style can be fully overriden with user styles
59 |
60 | ## [0.35.0] 2017-11-28
61 |
62 | ### Changed (breaking)
63 |
64 | - Removed Row's reaction to its own layout changes. Screens must contain Grid at top of view hierarchy in order to respond to orientation changes. Non-orientation layout changes should be handled with Flexbox contsraints, no longer from JS. Simplifies code, usage and improves performance.
65 |
66 | ## [0.34.0] - 2017-11-22
67 |
68 | ### Changed (non-breaking)
69 |
70 | - exposed .shown and .hidden as instance variables on Row and Col components
71 |
72 | ### Changed (breaking)
73 |
74 | - replaced layoutEvent prop and having to build stateful components (and the ambiguity around where in the component tree to place layoutEvent) with a Grid component that sits at the very top of the UI component tree, above ScrollView, ListView and FlatList et al as an optional component for when managing state is necessary (e.g. adaptive layouts)
75 |
76 | ## [Released]
77 |
78 | ## [0.33.0] - 2017-06-27
79 |
80 | ### Changed (non-breaking)
81 |
82 | - fixed hide() and show() for columns in wrapped rows
83 | - made 'center' synonomous with 'middle' throughout
84 |
85 | ### Changed (breaking)
86 |
87 | - columns and rows have overflow: 'hidden' by design
88 |
89 | ## [Released]
90 |
91 | ## [0.32.01] - 2017-06-27
92 |
93 | ### Changed (non-breaking)
94 |
95 | - fixed regression with Row update when no layoutEvent is specified
96 |
97 | ## [0.32.0] - 2017-06-27
98 |
99 | ### Added
100 |
101 | - `alignSelf` for Row and Column. See Readme.
102 |
103 | ### Changed (non-breaking)
104 |
105 | - updated the Universal Tiles demo show the number of each tile at the center so it's clear what is happening when tiles are removed and re-inserted and when orientation changes.
106 |
107 | [*Updated* Universal Tiles demo https://www.youtube.com/watch?v=OPUKz9wQ1Ks](https://www.youtube.com/watch?v=OPUKz9wQ1Ks)
108 |
109 | ## [0.31.0] - 2017-06-26
110 |
111 | [Universal Tiles demo https://www.youtube.com/watch?v=x785Qib0ySg](https://www.youtube.com/watch?v=x785Qib0ySg)
112 |
113 | ### Removed (Breaking)
114 |
115 | - `fullHeight` may be supplied as prop to Row ONLY as a convenience to enable vAlign to work on child Column(s) -- fullWidth on Row has been removed since it can interfere with Column's offset prop.
116 |
117 | - `fullWidth` may be supplied as prop to Column ONLY as a convenience to enable hAlign to work on child Row(s) -- fullHeight on Column has been removed since it can interfere with Row's size prop.
118 |
119 | ### Added
120 |
121 | - Rows can have size props to set high, both in percent and absolute points. See updated Readme.
122 |
123 | - Example of Universal Tiles: responsive tiles with hide/show for Universal Apps. See updated Readme.
124 |
125 | - Column and Row now have show() and hide() methods. See Example #1 in updated Readme for usage.
126 |
127 | ### Changed (Breaking)
128 |
129 | - Simplified interaction of props and styles: except for position, styles take precedence over props.
130 |
131 | - 'wrap` is now the default behavior for Row. You must specify 'noWrap' to disable wrapping.
132 |
133 | ### Changed (non-breaking)
134 |
135 | - Updated Readme
136 |
137 | - Fixed regression with non-grid props propagation
138 |
139 | ## [0.30.0] - 2017-06-21
140 |
141 | ### Removed (Breaking)
142 |
143 | - breakPoints prop was introduced as a screen-size-specific, point-valued _override_ for screen-size-specific percent-valued `size` props. Given that we have just added point-valued, screen-size-specific `size` and `offset` props in 0.29.88, we no longer need breakPoints. Mixing percent-valued and point-valued sizing info is an anti-pattern and it has been removed. Use of minWidth and minHeight is still supported as explicit override, but it's no longer exposed as a high level interface, since it's noth confusing and not necessary given the aforementioned additions.
144 |
145 | ## [0.29.88 & 0.29.89] - 2017-06-20
146 |
147 | ### Added
148 | - Points-based `size` and `offset` props since absolute positioning is sometimes needed in a responsive layout, e.g. position of back arrow and hamburger menu on navigation bar.
149 | - `baseline` value for `vAlign` when supplied to Row
150 | - This CHANGELOG.md
151 |
152 | ### Changed (Non-breaking)
153 | - Fixed device-size-based offsets
154 | - Fixed regression in item alignment for RTL mode
155 | - Fixed handling of left/right margins (when set in style) relative to offset value and RTL/LTR modes
156 | - Refactored code for clarity and correctness
157 | - Updated Readme to explain use of newly added features
158 |
159 | ### Changed (Breaking)
160 |
161 | None.
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribute
2 |
3 | ## Introduction
4 |
5 | First, thank you for considering contributing to react-native-responsive-grid! It's people like you that make the open source community such a great community! 😊
6 |
7 | We welcome any type of contribution, not only code. You can help with
8 | - **QA**: file bug reports, the more details you can give the better (e.g. screenshots with the console open)
9 | - **Marketing**: writing blog posts, howto's, printing stickers, ...
10 | - **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ...
11 | - **Code**: take a look at the [open issues](issues). Even if you can't write code, commenting on them, showing that you care about a given issue matters. It helps us triage them.
12 | - **Money**: we welcome financial contributions in full transparency on our [open collective](https://opencollective.com/react-native-responsive-grid).
13 |
14 | ## Your First Contribution
15 |
16 | Working on your first Pull Request? You can learn how from this *free* series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
17 |
18 | ## Submitting code
19 |
20 | Any code change should be submitted as a pull request. The description should explain what the code does and give steps to execute it. The pull request should also contain tests.
21 |
22 | ## Code review process
23 |
24 | The bigger the pull request, the longer it will take to review and merge. Try to break down large pull requests in smaller chunks that are easier to review and merge.
25 |
26 | It is also always helpful to have some context for your pull request. What was the purpose? Why does it matter to you?
27 |
28 | ## Financial contributions
29 |
30 | We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/react-native-responsive-grid).
31 | Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.
32 |
33 | ## Questions
34 |
35 | If you have any questions, create an [issue](issue) (protip: do a quick search first to see if someone else didn't ask the same question before!).
36 | You can also reach us at hello@react-native-responsive-grid.opencollective.com.
37 |
38 | ## Credits
39 |
40 | ### Contributors
41 |
42 | Thank you to all the people who have already contributed to react-native-responsive-grid!
43 |
44 |
45 |
46 | ### Backers
47 |
48 | Thank you to all our backers! [[Become a backer](https://opencollective.com/react-native-responsive-grid#backer)]
49 |
50 |
51 |
52 |
53 | ### Sponsors
54 |
55 | Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/react-native-responsive-grid#sponsor))
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/DesignPrinciples.md:
--------------------------------------------------------------------------------
1 | ## Design Principles
2 |
3 | ### _Simple Calculations_
4 |
5 | This grid simplifies the mental model for grid based layouts by abandoning the format-based, columns-per-view approach (e.g. "12 column grid") and instead allowing the developer to specify the width of each grid column as a percentage of parent Row's width, so 10% meams 10 columns will fit inside the row, and 8.333% means 12 columns.
6 |
7 | ### _Simple Layout_
8 |
9 | While most React Native developers use `flex: n` (which is based on Facebook's Yoga layout algorithm) in place of the confusing mix of `flexGrow`, `flexShrink` and `flexBasis` (lots has been written about the Flexbox spec and its steep learning curve, e.g. [flex-grow is weird. Or is it?](https://css-tricks.com/flex-grow-is-weird/)) we still find it difficult to use `flex: n` since n is not a percentage of the parent view's computed or explicit width or height but a more complex constraint. We lose perspective on the item size relative to the size of its parent as we constrain the item sizes relative to each other rather that the size of each item relative to a single parent. It's like O(n) vs O(n^2) complexity for these two different sizing models in that instead of relating the size of each item to the size of its parent as a percentage (n steps), with `flex: n` we relate the size of each item to the size of each other (sibling) item (n^2 steps.) That's because we don't have a single scale (parent's width or height) to measure against. More importantly, we give up direct knowledge of each item's width as a percentage of the parent's width in favor of having comparative size factors for the sibling items. However, there are times when we'd like to have that, so this grid does not take that ability away from us. In fact, this grid relies heavily (under the hood) on Flexbox features like flexDirection, justifyContent, alignItems, and alignContent, but it uses them under the hood and combines them with a simple percentage-based layout model. This results in a layout system that is simple and predictable, yet powerful.
10 |
11 | Having said that, there is an escape hatch in that we can still specify a numerical `flex: n` constraint in styles of Row and Column and even use bare Views mixed in with Row and Column components.
12 |
13 | _When To Use Flexbox Sizing:_
14 |
15 | _In some cases when having an absolutely sized view followed (vertically or horizontally) by a view that must take up the remaining space, we'll need to use a wrapping grid element -- Column (to wrap vertical layout) or Row (to wrap horizontal layout) -- with style={{flex: 1}} and same on the Flex sized element that it wraps along with the absolutely sized element. However, such mixing of absolute and Flex sizing is not recommended as it won't lead to a fully responsive UI layout._
16 |
17 | Other than that, the only other reason to use Flexbox grow/shrink sizing is for non-scrollable "squishy" UIs that shrink/grow elements instead of performing dynamic layout change and/or keeping things in proportion to screen width (rather tham to each other as is the case with Flexbox grow/shrink siing) via percentage based layout. You can still do that with this grid but you wouldn't want to use it if that was your only use case.
18 |
19 | ### _Works in Both Directions_
20 |
21 | Sometimes, we lay things out from left to right (LTR.) Other times, we might find it easier to lay things out from right to left (RTL.) I've found that RTL support to be generally lacking in both React and React Native grids, so I've added support for it. React makes it really simple. This can be very useful for apps with right-to-left text, i.e. Arabic, Aramaic, Azeri, Dhivehi/Maldivian, Hebrew, Kurdish (Sorani), Persian/Farsi, and Urdu.
22 |
--------------------------------------------------------------------------------
/EvenMoreExamples.md:
--------------------------------------------------------------------------------
1 | # Even More Examples
2 |
3 | ## Responsive Layout
4 |
5 |
6 |
7 |
8 | ### Navbar (ExNavigation - Todo: switch exampe to React Navigation)
9 |
10 | ```jsx
11 |
12 | static route = {
13 | navigationBar: {
14 | title: 'Home',
15 | renderTitle: (route, props) => {
16 | return (
17 |
18 |
281 |
282 | LOG IN WITH FACEBOOK
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 | ```
292 |
293 | ## Wrapped Alignment
294 |
295 | By default, content (plural) in Rows will wrap if the sum of the width values of the content is larger than 100% of the row's width. To prevent wrapping of content (plural) the Row must have the 'noWrap' prop supplied. When rows are allowed to wrap the row will contain two or more horizontal "lines" that hold the items within it. The lines themselves (as opposed to the items within them) may be aligned in the vertical direction using alignLines prop (see Props section above for details)
296 |
297 | Here are two screens illustrating the effect of wrap, vAlign and alignLines. The first tells the row that it can turn into a multi-line row that wraps the items. The second tells it how to vertically align the items. The third tells it how to vertically align the wrapped lines that contain the items.
298 |
299 | Markup #1:
300 | ```jsx
301 |
302 |
326 |
327 | SEE ALL
328 |
329 |
330 |
331 | ```
332 |
333 |
334 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Marc Fawzi (for modified version)
4 |
5 | The MIT License (MIT)
6 |
7 | Copyright (c) 2016 Derek Tor (for original)
8 |
9 | Permission is hereby granted, free of charge, to any person obtaining a copy of
10 | this software and associated documentation files (the "Software"), to deal in
11 | the Software without restriction, including without limitation the rights to
12 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13 | the Software, and to permit persons to whom the Software is furnished to do so,
14 | subject to the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included in all
17 | copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
21 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
22 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | [](https://npmjs.org/package/react-native-responsive-grid)
4 |
5 | [](#backers) [](#sponsors)
6 |
7 | # React Native Library for Responsive and Universal Apps
8 |
9 | ### Pending Proposals
10 |
11 | All issues that are not bugs are appropriately labeled and closed.
12 |
13 | For now we have three kinds of non-bug issues that are open:
14 |
15 | - [Pending Proposals](https://github.com/idibidiart/react-native-responsive-grid/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3Aproposal+label%3Apending)
16 |
17 | - [Pending Questions](https://github.com/idibidiart/react-native-responsive-grid/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3Aquestion+label%3Apending)
18 |
19 |
20 | ### Install
21 |
22 | In your project folder, `yarn add react-native-responsive-grid`
23 |
24 | *For best results, use React Native 0.50 or later
25 |
26 | ## Predictable Responsive Layout
27 |
28 | This grid is based on row and column components that can be nested in an alternating pattern to build a responsive and adaptive 'tree of Views' of any shape and depth. It eschews complicated Flexbox-based size constraints in favor of simple percentage-based size constraints. And it does so while using Flexbox-based vertical and horizontal alignment constraints.
29 |
30 | A Column may contain one or more Rows, each of which may contain one or more Columns, each of which may contain one or more Rows, and so on. Both Rows and Columns can be styled using predictable, percentage-based dimensions and, in case of Columns, percentage-based horizontal `offset`.
31 |
32 | Rows can be aligned inside Columns, vertically (along main axis,) and aligned and stretched horizontally (along cross axis.) Columns can be aligned inside Rows, horizontally (along main axis), and and aligned and stretched vertically (along cross axis.) Additionally, the lines created within a Row that wraps may be aligned and stretched vertically relative to a parent Column.
33 |
34 | With these basic features, we can build the entire UI component tree (or an individual component's subtree) as a consistent, repeatable and recursive pattern, one that has predictable and dynamic --not only static-- responsiveness and the ability to trigger specific adaptive behavior.
35 |
36 | _When To Use Flexbox Sizing:_
37 |
38 | _In some cases when having an absolutely sized view followed (vertically or horizontally) by a view that must take up the remaining space, we'll need to use a wrapping grid element -- Column (to wrap vertical layout) or Row (to wrap horizontal layout) -- with style={{flex: 1}} and same on the Flex sized element that it wraps along with the absolutely sized element. However, such mixing of absolute and Flex sizing is not recommended as it won't lead to a fully responsive UI layout._
39 |
40 | _The only other reason to use Flexbox grow/shrink sizing with this Grid is for grow-and-shrink-in-place UI (aka "squishy" UI) where elements shrink and grow in elastic fashion and relative to each other instead of undergoing dynamic layout change and/or staying in proportion to screen width._
41 |
42 | ## Examples
43 |
44 | You may use this grid to build responsive 2D layouts that maintain their relative proportions, change their basic structure in a predictable way and dynamically decide what content to display, based on screen size, aspect ratio, and orientation.
45 |
46 | ## [Example 1: Universal, Responsive Pinterest Layout](https://www.youtube.com/watch?v=QyIRoKinyLU)
47 | [](https://www.youtube.com/watch?v=QyIRoKinyLU)
48 |
49 | ## [Example 2: Reponsive Tiles for Universal Apps](https://www.youtube.com/watch?v=OPUKz9wQ1Ks)
50 | [](https://www.youtube.com/watch?v=OPUKz9wQ1Ks)
51 |
52 | ## [Example 3: Selecting an image with the right aspect ratio](https://www.youtube.com/watch?v=Nghqc5QFln8)
53 | [](https://www.youtube.com/watch?v=Nghqc5QFln8)
54 |
55 | ## [Example 4: Responsive Break Points (Row Wrapping)](https://www.youtube.com/watch?v=GZ1uxWEVAuQ)
56 | [](https://www.youtube.com/watch?v=GZ1uxWEVAuQ)
57 |
58 | ## [Example 5: FlatList + Row & Column Wrapping](https://www.youtube.com/watch?v=qLqxat3wX_8)
59 | [](https://www.youtube.com/watch?v=qLqxat3wX_8)
60 |
61 | The demos in the videos above show some of the possibilities, but this grid is capable of more complex responsive and adaptive behavior.
62 |
63 | ### Example 1: Universal, Responsive Pinterest Layout
64 |
65 | This examples showcases 2-dimensional Constraint-Based Layout using a custom layout in a few lines of code. Flexbox fails us here in that it does not support a 2-dimensional constraint layout. This is precisely why React Native needs native support for display:'grid' Until then you may use this grid with your own constraint-based layout. This example shows a simplified Pinterest-like layout. You may extend it to build a masonry effect using a box packing algorithm and Flexbox's 1-dimensional constraint-based elastic layout. One thing this grid is not designed to do is to implement transitions but it can be forked and extended to do that (would happy take a PR.)
66 |
67 | [Source Code for Example 1](https://github.com/idibidiart/react-native-responsive-grid/blob/master/UniversalPinterestLayout.md)
68 |
69 | ### Example 2: Reponsive Tiles for Universal Apps
70 |
71 | This examples showcases the grid's 1-dimensional Constraint-Based Layout using Flexbox wrapping behavior.
72 |
73 | The problem it solves is how to make a tiled screen layout that looks consistent across all screen sizes and aspect ratios, It involves the following:
74 |
75 | 1. How to size tiles such that they change size relative to the size of the screen *as well as* retain their shape (width/height aspect ratio)
76 |
77 | 2. How do we hide/show tiles on demand and fill the void left by hidden tiles.
78 |
79 | The goal is how to do the above in an elegant and declarative way that allows the average user to work without all the tedious implementation details of doing it in row Flexbox and JS.
80 |
81 | _This example also showes how to use alignLines='stretch' for wrapped row content to have the wrapped lines fill the whole screen. It's the right way to partition a Row vertically in 1/n tall lines where n is the number of wrapping-stacked fullWidth columns._
82 |
83 | [Source Code for Example 2](https://github.com/idibidiart/react-native-responsive-grid/blob/master/UniversalTiles.md)
84 |
85 | ### Example 3: Selecting an image with the right aspect ratio
86 |
87 | In this demo, the grid picks the image with the **closest aspect ratio** to the device aspect ratio, dynamically, taking into account the current device orientation. The images themselves must be sized and cropped by the designer so that they match the common device aspect ratios (see below) while also showing the part of the image that the designer intends to show for each aspect ratio. Since there could be many aspect ratios that correspond to different devices we should have multiple such images (and, optionally, their rotated versions.)
88 |
89 | The following table maps some common device aspect ratios to the ratio of width/height of devices known to this developer, for both landscape and portrait device orientations. The physical device aspect ratio does not change with device rotation (i.e. a device with 16:9 aspect ratio does not become one with a 9:16 aspect ratio when it's rotated, although it does mathematically), but since the width and height get flipped when changing orientation from portrait to lanscape and vice versa, we need to have two images per each physical device aspect ratio, one for portrait mode and the other for landscape. However, if our app only supports portrait or landscape mode then we only need to have the one corresponding to that orientation.
90 |
91 | | Aspect Ratio | Width | Height | Width/Height Ratio (landscape) | Devices
92 | | :---: | :---: | :---: | :---: | :---: |
93 | | '16:9' | 568 | 320 | 1.77 | iPhone 5
94 | | '16:9' | 667 | 375 | 1.77 | iPhone 6 & 7
95 | | '16:9' | 736 | 414 | 1.77 | iPhone 6 Plus & 7 Plus
96 | | '16:10' | ? | ? | 1.6 | ?
97 | | '3:2' | 480 | 320 | 1.5 | iPhone 4
98 | | '4:3' | 1024 | 768 | 1.33 | iPad Mini, iPad Air and small iPad Pro
99 | | '4:3' | 1366 | 1024 | 1.33 | Large iPad Pro
100 | | '1:1' | 1 | ? | ? | ?
101 |
102 | | Aspect Ratio | Width | Height | Width/Height Ratio (portrait) | Devices
103 | | :---: | :---: | :---: | :---: | :---: |
104 | | '16:9' | 320 | 568 | 0.56 | iPhone 5
105 | | '16:9' | 375 | 667 | 0.56 | iPhone 6 & 7
106 | | '16:9' | 414 | 736 | 0.56 | iPhone 6 Plus & 7 Plus
107 | | '16:10' | ? | ? | 0.625| ?
108 | | '3:2' | 320 | 480 | 0.66 | iPhone 4
109 | | '4:3' | 768 | 1024 | 0.75 | iPad Mini, iPad Air and small iPad Pro
110 | | '4:3' | 1024 | 1366 | 0.75 | Large iPad Pro
111 | | '1:1' | 1 | ? | ? | ?
112 |
113 | ```jsx
114 | {(state, setState) => (
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | )}
131 |
132 | ```
133 |
134 | ### Example 4: Responsive Break Points (Row Wrapping)
135 |
136 | A more basic example of he grid's 1-Dimensional Constraint-Based Layout using Flexbox.
137 |
138 | In the second demo, the grid folds columns in rows based on the screen-device-depebdent `xxSize` prop provided on the column (which can be percentage based, e.g. smSize, or point based, e.g. smSizePoints. This means that different break points can be supplied for the different screen sizes in both absolute and relative terms. This example demonstrates how to get Row content (e.g. child Columns) to wrap at certain break points (which can be supplied per screen width)
139 |
140 | The following are the preset screen widths (in points) at which breaks maybe specified (where row wraps columns within it into new horozintal lines):
141 |
142 | - SMALL_Width: 375 (0-375)
143 | - MEDIUM_Width: 767 (376-767)
144 | - LARGE_Width: 1023 (768-1023)
145 | - XLARGE_Width: 1024+
146 |
147 | - SMALL_Height: 667 (0-667)
148 | - MEDIUM_Height: 1023 (668-1023)
149 | - LARGE_Height: 1365 (1024-1365)
150 | - XLARGE_Height: 1366+
151 |
152 | The preset values may be overridden with `setBreakPoints` which merges the parameter object with the defaults. Each cutoff specifies the upper end for that range. `XLARGE_Width` is inferred from anything above `LARGE_Width`. BreakPoints should be set early in the app such as in `index.js`. An example overriding the `SMALL_Width`, `MEDIUM_Width`, and `LARGE_Width` break points:
153 | ```
154 | import { setBreakPoints } from 'react-native-responsive-grid';
155 |
156 | setBreakPoints({
157 | SMALL_Width: 414,
158 | MEDIUM_Width: 600,
159 | LARGE_Width: 1024
160 | })
161 | ```
162 |
163 | ```jsx
164 |
165 |
184 |
185 |
186 |
187 | ```
188 |
189 | ### Example 5: FlatList + Row & Column Wrapping
190 |
191 | FlatList is a virtualized replacement for React Native's old ListView component. Using FlatList as a container is supported by this grid. This example also demonstrate wrapping Column content based on screen size. See ('size' prop under the [Props](https://github.com/idibidiart/react-native-responsive-grid#props) section.) It also demonstrates who to wrap Row content (e.g. child columns) based on screen size (also see [Example 4](https://github.com/idibidiart/react-native-responsive-grid#example-4))
192 |
193 | ```jsx
194 | import React, { Component } from 'react';
195 | import {
196 | FlatList,
197 | Text,
198 | ScrollView
199 | } from 'react-native';
200 |
201 | import { Row, Column as Col, Grid} from 'react-native-responsive-grid'
202 | import { MaterialIcons } from '@expo/vector-icons';
203 | import faker from 'faker';
204 |
205 | let j = 0
206 | const randomUsers = (count = 10) => {
207 | const arr = [];
208 | for (let i = 0; i < count; i++) {
209 | arr.push({
210 | key: faker.random.uuid(),
211 | date: faker.date.weekday(),
212 | name: faker.name.firstName(),
213 | job: faker.name.jobTitle(),
214 | index: j++
215 | })
216 | }
217 | return arr
218 | }
219 |
220 | export default class Home extends Component {
221 | state = {
222 | refreshing: false,
223 | data: randomUsers(10),
224 | };
225 |
226 | onEndReached = () => {
227 | const data = [
228 | ...this.state.data,
229 | ...randomUsers(10),
230 | ]
231 |
232 | this.setState(state => ({
233 | data
234 | }));
235 | };
236 |
237 | onRefresh = () => {
238 | this.setState({
239 | data: randomUsers(10),
240 | });
241 | }
242 |
243 | render() {
244 | return (
245 | {
254 | return (
255 |
256 |
257 |
258 |
259 | {String(item.date)}
260 |
261 |
262 |
263 |
264 |
265 | {item.job}
266 |
267 |
268 |
269 |
270 | {item.name}
271 |
272 |
273 |
274 |
275 | {item.index}
276 |
277 |
278 | )
279 | }}
280 | />
281 | )
282 | }
283 | }
284 | ```
285 |
286 | ## Components
287 |
288 | - Row: Flexbox View with flexDirection set to 'row' with convenient props and dynamic behavior.
289 |
290 | - Col: Flexbox View with flexDirection set to 'column' with convenient props and dynamic behavior.
291 |
292 | - Grid: an optional, stateful, component with style={{flex: 1}}. The Grid uses the children-as-funnction pattern and passes its state to its children, and allows state to be declared in its props, which will have the latest screen and grid info after orientation changes. It also passes it's render-triggering async setState method to its children.
293 |
294 | **Important:**
295 |
296 | **Grid component is required if you need to re-run the render() function in response to orientation change (many examples here)**
297 |
298 | **Grid component is also required if you use aspectRatio prop on Rows or Columns since the selection of content of the closest aspect ratio requires re-running the render function after orientation change.**
299 |
300 | Below is an example:
301 |
302 | ```jsx
303 | export const Home = () => (
304 |
309 | {({state, setState}) => (
310 | {/* possibly other JSX here */}
311 |
312 |
313 |
314 | {layout(state)}
315 |
316 |
317 |
318 | )}
319 | )
320 | ```
321 |
322 | ## Utils
323 |
324 | import { Row, Column as Col, ScreenInfo, Grid} from './grid'
325 |
326 | `ScreenInfo()` This will return the following data:
327 |
328 | ```js
329 | {
330 | mediaSize: mediaSizeWidth,
331 | mediaSizeWidth,
332 | mediaSizeHeight,
333 | width: SCREEN_WIDTH,
334 | height: SCREEN_HEIGHT,
335 | aspectRatio: {currentNearestRatio, currentOrientation}
336 | }
337 | ```
338 |
339 | - mediaSize is one of `sm`, `md`, `lg`, `xl` screen width categories and is aliased to mediaSizeWidth
340 | - mediaSizeHeight is the same but for screen height. It's used for hiding/showing Rows wit `hidden` prop based on screen height category and for Row `size` props.
341 |
342 | if `sizeOnly` is true it will drop aspectRatio and its 'nearest match' calculation (shaves a few ms)
343 |
344 | ## Methods
345 |
346 | Row and Column both have `.hide()` and `.show()` instance methods. The instance reference you get from a ref callback will have these methods. See Example #1 for usage.
347 |
348 | ## Instance Variables
349 |
350 | These are provided mainly for unit tests, except for componentInstance`.hidden` and componentInstance`.shown` which can be used to tell the state of the component.
351 |
352 | ## Props
353 |
354 | All props are case sensitive.
355 |
356 | `aspectRatio` (see [Example 3](https://github.com/idibidiart/react-native-responsive-grid#example-3))
357 |
358 | `size` may be supplied as prop to Column (width) or Row (height). This number defines the width of the column or height of a row as a percentage of its parent view's computed or explicit width or height, respectively.
359 |
360 | `smSize`, `mdSize`, `lgSize` and `xlSize` are device-dependent size values that are applied to Columns (which map to width percent) and Rows (which map to height percent.) In addition to their utility in deciding the size of content based on screen size (width in case of Columns and height in case of Rows), they may are also used for defining column wrapping behavior based on screen size. For example, Columns in as Row will wrap if Row width becomes smaller at smaller screen sizes.
361 |
362 | `sizePoints` may be supplied as prop to Column (which map to width points) or Row (which map to height points). This number defines the width of the column or height of a row as an asolute value in points.
363 |
364 | `smSizePoints`, `mdSizePoints`, `lgSizePoints`, and `xlSizePoints` are like their percentage-based equivalents but use point values.
365 |
366 | `offset` may be applied to Column. This number defines the marginLeft (or marginRight in csase of RTL mode) for the column as a percentage of its parent view's computed or explicitly set width. Offset values can also be negative. Default is 0.
367 |
368 | `smOffset`, `mdOffset`, `lgOffset` and `xlOffset` are device-dependent offset values that are applied to columns.
369 |
370 | `offsetPoints`, `mdOffsetPoints`, `lgOffsetPoints`, and `xlOffsetPoints` are like their percentage-based equivalents (i.e. applied to Column to produce offset) but use value in points instead of value in percent.
371 |
372 | _Using offset values in RTL mode moves things from right to left. Using them in normal LTR mode moves things from left to right. It's pretty normal to expect that. If you're working in both directions, this makes offsets more useful than using marginLeft or marginRight directly._
373 |
374 | _Specifying an offset value in normal LTR mode means marginLeft (if specified in style prop) will be overwritten by offset value. However, marginRight (if specified in style prop) will not be overwritten by the offset value. Specifying offset value in RTL mode means marginRight (if specified in style prop) will be overwritten by offset value. However, marginLeft (if specified in style prop) will not be overwritten by offset value._
375 |
376 | `smHidden`, `mdHidden`, `lgHidden` and `xlHidden` - may be applied to Column or Row which tells the parent Row or Column, respectively, to hide the affected child Column or child Row based on the current width (for child Columns) or height (for child Rows) of the screen.
377 |
378 | The screen-size-specific _size_ and _hidden_ props refer to the current screen width in case of Columns and current screen height in case of Rows, which changes with orientation. The _offset_ props only apply to Columns so they refer to the current screen width.
379 |
380 | The following are the device width (for Columns) and height (for Rows) thresholds for these props:
381 |
382 | The preset values may be overridden with `setBreakPoints` which merges the parameter object with the defaults. Each cutoff specifies the upper end for that range. `XLARGE_Width` is inferred from anything above `LARGE_Width`. BreakPoints should be set early in the app such as in `index.js`. An example overriding the `SMALL_Width`, `MEDIUM_Width`, and `LARGE_Width` break points:
383 | ```
384 | import { setBreakPoints } from 'react-native-responsive-grid';
385 |
386 | setBreakPoints({
387 | SMALL_Width: 414,
388 | MEDIUM_Width: 600,
389 | LARGE_Width: 1024
390 | })
391 | ```
392 |
393 | `vAlign` may be supplied as prop to Column to vertically align the elements and/or rows within it. Possible values are: `middle` | `center`, `top`, `bottom`, `space` and `distribute`. Default is top.
394 |
395 | `vAlign` may also be supplied as prop to Row to align the columns within it in the vertical direction. Possible values are: `top`, `middle` | `center`, `bottom`, `baseline` and `stretch`. Default is `stretch`.
396 |
397 | `hAlign` may be supplied as prop to Row to align its child Columns and/or elements within it in the horizontal direction. Possible values are: `center` | `middle`, `left`, `right`, `space` and `distribute`. Default is left.
398 |
399 | `hAlign` may also be supplied as prop to Column to align its child Rows and/or elements within it in the horizontal direction. Possible values are: `center` | `middle`, `left`, `right`, and `stretch`. Default is `stretch`.
400 |
401 | `rtl` may be supplied as prop to Row to both reverse the order of columns (or elements) inside a row as well as to set hAlign to 'right.' This is useful for right-to-left layouts.
402 |
403 | `fullHeight` may be supplied as prop to Row in place of size={100} or style={{height: '100%'}} -- note that Rows have 0 height and width by default, but a fullHeight Row inside of a fullWidth Column will have height and width of 100%
404 |
405 | `fullWidth` may be supplied as prop to Column in place of size={100} or style={{width: '100%'}} -- note that Columns have 0 height and width by default, but a fullWidth Column inside of a fullHeight Row will have height and width of 100%
406 |
407 | `alignLines` may be supplied as prop to Row to vertically align the wrapped lines within the Row (not to be confused with the items that are inside each line.) Possible values are: top, middle, bottom, space, distribute, stretch. (See section on Aligning Wrapped Lines within Rows)
408 |
409 | `alignSelf` maybe supplied as prop to Row to override the hAlign prop of the parent Column for that Row.
410 | Possible values are: `auto`, `left`, `right`, `center` | `middle`, `stretch`
411 |
412 | `alignSelf` maybe supplied as prop to Column to override the vAlign prop of the parent Row for that Column.
413 | Possible values are: `auto`, `top`, `bottom`, `middle` | `center`, `stretch`, `baseline`
414 |
415 | `noWrap` may be supplied as prop to Row prevent child elements from wrapping.
416 |
417 | ### Nesting
418 |
419 | If you're nesting a column inside a row which is inside another column that is inside another row as below:
420 |
421 | ```jsx
422 |
423 |
424 |
425 |
426 |
427 | This column is 25% of the outer view's width (or 25% of the screen width if
428 | the top level Row has no parent)
429 |
430 |
431 |
432 |
433 |
434 | ```
435 |
436 | The nested column's size will be the column size value (size, sm, md, lg, xl) as a percentage of the width of the preceding column in the hierarchy .
437 |
438 | This nested percentages model applies to offsets, too.
439 |
440 | ### RTL Support
441 |
442 | This is intended for right-to-left (RTL) layouts and apps that have their text in any of the following languages:
443 |
444 | - Arabic
445 | - Aramaic
446 | - Azeri
447 | - Dhivehi/Maldivian
448 | - Hebrew
449 | - Kurdish (Sorani)
450 | - Persian/Farsi
451 | - Urdu
452 |
453 | Notice the reversed order of the Text relative to the physical order in the markup. Also notice that columns are justified as flex-end within the row and their content is rightAligned (except for the second column which is explicitly leftAligned to mimic the rightAligned behavior in normal ltr layout)
454 |
455 |
456 |
457 | ### Normal LTR Markup
458 |
459 | ```jsx
460 |
461 |
462 |
463 | PREVIOUS ORDERS
464 |
465 |
466 |
467 |
468 | SEE ALL
469 |
470 |
471 |
472 | ```
473 |
474 | ### RTL Markup
475 |
476 | Notice the offset values work in RTL direction now. The addition of .7 offset is to mimic the fact that the left margin in the LTR layout is smaller than the right margin in that layout, whereas it's the opposite in the RTL direction. So the .7 offset is used in RTL layout instead of the 1 offset, so alignment is identical.
477 |
478 | ```jsx
479 |
480 |
481 |
482 | PREVIOUS ORDERS
483 |
484 |
485 |
486 |
487 | SEE ALL
488 |
489 |
490 |
491 | ```
492 |
493 | ### Utils
494 |
495 | You may import ScreenInfo from grid and invoke inside of render() of your component to get current screen diemsnions and orientation.
496 |
497 | ### Predictable, Dynamic Layout Behavior
498 |
499 | Being able to readt to layout changes, including changes due to device rotation (for apps that allow it), is a key aspect of responsive design. This grid is designed to enable dynamic response to layout changes (see the demos at the start of this Readme)
500 |
501 | Columns and Rows have `position: 'relative'` by default to keep them within the layout flow, but they can have `position: 'absolute'` specified in style prop, for overlays and such.
502 |
503 | The Grid component is a stateful top-level component (at root, above ScrollView, ListView, FlatList et al but below a Modal and Drawer) Grid should not be inside another Grid and it is only needed if you wish to respond to orientation and layout changes by re-running the render() function. It uses the children-as-funnction pattern to pass its state, including its dimensions and any user-defined state, along with screen dimensions, to its children. The user may define Grid state in its props. The Grid also passes it's async render-causing setState method to its children.
504 |
505 | ## More Examples
506 |
507 | ```jsx
508 | import {Column as Col, Row} from 'react-native-responsive-grid';
509 |
510 |
511 |
512 | First Column
513 |
514 |
515 | ```
516 |
517 | In the example above, on a phone in portrait mode, the Column would take up 50% of the row's computed width. On a phone in landscape nmode or a normal tablet the Column would take up 33.333% of the row's width. On a big tablet the Column would take up 25% of the row's width.
518 |
519 | ```jsx
520 | import {Column as Col, Row} from 'react-native-responsive-grid';
521 |
522 |
523 |
524 | test
525 |
526 |
527 | ```
528 |
529 | In the example above, the text "test" will move further to the right with larger screen sizes.
530 |
531 | ```jsx
532 | import {Column as Col, Row} from 'react-native-responsive-grid';
533 |
534 |
535 |
536 | Column displayed when width is <= 480
537 |
538 |
539 | Column displayed when width is > 480
540 |
541 |
542 | ```
543 |
544 | In the example above, the column and all of it's children will be hidden on small screens like phones, but it will appear on bigger screens like tablets. The size-prefixed 'hidden' props may be applied to columns. Hidden props are all booleans. They default to false.
545 |
546 | ## More Examples
547 |
548 | - [Responsive Layout](https://github.com/idibidiart/react-native-responsive-grid/blob/master/EvenMoreExamples.md#responsive-layout)
549 | - [Custom Components](https://github.com/idibidiart/react-native-responsive-grid/blob/master/EvenMoreExamples.md#custom-components)
550 | - [Wrapped Alignment](https://github.com/idibidiart/react-native-responsive-grid/blob/master/EvenMoreExamples.md#wrapped-alignment)
551 |
552 | ## History
553 |
554 | Before React Native v0.42 we didn't have a performant, declarative way of specifying percentage-based dimensions. Then came React Native v0.42 which gave us that ability. Since then several open source contributors have made responsive grids that take advantage of this new capability. This "grid" takes one of the simplest and most well-thought-out ones, namely, `react-native-flexbox-grid` (by @rundmt), and modifies it heavily to produce a simple yet powerful layout model that we can use to implement responsive and adaptive behavior.
555 |
556 | # Gridism
557 |
558 | ## _When I first made a grid I happened to be thinking of the innocence of trees and then this grid came into my mind and I thought it represented innocence, and I still do, and so I painted it and then I was satisfied. I thought, this is my vision._ --[Agnes Martin](https://www.guggenheim.org/arts-curriculum/topic/grids)
559 |
560 |
561 | ## Contributors
562 |
563 | This project exists thanks to all the people who contribute. [[Contribute]](CONTRIBUTING.md).
564 |
565 |
566 |
567 | ## Backers
568 |
569 | Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/react-native-responsive-grid#backer)]
570 |
571 |
572 |
573 |
574 | ## Sponsors
575 |
576 | Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/react-native-responsive-grid#sponsor)]
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
--------------------------------------------------------------------------------
/UniversalPinterestLayout.md:
--------------------------------------------------------------------------------
1 | ## Universal, Responsive Pinterest Layout
2 |
3 | ```jsx
4 | import React, { Component} from 'react'
5 |
6 | import {
7 | View,
8 | Text,
9 | Image,
10 | StyleSheet,
11 | ScrollView,
12 | ImageBackground
13 | } from 'react-native'
14 |
15 | import { Row, Column as Col, ScreenInfo, Grid} from './grid'
16 |
17 | // column width (relative to screen size)
18 | const sizes = {sm: 100, md: 50, lg: 25, xl: 20}
19 |
20 | const layout = (state) => {
21 |
22 | const numCols = Math.floor(100/sizes[ScreenInfo().mediaSize])
23 | const numRows = Math.ceil(data.length / numCols)
24 | const colWidth = state.layout.grid ? state.layout.grid.width / numCols : 0
25 |
26 | let layoutMatrix = [], layoutCols = []
27 |
28 | for (let col = 0; col < numCols; col++) {
29 | layoutMatrix.push([])
30 | for (let row = 0, i = col; row < numRows; row++, i += numCols) {
31 | if (data[i])
32 | layoutMatrix[col].push(
33 |
43 | )
44 | }
45 | layoutCols.push(
46 |