Skip to content

Commit c213455

Browse files
committed
Update demo
1 parent 48ba554 commit c213455

File tree

4 files changed

+83
-68
lines changed

4 files changed

+83
-68
lines changed

demo/App.tsx

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,89 +12,87 @@ import {
1212
SafeAreaView,
1313
StatusBar,
1414
StyleSheet,
15-
Text,
1615
useColorScheme,
1716
View,
1817
TouchableOpacity,
18+
Image,
19+
Dimensions,
20+
ScrollView,
1921
} from 'react-native';
2022

2123
import {Colors} from 'react-native/Libraries/NewAppScreen';
2224
import axios from 'axios';
2325
import ImageViewer from './components/ImageViewer';
2426

27+
const WIDTH = Dimensions.get('window').width;
28+
2529
const App: () => Node = () => {
2630
const isDarkMode = useColorScheme() === 'dark';
27-
const imageViewerRef = React.createRef();
31+
const [images, setImages] = React.useState([]);
32+
const [visible, setVisible] = React.useState(false);
33+
const [showIndex, setShowIndex] = React.useState(0);
2834

2935
const backgroundStyle = {
3036
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
3137
flex: 1,
3238
};
3339

34-
function showImageViewer() {
40+
React.useEffect(() => {
3541
axios
3642
.get('https://picsum.photos/v2/list?limit=20')
3743
.then((res: any) => res.data)
3844
.then((res: any) => {
39-
const images = res.map((item: any) => ({
40-
// width: item.width,
41-
// height: item.height,
42-
// url: item.download_url,
45+
const imagesMap = res.map((item: any) => ({
4346
title: item.author,
4447
source: {
4548
uri: item.download_url,
4649
headers: {
4750
'X-Test': 'foo',
4851
},
49-
// width: item.width,
50-
// height: item.height,
52+
width: item.width,
53+
height: item.height,
5154
},
5255
}));
53-
54-
imageViewerRef.current.show(
55-
images,
56-
Math.floor(Math.random() * images.length - 1),
57-
);
56+
setImages(imagesMap);
5857
});
58+
}, []);
59+
60+
function onImagePress(index: number) {
61+
setShowIndex(index);
62+
setVisible(true);
5963
}
6064

6165
return (
6266
<SafeAreaView style={backgroundStyle}>
6367
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
64-
<View style={styles.container}>
65-
<TouchableOpacity
66-
onPress={() => showImageViewer()}
67-
hitSlop={{top: 20, left: 20, right: 20, bottom: 20}}>
68-
<View style={styles.button}>
69-
<Text style={styles.buttonText}>Show</Text>
70-
</View>
71-
</TouchableOpacity>
72-
</View>
73-
<ImageViewer ref={imageViewerRef} debug />
68+
<ScrollView>
69+
{images.map((image, index) => (
70+
<TouchableOpacity
71+
activeOpacity={0.8}
72+
key={index}
73+
onPress={() => onImagePress(index)}>
74+
<View>
75+
<Image source={image.source} style={styles.image} />
76+
</View>
77+
</TouchableOpacity>
78+
))}
79+
</ScrollView>
80+
<ImageViewer
81+
images={images}
82+
initialIndex={showIndex}
83+
visible={visible}
84+
onClose={() => setVisible(false)}
85+
animationType="slide"
86+
debug
87+
/>
7488
</SafeAreaView>
7589
);
7690
};
7791

7892
const styles = StyleSheet.create({
79-
container: {
80-
flex: 1,
81-
justifyContent: 'center',
82-
alignItems: 'center',
83-
backgroundColor: Colors.lighter,
84-
},
85-
button: {
86-
paddingHorizontal: 50,
87-
paddingVertical: 15,
88-
borderWidth: 1,
89-
borderColor: '#2985c6',
90-
borderRadius: 10,
91-
backgroundColor: '#2577b1',
92-
},
93-
buttonText: {
94-
fontSize: 15,
95-
textTransform: 'uppercase',
96-
fontWeight: '600',
97-
color: '#fff',
93+
image: {
94+
width: WIDTH,
95+
height: 360,
9896
},
9997
});
10098

demo/components/ImageViewer/Image.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import {
1919
PinchGestureHandler,
2020
State,
2121
GestureEvent,
22-
TouchableWithoutFeedback,
2322
} from 'react-native-gesture-handler';
2423
import {ImageComponentOptionalProps, ImageComponentProps, ImageComponentState} from './types';
2524

@@ -63,7 +62,11 @@ class Image extends React.Component<ImageComponentProps, ImageComponentState> {
6362

6463
this._panResponder = PanResponder.create({
6564
onStartShouldSetPanResponder: onShouldSetPanResponder,
66-
onMoveShouldSetPanResponder: onShouldSetPanResponder,
65+
onStartShouldSetPanResponderCapture: () => true,
66+
67+
onMoveShouldSetPanResponder: () => true,
68+
onMoveShouldSetPanResponderCapture: () => true,
69+
6770
onPanResponderTerminate: onPanEnd,
6871
onPanResponderRelease: onPanEnd,
6972
onPanResponderMove: onPanMove,
@@ -100,7 +103,7 @@ class Image extends React.Component<ImageComponentProps, ImageComponentState> {
100103
if (Math.abs(gesture.dx) > Math.abs(gesture.dy)) {
101104
this.props.toggleEnableScroll(true);
102105

103-
return;
106+
return false;
104107
}
105108

106109
this.props.toggleEnableScroll(false);
@@ -315,7 +318,11 @@ class Image extends React.Component<ImageComponentProps, ImageComponentState> {
315318

316319
return (
317320
<Animated.View style={headerAnim}>
318-
<Text style={{color: '#fff'}}>{`${this.props.imageIndex + 1}/${this.props.imageTotal}`}</Text>
321+
{this.props.imagesTotal > 1 && (
322+
<View style={styles.headerCount}>
323+
<Text style={styles.defaultText}>{`${this.props.imageIndex + 1}/${this.props.imagesTotal}`}</Text>
324+
</View>
325+
)}
319326
</Animated.View>
320327
);
321328
};
@@ -463,6 +470,11 @@ const styles = StyleSheet.create({
463470
defaultText: {
464471
color: '#fff',
465472
},
473+
headerCount: {
474+
backgroundColor: '#131313',
475+
padding: 10,
476+
borderRadius: 10,
477+
},
466478
});
467479

468480
export default Image;

demo/components/ImageViewer/index.tsx

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
11
import React from 'react';
2-
import {Modal, Dimensions, VirtualizedList} from 'react-native';
2+
import {Modal, Dimensions, VirtualizedList, View} from 'react-native';
33
import Image from './Image';
44
import {ImageViewerImageProps, ImageViewerComponentProps, ImageViewerComponentState, SwipeDirection} from './types';
55

66
const SCREEN_WIDTH = Dimensions.get('window').width;
77

88
class ImageViewer extends React.Component<ImageViewerComponentProps, ImageViewerComponentState> {
99
state: ImageViewerComponentState = {
10-
visible: false,
11-
images: [],
1210
scrollEnabled: true,
13-
startIndex: 0,
1411
};
15-
private _scrollRef: {current: VirtualizedList<any> | null} = React.createRef();
12+
static defaultProps = {
13+
animationType: 'none',
14+
};
1615

17-
public show(images: ImageViewerImageProps[], startIndex: number = 0) {
18-
this.setState({images, visible: true, startIndex});
19-
}
16+
private _scrollRef: {current: any} = React.createRef();
2017

21-
private _closeInternal = () => this.setState({visible: false});
18+
private _closeInternal = () => this.props.onClose();
2219
private _renderImage = (info: {item: ImageViewerImageProps; index: number}) => (
2320
<Image
2421
source={info.item.source}
2522
title={info.item.title}
2623
onClose={this._closeInternal}
27-
toggleEnableScroll={(enabled: boolean) => this.setState({scrollEnabled: enabled})}
24+
toggleEnableScroll={this._handleToggleScrollState}
2825
imageIndex={info.index}
29-
imageTotal={this._getItemCount()}
26+
imagesTotal={this._getItemCount()}
3027
// extendable props
3128
debug={this.props.debug}
3229
initialWidth={this.props.imageProps?.initialWidth}
@@ -35,36 +32,42 @@ class ImageViewer extends React.Component<ImageViewerComponentProps, ImageViewer
3532
/>
3633
);
3734

38-
private _getItemCount = () => this.state.images.length;
35+
private _handleToggleScrollState = (enabled: boolean) => {
36+
this.setState({scrollEnabled: enabled});
37+
};
38+
39+
private _getItemCount = () => this.props.images.length;
3940
private _getItem = (data: any, index: number) => data[index];
4041
private _getItemLayout = (_data: any, index: number) => ({
4142
length: SCREEN_WIDTH,
4243
offset: SCREEN_WIDTH * index,
4344
index,
4445
});
4546

46-
private _keyExtractor = (item: ImageViewerImageProps, index: number) => `${index}`;
47+
private _keyExtractor = (_item: ImageViewerImageProps, index: number) => `${index}`;
4748

4849
render() {
4950
return (
50-
<Modal visible={this.state.visible} transparent animationType="none" onRequestClose={this._closeInternal}>
51+
<Modal visible={this.props.visible} transparent animationType={this.props.animationType} onRequestClose={this._closeInternal}>
5152
<VirtualizedList
5253
horizontal
5354
showsHorizontalScrollIndicator={false}
5455
windowSize={2}
55-
data={this.state.images}
56+
data={this.props.images}
5657
renderItem={this._renderImage}
5758
keyExtractor={this._keyExtractor}
5859
getItemCount={this._getItemCount}
5960
getItem={this._getItem}
6061
getItemLayout={this._getItemLayout}
61-
scrollEnabled={this.state.scrollEnabled}
62+
scrollEnabled
6263
ref={this._scrollRef}
6364
removeClippedSubviews={true}
6465
maxToRenderPerBatch={2}
6566
initialNumToRender={2}
6667
pagingEnabled
67-
initialScrollIndex={this.state.startIndex}
68+
initialScrollIndex={this.props.initialIndex !== undefined ? this.props.initialIndex : 0}
69+
listKey={'RNImageViewer'}
70+
disableScrollViewPanResponder={!this.state.scrollEnabled}
6871
/>
6972
</Modal>
7073
);

demo/components/ImageViewer/types.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export interface ImageComponentProps extends ImageComponentOptionalProps {
1414
toggleEnableScroll: (enabled: boolean) => void;
1515

1616
imageIndex: number;
17-
imageTotal: number;
17+
imagesTotal: number;
1818
}
1919
export interface ImageComponentOptionalProps {
2020
// optional
@@ -37,10 +37,12 @@ export interface ImageComponentState {
3737
export interface ImageViewerComponentProps {
3838
debug?: boolean;
3939
imageProps?: ImageComponentOptionalProps;
40+
animationType?: 'slide' | 'fade' | 'none';
41+
images: ImageViewerImageProps[];
42+
visible: boolean;
43+
initialIndex?: number;
44+
onClose: () => void;
4045
}
4146
export interface ImageViewerComponentState {
42-
visible: boolean;
43-
images: ImageViewerImageProps[];
4447
scrollEnabled: boolean;
45-
startIndex: number;
4648
}

0 commit comments

Comments
 (0)