Skip to content

Commit 45fa1b3

Browse files
committed
1. 新增图片加载动画和图片加载失败的效果
1 parent beef9c6 commit 45fa1b3

File tree

12 files changed

+185
-32
lines changed

12 files changed

+185
-32
lines changed

app/components/CustomImage/index.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import React from 'react';
77

88
import FastImage from 'react-native-fast-image';
9-
import { Image, StyleSheet, View } from 'react-native';
9+
import { Image, StyleSheet, View, Animated } from 'react-native';
1010
import { observer } from 'mobx-react';
1111
// import {observable, action} from 'mobx';
1212

@@ -31,6 +31,22 @@ class CustomImage extends React.Component<Props, any> {
3131
this.props.onError && this.props.onError();
3232
}
3333

34+
onLoad = () => {
35+
const minimumWait = 100;
36+
const staggerNonce = 200 * Math.random();
37+
38+
setTimeout(
39+
() => {
40+
Animated.timing(placeholderOpacity, {
41+
toValue: 0,
42+
duration: 350,
43+
useNativeDriver: Android ? false : true,
44+
}).start();
45+
},
46+
Platform.OS === 'android' ? 0 : Math.floor(minimumWait + staggerNonce)
47+
);
48+
};
49+
3450
render() {
3551
let { source } = this.props;
3652
const { style, resizeMode } = this.props;
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/**
2+
* Created by Rabbit on 2019-08-12.
3+
* @flow
4+
*/
5+
6+
import React, { useState } from 'react';
7+
import PropTypes, { any } from 'prop-types';
8+
import { Animated, Image as ImageNative, StyleSheet, View, Platform } from 'react-native';
9+
import FastImage, { ImageStyle } from 'react-native-fast-image';
10+
11+
const CustomImage = ({
12+
placeholderStyle,
13+
PlaceholderContent,
14+
containerStyle,
15+
style,
16+
ImageComponent,
17+
children,
18+
...attributes
19+
}) => {
20+
const [placeholderOpacity] = useState(new Animated.Value(1));
21+
const [imageError, setImageError] = useState(false);
22+
const hasImage = typeof attributes.source !== 'undefined';
23+
24+
const onLoad = () => {
25+
setImageError(false);
26+
const minimumWait = 100;
27+
const staggerNonce = 200 * Math.random();
28+
29+
setTimeout(
30+
() => {
31+
Animated.timing(placeholderOpacity, {
32+
toValue: 0,
33+
duration: 350,
34+
useNativeDriver: Platform.OS !== 'android'
35+
}).start();
36+
},
37+
Platform.OS === 'android' ? 0 : Math.floor(minimumWait + staggerNonce)
38+
);
39+
};
40+
41+
const onError = () => {
42+
setImageError(true);
43+
};
44+
45+
return (
46+
<View accessibilityIgnoresInvertColors={true} style={StyleSheet.flatten([styles.container, containerStyle])}>
47+
<ImageComponent
48+
{...attributes}
49+
onLoad={onLoad}
50+
onError={onError}
51+
style={[
52+
StyleSheet.absoluteFill,
53+
{
54+
width: style.width,
55+
height: style.height
56+
}
57+
]}
58+
testID="RNE__Image"
59+
/>
60+
61+
<Animated.View
62+
pointerEvents={hasImage ? 'none' : 'auto'}
63+
accessibilityElementsHidden={hasImage}
64+
importantForAccessibility={hasImage ? 'no-hide-descendants' : 'yes'}
65+
style={[
66+
styles.placeholderContainer,
67+
{
68+
opacity: hasImage ? placeholderOpacity : 1
69+
}
70+
]}
71+
>
72+
<View
73+
testID="RNE__Image__placeholder"
74+
style={StyleSheet.flatten([style, styles.placeholder, placeholderStyle])}
75+
>
76+
{PlaceholderContent}
77+
</View>
78+
</Animated.View>
79+
80+
<View style={style}>{children}</View>
81+
82+
{imageError && (
83+
<FastImage
84+
source={{ uri: 'https://reactnativecode.com/wp-content/uploads/2018/01/Error_Img.png' }}
85+
style={[containerStyle, style]}
86+
/>
87+
)}
88+
</View>
89+
);
90+
};
91+
92+
const styles = {
93+
container: {
94+
backgroundColor: 'transparent',
95+
position: 'relative'
96+
},
97+
placeholderContainer: {
98+
...StyleSheet.absoluteFillObject
99+
},
100+
placeholder: {
101+
backgroundColor: '#bdbdbd',
102+
alignItems: 'center',
103+
justifyContent: 'center'
104+
}
105+
};
106+
107+
CustomImage.propTypes = {
108+
...ImageStyle,
109+
ImageComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
110+
PlaceholderContent: any,
111+
containerStyle: any,
112+
placeholderStyle: ImageNative.propTypes.style
113+
};
114+
115+
CustomImage.defaultProps = {
116+
ImageComponent: FastImage,
117+
style: {}
118+
};
119+
120+
export { CustomImage };

app/mobx/News/BuDeJieMobx.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,15 @@ class BuDeJieMobx extends ConfigStore {
167167
try {
168168
const buDeJieData: RTBDJResult = await loadBuDeJieData(type, value);
169169

170+
// const { largeListData, dataSource } = await BuDeJieMobx.handleLargeListData(buDeJieData.data.list, type);
170171
const { largeListData, dataSource } = await BuDeJieMobx.handleLargeListData(buDeJieData.list, type);
171172

172173
if (value === '') {
173174
runInAction(() => {
174175
this.dataSource = dataSource;
175176
this.largeListData = [largeListData];
176177
this.maxtime = buDeJieData.info.maxid;
178+
// this.maxtime = buDeJieData.data.info.maxid;
177179
});
178180
} else {
179181
runInAction(() => {

app/mobx/News/WelfareMobx.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,11 @@ class WelfareMobx extends ConfigStore {
6262
this.page = type === 'refreshing' ? 1 : this.page + 1;
6363

6464
try {
65-
// const welfareData: RTGankData = await fetchWelfareData(this.page);
66-
const welfareData: RTWealResult = await fetchWelfareData(this.page);
65+
const welfareData: RTGankData = await fetchWelfareData(this.page);
66+
// const welfareData: RTWealResult = await fetchWelfareData(this.page);
6767
console.log('welfareData', welfareData);
6868

69+
// const results = welfareData.data;
6970
const results = welfareData.results;
7071

7172
const defaultHeights = [216, 245, 263, 234, 259, 222];

app/pages/News/News.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { observer } from 'mobx-react-lite';
1313
import ScrollableTabView, { DefaultTabBar } from 'react-native-scrollable-tab-view';
1414

1515
import { Welfare } from './Welfare';
16-
import { BuDeJie } from './BuDeJie';
16+
import { BuDeJie } from './BuDeJie/index';
1717

1818
import { StoreContext } from '../../utils/Tool';
1919

@@ -26,11 +26,11 @@ type typeItem = {
2626
};
2727

2828
const typeArr: Array<typeItem> = [
29+
{ key: 'WELFARE', title: '福利', type: '福利' },
2930
{ key: 'ALL', title: '全部', type: 1 },
3031
{ key: 'VIDEO', title: '视频', type: 41 },
3132
{ key: 'PICTURE', title: '图片', type: 10 },
32-
{ key: 'JOKE', title: '笑话', type: 29 },
33-
{ key: 'WELFARE', title: '福利', type: '福利' }
33+
{ key: 'JOKE', title: '笑话', type: 29 }
3434
];
3535

3636
const typeData = {

app/pages/News/Welfare/index.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Created by Rabbit on 2019-02-25.
44
*/
55
import React, { useEffect, useRef } from 'react';
6-
import { StyleSheet } from 'react-native';
6+
import { StyleSheet, ActivityIndicator } from 'react-native';
77
import { WaterfallList } from 'react-native-largelist-v3';
88
import { NormalFooter } from 'react-native-spring-scrollview/NormalFooter';
99

@@ -12,7 +12,8 @@ import { WelfareMobx } from '../../../mobx/News';
1212
import { observer } from 'mobx-react-lite';
1313

1414
import type { RTWeal } from '../../../servers/News/interfaces';
15-
import { Button, CustomImage } from '../../../components';
15+
import { Button } from '../../../components';
16+
import { CustomImage } from '../../../components/CustomImage/index_new';
1617
import { System } from '../../../utils';
1718
import { ActionSheet, Overlay } from 'teaset';
1819
import type { NavigationState } from 'react-navigation';
@@ -60,7 +61,7 @@ const Welfare = observer(function(props: Props) {
6061
function showPopCustom(item: RTWeal) {
6162
const overlayView = (
6263
<Overlay.PopView
63-
style={{ alignItems: 'center', justifyContent: 'center' }}
64+
// style={{ alignItems: 'center', justifyContent: 'center' }}
6465
overlayOpacity={1}
6566
type="zoomOut"
6667
ref={customOverlayRef}
@@ -71,12 +72,14 @@ const Welfare = observer(function(props: Props) {
7172
>
7273
<CustomImage
7374
source={{ uri: item.largeUrl }}
74-
// resizeMode="cover"
75+
resizeMode="contain"
7576
style={{
76-
backgroundColor: 'white',
77+
// backgroundColor: 'white',
7778
width: SCREEN_WIDTH,
7879
height: SCREEN_HEIGHT
7980
}}
81+
PlaceholderContent={<ActivityIndicator />}
82+
placeholderStyle={{ backgroundColor: 'black' }}
8083
/>
8184
</Button>
8285
</Overlay.PopView>
@@ -87,7 +90,13 @@ const Welfare = observer(function(props: Props) {
8790
function renderItem(item: RTWeal) {
8891
return (
8992
<Button onPress={() => showPopCustom(item)} style={{ flex: 1 }}>
90-
<CustomImage source={{ uri: item.url }} style={[styles.cell]} />
93+
<CustomImage
94+
source={{ uri: item.url }}
95+
containerStyle={[styles.cell]}
96+
style={{ flex: 1 }}
97+
placeholderStyle={{ backgroundColor: 'white' }}
98+
PlaceholderContent={<ActivityIndicator />}
99+
/>
91100
</Button>
92101
);
93102
}
@@ -121,7 +130,11 @@ const styles = StyleSheet.create({
121130
},
122131
cell: {
123132
flex: 1,
124-
margin: 3,
125-
backgroundColor: 'white'
133+
margin: 3
134+
// backgroundColor: 'white',
135+
// height: 100,
136+
// width: 100,
137+
// width: SCREEN_WIDTH / 2 - 5,
138+
// height: 300
126139
}
127140
});

app/pages/STWebView/index.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export default class index extends React.Component<Props, State> {
5050

5151
componentDidMount(): void {
5252
const { configStore } = this.context;
53-
configStore.showLoading();
53+
// configStore.showLoading();
5454

5555
AppState.addEventListener('change', this._handleAppStateChange);
5656

@@ -136,6 +136,8 @@ export default class index extends React.Component<Props, State> {
136136

137137
onLoad = () => {
138138
console.log('加载中');
139+
const { configStore } = this.context;
140+
configStore.showLoading();
139141
};
140142
onLoadEnd = () => {
141143
console.log('加载结束,成功或失败都会走到这里');
@@ -144,8 +146,8 @@ export default class index extends React.Component<Props, State> {
144146
};
145147
onLoadStart = () => {
146148
console.log('开始加载');
147-
// const {configStore} = this.context;
148-
// configStore.showLoading();
149+
const {configStore} = this.context;
150+
configStore.showLoading();
149151
};
150152
onError = () => {
151153
const { configStore } = this.context;

app/routers/AppRouter.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import { TabOptions } from '../utils/TabOptions';
2525

2626
let badgeNumberListener;
2727

28-
2928
const IOS_MODAL_ROUTES = ['Login'];
3029

3130
const dynamicModalTransition = (transitionProps, prevTransitionProps) => {

app/servers/News/index.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@ type RGankType = '福利' | 'iOS' | 'Android';
1111

1212
export async function fetchWelfareData(
1313
page: number,
14-
type: RGankType = '福利',
15-
count: number = 20
14+
type?: RGankType = '福利',
15+
count?: number = 20
1616
): Promise<RTWealResult> {
1717
const _type: string = encodeURIComponent(type);
1818

19-
const url = `http://gank.io/api/data/${_type}/${count}/${page}`;
19+
let url = `http://gank.io/api/data/${_type}/${count}/${page}`;
2020

2121
const params = {
2222
type: _type,
2323
count: count,
2424
page: page
2525
};
2626

27-
// const url = ApiConfig.api.news.list;
27+
// url = ApiConfig.api.news.list;
2828

2929
return await Fetch.get(url, params);
3030
}
@@ -40,14 +40,14 @@ export async function fetchWelfareData(
4040
export type RTBuDeJieType = '1' | '41' | '10' | '29' | string | number;
4141

4242
export async function loadBuDeJieData(type: RTBuDeJieType, maxtime: string): Promise<RTBDJResult> {
43-
const url = `http://api.budejie.com/api/api_open.php?a=list&c=data&type=${type}&maxtime=${maxtime}`;
43+
let url = `http://api.budejie.com/api/api_open.php?a=list&c=data&type=${type}&maxtime=${maxtime}`;
4444

4545
const params = {
4646
type,
4747
maxtime
4848
};
4949

50-
// const url = ApiConfig.api.news.list;
50+
// url = ApiConfig.api.news.list;
5151

5252
return await Fetch.get(url, params);
5353
}

app/utils/ApiConfig.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ const base = {
1212
// baseURL:!iOS?'http://localhost:1234/api':'http://172.16.17.61:1234/api',
1313

1414
// baseURL :__DEV__ ? iOS?'http://localhost:3000/api':'http://172.16.17.11:3000/api' : 'http://shitu.leanapp.cn/api'
15-
// baseURL: 'http://shitu.leanapp.cn/api',
16-
baseURL: 'http://127.0.0.1:7001'
15+
baseURL: 'http://shitu.leanapp.cn/api',
16+
// baseURL: 'http://127.0.0.1:7001'
1717
};
1818

1919
const ApiConfig = {

0 commit comments

Comments
 (0)