@@ -9,34 +9,46 @@ import {
99 ViewStyle ,
1010 StyleProp ,
1111 ImageStyle ,
12+ NativeSyntheticEvent ,
13+ ImageLoadEventData ,
14+ ImageErrorEventData ,
15+ ActivityIndicator ,
16+ Text ,
1217} from 'react-native' ;
18+ import Icon from '../Icon' ;
1319
1420export type ImageProps = RNImageProps & {
1521 Component ?: typeof React . Component ;
1622 onPress ?( ) : void ;
1723 onLongPress ?( ) : void ;
18- ImageComponent ?: React . ComponentType < any > ;
24+ ImageComponent ?: React . ComponentType < ImageProps > ;
1925 PlaceholderContent ?: React . ReactElement < any > ;
2026 containerStyle ?: StyleProp < ViewStyle > ;
2127 childrenContainerStyle ?: StyleProp < ViewStyle > ;
2228 placeholderStyle ?: StyleProp < ViewStyle > ;
2329 transition ?: boolean ;
2430 transitionDuration ?: number ;
31+ disabled ?: boolean ;
2532 children ?: React . ReactNode ;
2633} ;
2734
2835type ImageState = {
2936 placeholderOpacity : Animated . Value ;
37+ isLoading : boolean ;
38+ hasError : boolean ;
3039} ;
3140
3241export default function TransitionImage ( props : ImageProps & Partial < ImageProps > ) {
33- const [ state , _ ] = useState < ImageState > ( {
42+ const [ state , setState ] = useState < ImageState > ( {
3443 placeholderOpacity : new Animated . Value ( 1 ) ,
44+ isLoading : true ,
45+ hasError : false ,
3546 } ) ;
3647
37- const onLoad = ( e : any ) => {
48+ const onLoad = ( e : NativeSyntheticEvent < ImageLoadEventData > ) => {
3849 const { transition, onLoad, transitionDuration } = props ;
3950 if ( ! transition ) {
51+ setState ( { ...state , isLoading : false } ) ;
4052 state . placeholderOpacity . setValue ( 0 ) ;
4153 return ;
4254 }
@@ -46,9 +58,14 @@ export default function TransitionImage(props: ImageProps & Partial<ImageProps>)
4658 duration : transitionDuration ,
4759 useNativeDriver : true ,
4860 } ) . start ( ) ;
61+ setState ( { ...state , isLoading : false } ) ;
4962 onLoad && onLoad ( e ) ;
5063 } ;
5164
65+ const onError = ( e : NativeSyntheticEvent < ImageErrorEventData > ) => {
66+ setState ( { ...state , isLoading : false , hasError : true } ) ;
67+ } ;
68+
5269 const {
5370 onPress,
5471 onLongPress,
@@ -60,25 +77,42 @@ export default function TransitionImage(props: ImageProps & Partial<ImageProps>)
6077 style = { } ,
6178 ImageComponent = ImageNative ,
6279 children,
80+ disabled = false ,
6381 ...attributes
6482 } = props ;
6583
6684 const hasImage = Boolean ( attributes . source ) ;
6785 const { width, height, ...styleProps } = StyleSheet . flatten ( style ) ;
6886
87+ const PlaceholderContentLoading = (
88+ < View style = { styles . errorContainer } >
89+ < ActivityIndicator />
90+ < Text style = { { color : '#fff' , marginTop : 8 } } > 加载中...</ Text >
91+ </ View >
92+ ) ;
93+
94+ const PlaceholderContentError = (
95+ < View style = { styles . errorContainer } >
96+ < Icon name = "circle-close-o" color = "#fff" size = { 24 } />
97+ < Text style = { { color : '#fff' , marginTop : 8 } } > 加载失败</ Text >
98+ </ View >
99+ ) ;
100+
69101 return (
70102 < Component
71103 onPress = { onPress }
72104 onLongPress = { onLongPress }
73105 accessibilityIgnoresInvertColors = { true }
74106 style = { StyleSheet . flatten ( [ styles . container , containerStyle ] ) }
107+ disabled = { disabled || state . isLoading || state . hasError }
75108 >
76109 < ImageComponent
77110 testID = "RNE__Image"
78111 transition = { true }
79112 transitionDuration = { 360 }
80113 { ...attributes }
81114 onLoad = { onLoad }
115+ onError = { onError }
82116 style = { StyleSheet . flatten ( [
83117 StyleSheet . absoluteFill ,
84118 {
@@ -104,7 +138,9 @@ export default function TransitionImage(props: ImageProps & Partial<ImageProps>)
104138 testID = "RNE__Image__placeholder"
105139 style = { StyleSheet . flatten ( [ style , styles . placeholder , placeholderStyle ] ) }
106140 >
107- { PlaceholderContent }
141+ { state . isLoading && PlaceholderContentLoading }
142+ { state . hasError && PlaceholderContentError }
143+ { ! state . isLoading && ! state . hasError && PlaceholderContent }
108144 </ View >
109145 </ Animated . View >
110146
@@ -137,4 +173,13 @@ const styles = StyleSheet.create({
137173 alignItems : 'center' ,
138174 justifyContent : 'center' ,
139175 } ,
176+ errorContainer : {
177+ display : 'flex' ,
178+ flexDirection : 'column' ,
179+ alignItems : 'center' ,
180+ justifyContent : 'center' ,
181+ backgroundColor : 'rgba(50, 50, 51, .88)' ,
182+ height : '100%' ,
183+ width : '100%' ,
184+ } ,
140185} ) ;
0 commit comments