Skip to content

Commit da1b03c

Browse files
OleksandrRiabtsevOleksandrRiethanshar
authored
Add GridView and GridListItem component (#1451)
* Add GridView and GridListItem component. Implement example GridViewScreen.tsx and add to demo app * Update src/components/GridListItem/index.tsx Co-authored-by: Ethan Sharabi <[email protected]> * Update src/components/GridListItem/index.tsx Co-authored-by: Ethan Sharabi <[email protected]> * Rename imageProps prop into GridListItem Co-authored-by: OleksandrRi <[email protected]> Co-authored-by: Ethan Sharabi <[email protected]>
1 parent f89f595 commit da1b03c

File tree

6 files changed

+739
-1
lines changed

6 files changed

+739
-1
lines changed

demo/src/screens/MenuStructure.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ export const navigationData = {
111111
tags: 'scroll fader',
112112
screen: 'unicorn.components.FaderScreen'
113113
},
114-
{title: 'Wizard', tags: 'wizard', screen: 'unicorn.components.WizardScreen'}
114+
{title: 'Wizard', tags: 'wizard', screen: 'unicorn.components.WizardScreen'},
115+
{title: 'GridView', tags: 'grid view', screen: 'unicorn.components.GridViewScreen'}
115116
]
116117
},
117118
Native: {
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
import _ from 'lodash';
2+
import {View, Text, Colors, Constants, Avatar} from 'react-native-ui-lib';
3+
import React, {Component} from 'react';
4+
import {Alert, ScrollView} from 'react-native';
5+
import GridView from '../../../../src/components/GridView';
6+
import conversations from '../../data/conversations';
7+
import products from '../../data/products';
8+
9+
10+
class GridViewScreen extends Component {
11+
state = {
12+
contacts: _.chain(conversations)
13+
.take(15)
14+
.map(contact => ({
15+
imageProps: {source: {uri: contact.thumbnail}, borderRadius: 999},
16+
title: _.split(contact.name, ' ')[0],
17+
onPress: () => Alert.alert('My name is ' + contact.name)
18+
}))
19+
.value(),
20+
products: _.chain(products)
21+
.take(8)
22+
.map((product, index) => ({
23+
imageProps: {source: {uri: product.mediaUrl}, borderRadius: 4},
24+
title: product.name,
25+
titleTypography: 'subtextBold',
26+
onPress: () => Alert.alert('My price is ' + product.formattedPrice),
27+
renderOverlay: () => {
28+
if (index < 7) {
29+
return (
30+
<Text
31+
text={product.price}
32+
style={{alignSelf: 'center', marginTop: 3}}
33+
/>
34+
);
35+
}
36+
}
37+
}))
38+
.value(),
39+
pairs: _.chain(products)
40+
.take(2)
41+
.map(product => ({
42+
imageProps: {source: {uri: product.mediaUrl}},
43+
title: product.name,
44+
subtitle: (
45+
<Text>
46+
<Text style={{textDecorationLine: 'line-through', color: Colors.grey30}}>{product.formattedPrice}</Text>
47+
<Text style={{textDecorationLine: 'none'}}> $50</Text>
48+
</Text>
49+
),
50+
description: product.inventory.status,
51+
descriptionLines: 2,
52+
alignToStart: true,
53+
onPress: () => Alert.alert('My price was ' + product.formattedPrice + ', now it is $50')
54+
}))
55+
.value(),
56+
dynamicLayout: _.chain(products)
57+
.take(2)
58+
.map(product => ({
59+
imageProps: {
60+
source: {
61+
uri: product.mediaUrl
62+
}
63+
},
64+
itemSize: {height: 70},
65+
title: 'Title',
66+
subtitle: 'subtitle',
67+
description: product.name,
68+
descriptionLines: 2,
69+
alignToStart: true,
70+
onPress: () => Alert.alert('Click!')
71+
}))
72+
.value(),
73+
overlayText: _.chain(products)
74+
.take(2)
75+
.map((product, index) => ({
76+
imageProps: {
77+
source: {
78+
uri: product.mediaUrl
79+
}
80+
},
81+
itemSize: {height: 240},
82+
overlayText: true,
83+
title: product.name,
84+
subtitle: (
85+
<Text>
86+
<Text style={{textDecorationLine: 'line-through', color: Colors.grey30}}>{product.formattedPrice}</Text>
87+
<Text style={{textDecorationLine: 'none'}}>{product.formattedPrice}</Text>
88+
</Text>
89+
),
90+
description: '4 items',
91+
descriptionLines: 2,
92+
alignToStart: true,
93+
onPress: () => Alert.alert('My price was ' + product.formattedPrice + ', now it is $50'),
94+
renderOverlay: () => {
95+
if (index === 0) {
96+
return (
97+
<Text
98+
margin-10 text80BO
99+
style={{alignSelf: 'flex-start', marginTop: 12, marginLeft: 12}}
100+
>{product.formattedPrice}</Text>
101+
);
102+
}
103+
}
104+
}))
105+
.value(),
106+
avatars: _.chain(conversations)
107+
.take(9)
108+
.map((item) => ({
109+
renderCustomItem: () => {
110+
const imageElementElement = item.thumbnail;
111+
return (
112+
<View flex center marginB-10>
113+
<Avatar size={100} source={{uri: imageElementElement}}/>
114+
</View>
115+
);
116+
},
117+
onPress: () => Alert.alert('Your choose is ' + item.name),
118+
title: item.name,
119+
titleLines: 2,
120+
titleTypography: 'bodySmall'
121+
}))
122+
.value(),
123+
orientation: Constants.orientation
124+
};
125+
126+
onLayout = () => {
127+
if (this.state.orientation !== Constants.orientation) {
128+
// Basically just for triggering render - can be any other variable
129+
// (Constants.orientation is already up-to-date and can be used directly)
130+
this.setState({
131+
orientation: Constants.orientation
132+
});
133+
}
134+
};
135+
136+
render() {
137+
const {contacts, dynamicLayout, overlayText, avatars, products, pairs} = this.state;
138+
139+
return (
140+
<ScrollView onLayout={this.onLayout}>
141+
<View padding-page>
142+
<Text center text60BO>
143+
GridView
144+
</Text>
145+
146+
<Text margin-30 text60BO>
147+
Avatars
148+
</Text>
149+
<GridView
150+
items={contacts}
151+
// viewWidth={300}
152+
numColumns={5}
153+
lastItemOverlayColor={Colors.primary}
154+
lastItemLabel={7}
155+
/>
156+
157+
<Text margin-30 text60BO>
158+
Thumbnails
159+
</Text>
160+
<GridView
161+
items={products}
162+
numColumns={4}
163+
lastItemOverlayColor={Colors.primary}
164+
lastItemLabel={42}
165+
keepItemSize
166+
/>
167+
168+
<Text margin-30 text60BO>
169+
Pairs
170+
</Text>
171+
<GridView
172+
items={pairs}
173+
numColumns={2}
174+
useCustomTheme
175+
/>
176+
<Text margin-30 text60BO>
177+
Dynamic itemSize
178+
</Text>
179+
<GridView
180+
items={dynamicLayout}
181+
numColumns={2}
182+
useCustomTheme
183+
/>
184+
<Text margin-30 text60BO>
185+
OverlayText
186+
</Text>
187+
<GridView
188+
items={overlayText}
189+
numColumns={2}
190+
useCustomTheme
191+
/>
192+
<Text margin-30 text60BO>
193+
Custom content (Avatars)
194+
</Text>
195+
<GridView items={avatars} numColumns={Constants.orientation === 'landscape' ? 6 : 3}/>
196+
</View>
197+
</ScrollView>
198+
);
199+
}
200+
}
201+
202+
export default GridViewScreen;

demo/src/screens/componentScreens/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export function registerScreens(registrar) {
5656
registrar('unicorn.components.DateTimePickerScreen', () => require('./DateTimePickerScreen').default);
5757
registrar('unicorn.components.ViewScreen', () => require('./ViewScreen').default);
5858
registrar('unicorn.components.WizardScreen', () => require('./WizardScreen').default);
59+
registrar('unicorn.components.GridViewScreen', () => require('./GridViewScreen').default);
5960
// List Components
6061
registrar('unicorn.lists.BasicListScreen', () => require('./BasicListScreen').default);
6162
registrar('unicorn.lists.ContactsListScreen', () => require('./ContactsListScreen').default);

0 commit comments

Comments
 (0)