Skip to content

Commit d43184c

Browse files
authored
Merge pull request #1625 from StoDevX/webcams-two-column-android
Fix column layout in Webcams list
2 parents 9225bb2 + ccf7f26 commit d43184c

File tree

1 file changed

+55
-46
lines changed

1 file changed

+55
-46
lines changed

source/views/streaming/webcams.js

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@
55
*/
66

77
import React from 'react'
8-
import {StyleSheet, View, Text, FlatList, Image, Platform} from 'react-native'
8+
import {
9+
StyleSheet,
10+
View,
11+
Text,
12+
ScrollView,
13+
Image,
14+
Platform,
15+
Dimensions,
16+
} from 'react-native'
917
import delay from 'delay'
1018
import {reportNetworkProblem} from '../../lib/report-network-problem'
1119
import {TabBarIcon} from '../components/tabbar-icon'
@@ -15,6 +23,8 @@ import * as defaultData from '../../../docs/webcams.json'
1523
import {webcamImages} from '../../../images/webcam-images'
1624
import {trackedOpenUrl} from '../components/open-url'
1725
import LinearGradient from 'react-native-linear-gradient'
26+
import {Column} from '../components/layout'
27+
import {partitionByIndex} from '../../lib/partition-by-index'
1828

1929
const transparentPixel = require('../../../images/transparent.png')
2030
const GITHUB_URL = 'https://stodevx.github.io/AAO-React-Native/webcams.json'
@@ -32,6 +42,7 @@ type WebcamType = {
3242
type Props = {}
3343

3444
type State = {
45+
width: number,
3546
webcams: Array<WebcamType>,
3647
loading: boolean,
3748
refreshing: boolean,
@@ -44,15 +55,25 @@ export class WebcamsView extends React.PureComponent<void, Props, State> {
4455
}
4556

4657
state = {
58+
width: Dimensions.get('window').width,
4759
webcams: defaultData.data,
4860
loading: false,
4961
refreshing: false,
5062
}
5163

5264
componentWillMount() {
65+
Dimensions.addEventListener('change', this.handleResizeEvent)
5366
this.fetchData()
5467
}
5568

69+
componentWillUnmount() {
70+
Dimensions.removeEventListener('change', this.handleResizeEvent)
71+
}
72+
73+
handleResizeEvent = (event: {window: {width: number}}) => {
74+
this.setState(() => ({width: event.window.width}))
75+
}
76+
5677
refresh = async () => {
5778
const start = Date.now()
5879
this.setState(() => ({refreshing: true}))
@@ -83,32 +104,33 @@ export class WebcamsView extends React.PureComponent<void, Props, State> {
83104
this.setState(() => ({webcams, loading: false}))
84105
}
85106

86-
renderItem = ({item}: {item: WebcamType}) =>
87-
<StreamThumbnail key={item.name} webcam={item} />
88-
89-
keyExtractor = (item: WebcamType) => item.name
90-
91107
render() {
108+
const columns = partitionByIndex(this.state.webcams)
109+
92110
return (
93-
<FlatList
94-
keyExtractor={this.keyExtractor}
95-
renderItem={this.renderItem}
96-
refreshing={this.state.refreshing}
97-
onRefresh={this.refresh}
98-
data={this.state.webcams}
99-
numColumns={2}
100-
columnWrapperStyle={styles.row}
101-
contentContainerStyle={styles.container}
102-
/>
111+
<ScrollView contentContainerStyle={styles.container}>
112+
{columns.map((contents, i) =>
113+
<Column key={i} style={styles.column}>
114+
{contents.map(webcam =>
115+
<StreamThumbnail
116+
key={webcam.name}
117+
webcam={webcam}
118+
viewportWidth={this.state.width}
119+
/>,
120+
)}
121+
</Column>,
122+
)}
123+
</ScrollView>
103124
)
104125
}
105126
}
106127

107-
class StreamThumbnail extends React.PureComponent {
108-
props: {
109-
webcam: WebcamType,
110-
}
128+
type ThumbnailProps = {
129+
webcam: WebcamType,
130+
viewportWidth: number,
131+
}
111132

133+
class StreamThumbnail extends React.PureComponent<void, ThumbnailProps, void> {
112134
handlePress = () => {
113135
const {streamUrl, name, pageUrl} = this.props.webcam
114136
if (Platform.OS === 'ios') {
@@ -121,18 +143,17 @@ class StreamThumbnail extends React.PureComponent {
121143
}
122144

123145
render() {
124-
const {
125-
name,
126-
thumbnail,
127-
accentColor,
128-
textColor,
129-
thumbnailUrl,
130-
} = this.props.webcam
146+
const {viewportWidth, webcam} = this.props
147+
const {name, thumbnail, accentColor, textColor, thumbnailUrl} = webcam
131148

132149
const [r, g, b] = accentColor
133150
const baseColor = `rgba(${r}, ${g}, ${b}, 1)`
134151
const startColor = `rgba(${r}, ${g}, ${b}, 0.1)`
135152

153+
const width = viewportWidth / 2 - CELL_MARGIN * 1.5
154+
const cellRatio = 2.15625
155+
const height = width / cellRatio
156+
136157
const img = thumbnailUrl
137158
? {uri: thumbnailUrl}
138159
: webcamImages.hasOwnProperty(thumbnail)
@@ -145,9 +166,8 @@ class StreamThumbnail extends React.PureComponent {
145166
underlayColor={baseColor}
146167
activeOpacity={0.7}
147168
onPress={this.handlePress}
148-
containerStyle={styles.cell}
149169
>
150-
<Image source={img} style={styles.image}>
170+
<Image source={img} style={[styles.image, {width, height}]}>
151171
<View style={styles.titleWrapper}>
152172
<LinearGradient
153173
colors={[startColor, baseColor]}
@@ -168,27 +188,16 @@ const CELL_MARGIN = 10
168188

169189
const styles = StyleSheet.create({
170190
container: {
171-
marginVertical: CELL_MARGIN / 2,
191+
padding: CELL_MARGIN / 2,
192+
flexDirection: 'row',
172193
},
173-
row: {
174-
justifyContent: 'center',
175-
marginHorizontal: CELL_MARGIN / 2,
176-
},
177-
cell: {
194+
column: {
178195
flex: 1,
179-
overflow: 'hidden',
180-
margin: CELL_MARGIN / 2,
181-
justifyContent: 'center',
182-
183-
elevation: 2,
184-
185-
// TODO: Android doesn't currently (0.42) respect both
186-
// overflow:hidden and border-radius.
187-
borderRadius: Platform.OS === 'android' ? 0 : 6,
196+
alignItems: 'center',
188197
},
189198
image: {
190-
width: '100%',
191-
height: '100%',
199+
margin: CELL_MARGIN / 2,
200+
borderRadius: 6,
192201
},
193202
titleWrapper: {
194203
flex: 1,

0 commit comments

Comments
 (0)