react-native-refresh-list2 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +67 -0
- package/lib/module/Loading/Loading.js +19 -0
- package/lib/module/Loading/Loading.js.map +1 -0
- package/lib/module/Loading/index.js +5 -0
- package/lib/module/Loading/index.js.map +1 -0
- package/lib/module/RefreshControl/BottomContainer.js +88 -0
- package/lib/module/RefreshControl/BottomContainer.js.map +1 -0
- package/lib/module/RefreshControl/NormalControl.js +94 -0
- package/lib/module/RefreshControl/NormalControl.js.map +1 -0
- package/lib/module/RefreshControl/RefreshContainer.js +53 -0
- package/lib/module/RefreshControl/RefreshContainer.js.map +1 -0
- package/lib/module/RefreshControl/RefreshContext.js +32 -0
- package/lib/module/RefreshControl/RefreshContext.js.map +1 -0
- package/lib/module/RefreshControl/RefreshFlatList.js +291 -0
- package/lib/module/RefreshControl/RefreshFlatList.js.map +1 -0
- package/lib/module/RefreshControl/RefreshScrollView.js +279 -0
- package/lib/module/RefreshControl/RefreshScrollView.js.map +1 -0
- package/lib/module/RefreshControl/index.js +7 -0
- package/lib/module/RefreshControl/index.js.map +1 -0
- package/lib/module/RefreshControl/type.js +39 -0
- package/lib/module/RefreshControl/type.js.map +1 -0
- package/lib/module/icon/CommentIcon.js +32 -0
- package/lib/module/icon/CommentIcon.js.map +1 -0
- package/lib/module/icon/Icon.js +25 -0
- package/lib/module/icon/Icon.js.map +1 -0
- package/lib/module/icon/MoreIcon.js +40 -0
- package/lib/module/icon/MoreIcon.js.map +1 -0
- package/lib/module/icon/Praise.js +23 -0
- package/lib/module/icon/Praise.js.map +1 -0
- package/lib/module/icon/SearchIcon.js +35 -0
- package/lib/module/icon/SearchIcon.js.map +1 -0
- package/lib/module/icon/index.js +5 -0
- package/lib/module/icon/index.js.map +1 -0
- package/lib/module/icon/library.js +20 -0
- package/lib/module/icon/library.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/Loading/Loading.d.ts +9 -0
- package/lib/typescript/src/Loading/Loading.d.ts.map +1 -0
- package/lib/typescript/src/Loading/index.d.ts +3 -0
- package/lib/typescript/src/Loading/index.d.ts.map +1 -0
- package/lib/typescript/src/RefreshControl/BottomContainer.d.ts +17 -0
- package/lib/typescript/src/RefreshControl/BottomContainer.d.ts.map +1 -0
- package/lib/typescript/src/RefreshControl/NormalControl.d.ts +20 -0
- package/lib/typescript/src/RefreshControl/NormalControl.d.ts.map +1 -0
- package/lib/typescript/src/RefreshControl/RefreshContainer.d.ts +17 -0
- package/lib/typescript/src/RefreshControl/RefreshContainer.d.ts.map +1 -0
- package/lib/typescript/src/RefreshControl/RefreshContext.d.ts +9 -0
- package/lib/typescript/src/RefreshControl/RefreshContext.d.ts.map +1 -0
- package/lib/typescript/src/RefreshControl/RefreshFlatList.d.ts +20 -0
- package/lib/typescript/src/RefreshControl/RefreshFlatList.d.ts.map +1 -0
- package/lib/typescript/src/RefreshControl/RefreshScrollView.d.ts +20 -0
- package/lib/typescript/src/RefreshControl/RefreshScrollView.d.ts.map +1 -0
- package/lib/typescript/src/RefreshControl/index.d.ts +5 -0
- package/lib/typescript/src/RefreshControl/index.d.ts.map +1 -0
- package/lib/typescript/src/RefreshControl/type.d.ts +70 -0
- package/lib/typescript/src/RefreshControl/type.d.ts.map +1 -0
- package/lib/typescript/src/icon/CommentIcon.d.ts +3 -0
- package/lib/typescript/src/icon/CommentIcon.d.ts.map +1 -0
- package/lib/typescript/src/icon/Icon.d.ts +10 -0
- package/lib/typescript/src/icon/Icon.d.ts.map +1 -0
- package/lib/typescript/src/icon/MoreIcon.d.ts +3 -0
- package/lib/typescript/src/icon/MoreIcon.d.ts.map +1 -0
- package/lib/typescript/src/icon/Praise.d.ts +9 -0
- package/lib/typescript/src/icon/Praise.d.ts.map +1 -0
- package/lib/typescript/src/icon/SearchIcon.d.ts +9 -0
- package/lib/typescript/src/icon/SearchIcon.d.ts.map +1 -0
- package/lib/typescript/src/icon/index.d.ts +3 -0
- package/lib/typescript/src/icon/index.d.ts.map +1 -0
- package/lib/typescript/src/icon/library.d.ts +17 -0
- package/lib/typescript/src/icon/library.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +168 -0
- package/src/Loading/Loading.tsx +15 -0
- package/src/Loading/index.tsx +5 -0
- package/src/RefreshControl/BottomContainer.tsx +112 -0
- package/src/RefreshControl/NormalControl.tsx +118 -0
- package/src/RefreshControl/RefreshContainer.tsx +74 -0
- package/src/RefreshControl/RefreshContext.tsx +30 -0
- package/src/RefreshControl/RefreshFlatList.tsx +372 -0
- package/src/RefreshControl/RefreshScrollView.tsx +359 -0
- package/src/RefreshControl/index.tsx +5 -0
- package/src/RefreshControl/type.ts +74 -0
- package/src/icon/CommentIcon.tsx +29 -0
- package/src/icon/Icon.tsx +26 -0
- package/src/icon/MoreIcon.tsx +38 -0
- package/src/icon/Praise.tsx +21 -0
- package/src/icon/SearchIcon.tsx +36 -0
- package/src/icon/index.tsx +3 -0
- package/src/icon/library.ts +30 -0
- package/src/index.tsx +1 -0
package/package.json
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-refresh-list2",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "reactnative 下拉刷新统一android/ios 样式ios样式",
|
|
5
|
+
"main": "./lib/module/index.js",
|
|
6
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"source": "./src/index.tsx",
|
|
10
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
11
|
+
"default": "./lib/module/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"src",
|
|
17
|
+
"lib",
|
|
18
|
+
"!ios/build",
|
|
19
|
+
"!android/build",
|
|
20
|
+
"!android/gradle",
|
|
21
|
+
"!android/gradlew",
|
|
22
|
+
"!android/gradlew.bat",
|
|
23
|
+
"!android/local.properties",
|
|
24
|
+
"!**/__tests__",
|
|
25
|
+
"!**/__fixtures__",
|
|
26
|
+
"!**/__mocks__",
|
|
27
|
+
"!**/.*"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"example": "yarn workspace react-native-refresh-flatlist-example",
|
|
31
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
32
|
+
"prepare": "bob build",
|
|
33
|
+
"typecheck": "tsc",
|
|
34
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
35
|
+
"test": "jest",
|
|
36
|
+
"release": "release-it --only-version"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"react-native",
|
|
40
|
+
"ios",
|
|
41
|
+
"android"
|
|
42
|
+
],
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/1176506184/react-native-refresh-flatlist.git"
|
|
46
|
+
},
|
|
47
|
+
"author": "tangfeifan <1050069968@qq.com> (https://github.com/1176506184/react-native-refresh-flatlist)",
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/1176506184/react-native-refresh-flatlist/issues"
|
|
51
|
+
},
|
|
52
|
+
"homepage": "https://github.com/1176506184/react-native-refresh-flatlist#readme",
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"registry": "https://registry.npmjs.org/"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@babel/core": "^7.25.2",
|
|
58
|
+
"@commitlint/config-conventional": "^19.8.1",
|
|
59
|
+
"@eslint/compat": "^1.3.2",
|
|
60
|
+
"@eslint/eslintrc": "^3.3.1",
|
|
61
|
+
"@eslint/js": "^9.35.0",
|
|
62
|
+
"@react-native/babel-preset": "0.83.0",
|
|
63
|
+
"@react-native/eslint-config": "0.83.0",
|
|
64
|
+
"@release-it/conventional-changelog": "^10.0.1",
|
|
65
|
+
"@types/jest": "^29.5.14",
|
|
66
|
+
"@types/react": "^19.2.0",
|
|
67
|
+
"commitlint": "^19.8.1",
|
|
68
|
+
"del-cli": "^6.0.0",
|
|
69
|
+
"eslint": "^9.35.0",
|
|
70
|
+
"eslint-config-prettier": "^10.1.8",
|
|
71
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
72
|
+
"jest": "^29.7.0",
|
|
73
|
+
"lefthook": "^2.0.3",
|
|
74
|
+
"prettier": "^2.8.8",
|
|
75
|
+
"react": "19.2.0",
|
|
76
|
+
"react-native": "0.83.0",
|
|
77
|
+
"react-native-builder-bob": "^0.40.13",
|
|
78
|
+
"react-native-gesture-handler": "^2.30.0",
|
|
79
|
+
"react-native-reanimated": "^4.1.0",
|
|
80
|
+
"react-native-svg": "^15.15.3",
|
|
81
|
+
"react-native-worklets": "0.7",
|
|
82
|
+
"release-it": "^19.0.4",
|
|
83
|
+
"turbo": "^2.5.6",
|
|
84
|
+
"typescript": "^5.9.2"
|
|
85
|
+
},
|
|
86
|
+
"peerDependencies": {
|
|
87
|
+
"react": "*",
|
|
88
|
+
"react-native": "*",
|
|
89
|
+
"react-native-gesture-handler": "*",
|
|
90
|
+
"react-native-reanimated": "^4.1.0",
|
|
91
|
+
"react-native-svg": "*",
|
|
92
|
+
"react-native-worklets": "0.7"
|
|
93
|
+
},
|
|
94
|
+
"workspaces": [
|
|
95
|
+
"example"
|
|
96
|
+
],
|
|
97
|
+
"packageManager": "yarn@4.11.0",
|
|
98
|
+
"react-native-builder-bob": {
|
|
99
|
+
"source": "src",
|
|
100
|
+
"output": "lib",
|
|
101
|
+
"targets": [
|
|
102
|
+
[
|
|
103
|
+
"module",
|
|
104
|
+
{
|
|
105
|
+
"esm": true
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
[
|
|
109
|
+
"typescript",
|
|
110
|
+
{
|
|
111
|
+
"project": "tsconfig.build.json"
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
"prettier": {
|
|
117
|
+
"quoteProps": "consistent",
|
|
118
|
+
"singleQuote": true,
|
|
119
|
+
"tabWidth": 2,
|
|
120
|
+
"trailingComma": "es5",
|
|
121
|
+
"useTabs": false
|
|
122
|
+
},
|
|
123
|
+
"jest": {
|
|
124
|
+
"preset": "react-native",
|
|
125
|
+
"modulePathIgnorePatterns": [
|
|
126
|
+
"<rootDir>/example/node_modules",
|
|
127
|
+
"<rootDir>/lib/"
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
"commitlint": {
|
|
131
|
+
"extends": [
|
|
132
|
+
"@commitlint/config-conventional"
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
"release-it": {
|
|
136
|
+
"git": {
|
|
137
|
+
"commitMessage": "chore: release ${version}",
|
|
138
|
+
"tagName": "v${version}"
|
|
139
|
+
},
|
|
140
|
+
"npm": {
|
|
141
|
+
"publish": true
|
|
142
|
+
},
|
|
143
|
+
"github": {
|
|
144
|
+
"release": true
|
|
145
|
+
},
|
|
146
|
+
"plugins": {
|
|
147
|
+
"@release-it/conventional-changelog": {
|
|
148
|
+
"preset": {
|
|
149
|
+
"name": "angular"
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
"create-react-native-library": {
|
|
155
|
+
"type": "turbo-module",
|
|
156
|
+
"languages": "kotlin-objc",
|
|
157
|
+
"tools": [
|
|
158
|
+
"eslint",
|
|
159
|
+
"jest",
|
|
160
|
+
"lefthook",
|
|
161
|
+
"release-it"
|
|
162
|
+
],
|
|
163
|
+
"version": "0.57.2"
|
|
164
|
+
},
|
|
165
|
+
"resolutions": {
|
|
166
|
+
"semver": "7.6.3"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ActivityIndicator } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export interface LoadingProps {
|
|
5
|
+
color?: string;
|
|
6
|
+
size?: 'small' | 'large';
|
|
7
|
+
animating?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const Loading: React.FC<LoadingProps> = (props) => {
|
|
11
|
+
const { color, size, animating = true } = props;
|
|
12
|
+
return <ActivityIndicator {...{ color, size, animating }} />;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default Loading;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refresh Control Implement
|
|
3
|
+
* Every Control can get props from useRefresh()
|
|
4
|
+
*/
|
|
5
|
+
import React, {useState} from 'react';
|
|
6
|
+
import {View, Text, StyleSheet} from 'react-native';
|
|
7
|
+
import Animated, {
|
|
8
|
+
useAnimatedStyle,
|
|
9
|
+
useAnimatedReaction,
|
|
10
|
+
runOnJS,
|
|
11
|
+
withTiming,
|
|
12
|
+
useSharedValue,
|
|
13
|
+
} from 'react-native-reanimated';
|
|
14
|
+
import {RefreshStatus, useRefreshScroll} from './type';
|
|
15
|
+
import {Icon} from '../icon';
|
|
16
|
+
import {Loading} from '../Loading';
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
interface NormalControlProps {
|
|
20
|
+
textConfig?: {
|
|
21
|
+
normal: string;
|
|
22
|
+
release: string;
|
|
23
|
+
refresing: string;
|
|
24
|
+
done: string;
|
|
25
|
+
};
|
|
26
|
+
position: 'top' | 'bottom';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const NormalControl: React.FC<NormalControlProps> = (props) => {
|
|
30
|
+
const {
|
|
31
|
+
textConfig = {
|
|
32
|
+
normal: '下拉刷新',
|
|
33
|
+
release: '释放以刷新',
|
|
34
|
+
refresing: '努力刷新中',
|
|
35
|
+
done: '刷新成功',
|
|
36
|
+
},
|
|
37
|
+
position,
|
|
38
|
+
} = props;
|
|
39
|
+
const {transitionY, triggleHeight, refreshStatus} = useRefreshScroll();
|
|
40
|
+
const [refreshText, setRefreshText] = useState(textConfig.normal);
|
|
41
|
+
const [loading, setLoading] = useState(false);
|
|
42
|
+
const degree = useSharedValue(0);
|
|
43
|
+
|
|
44
|
+
const setRefreshTextByStatus = (text: string) => {
|
|
45
|
+
setRefreshText(text);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
useAnimatedReaction(
|
|
49
|
+
() => refreshStatus.value,
|
|
50
|
+
(value) => {
|
|
51
|
+
if (value === RefreshStatus.Idle) {
|
|
52
|
+
runOnJS(setRefreshTextByStatus)(textConfig.normal);
|
|
53
|
+
}
|
|
54
|
+
if (value === RefreshStatus.Pulling) {
|
|
55
|
+
runOnJS(setRefreshTextByStatus)(textConfig.normal);
|
|
56
|
+
}
|
|
57
|
+
if (value === RefreshStatus.Reached) {
|
|
58
|
+
runOnJS(setRefreshTextByStatus)(textConfig.release);
|
|
59
|
+
}
|
|
60
|
+
if (value === RefreshStatus.Holding) {
|
|
61
|
+
runOnJS(setRefreshTextByStatus)(textConfig.refresing);
|
|
62
|
+
runOnJS(setLoading)(true);
|
|
63
|
+
}
|
|
64
|
+
if (value === RefreshStatus.Done) {
|
|
65
|
+
runOnJS(setRefreshTextByStatus)(textConfig.done);
|
|
66
|
+
runOnJS(setLoading)(false);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const arrowStyle = useAnimatedStyle(() => {
|
|
72
|
+
degree.value = withTiming(transitionY.value >= triggleHeight ? 180 : 0, {
|
|
73
|
+
duration: 200,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
transform: [
|
|
78
|
+
{
|
|
79
|
+
rotateZ: `${degree.value}deg`,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<View style={styles.container}>
|
|
87
|
+
{loading ? (
|
|
88
|
+
<Loading/>
|
|
89
|
+
) : (
|
|
90
|
+
<Animated.View style={arrowStyle}>
|
|
91
|
+
<Icon
|
|
92
|
+
name={position === 'top' ? 'arrow-line-down' : 'arrow-line-up'}
|
|
93
|
+
size={18}
|
|
94
|
+
color={'grey'}
|
|
95
|
+
/>
|
|
96
|
+
</Animated.View>
|
|
97
|
+
)}
|
|
98
|
+
<Text style={styles.textStyle}>{refreshText}</Text>
|
|
99
|
+
</View>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const styles = StyleSheet.create({
|
|
104
|
+
container: {
|
|
105
|
+
flexDirection: 'row',
|
|
106
|
+
},
|
|
107
|
+
textStyle: {
|
|
108
|
+
marginHorizontal: 10,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export default NormalControl;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refresh Control Implement
|
|
3
|
+
* Every Control can get props from useRefresh()
|
|
4
|
+
*/
|
|
5
|
+
import React, { useState } from 'react';
|
|
6
|
+
import { View, StyleSheet, Text } from 'react-native';
|
|
7
|
+
import Animated, {
|
|
8
|
+
useAnimatedStyle,
|
|
9
|
+
useAnimatedReaction,
|
|
10
|
+
runOnJS,
|
|
11
|
+
withTiming,
|
|
12
|
+
useSharedValue,
|
|
13
|
+
} from 'react-native-reanimated';
|
|
14
|
+
import { RefreshStatus, useRefreshScroll } from './type';
|
|
15
|
+
import { Icon } from '../icon';
|
|
16
|
+
import { Loading } from '../Loading';
|
|
17
|
+
|
|
18
|
+
interface NormalControlProps {
|
|
19
|
+
textConfig?: {
|
|
20
|
+
normal: string;
|
|
21
|
+
release: string;
|
|
22
|
+
refresing: string;
|
|
23
|
+
done: string;
|
|
24
|
+
};
|
|
25
|
+
position: 'top' | 'bottom';
|
|
26
|
+
textStyle?: any;
|
|
27
|
+
iconColor?: string;
|
|
28
|
+
arrowColor?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const NormalControl: React.FC<NormalControlProps> = (props) => {
|
|
32
|
+
const {
|
|
33
|
+
textConfig = {
|
|
34
|
+
normal: '下拉刷新',
|
|
35
|
+
release: '释放以刷新',
|
|
36
|
+
refresing: '努力刷新中',
|
|
37
|
+
done: '刷新成功',
|
|
38
|
+
},
|
|
39
|
+
position,
|
|
40
|
+
} = props;
|
|
41
|
+
const { transitionY, triggleHeight, refreshStatus } = useRefreshScroll();
|
|
42
|
+
const [refreshText, setRefreshText] = useState(textConfig.normal);
|
|
43
|
+
const [loading, setLoading] = useState(false);
|
|
44
|
+
const degree = useSharedValue(0);
|
|
45
|
+
const iconColor = props.iconColor || '#7A6FFA';
|
|
46
|
+
const arrowColor = props.arrowColor || 'grey';
|
|
47
|
+
|
|
48
|
+
const setRefreshTextByStatus = (text: string) => {
|
|
49
|
+
setRefreshText(text);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
useAnimatedReaction(
|
|
53
|
+
() => refreshStatus.value,
|
|
54
|
+
(value) => {
|
|
55
|
+
if (value === RefreshStatus.Idle) {
|
|
56
|
+
runOnJS(setRefreshTextByStatus)(textConfig.normal);
|
|
57
|
+
}
|
|
58
|
+
if (value === RefreshStatus.Pulling) {
|
|
59
|
+
runOnJS(setRefreshTextByStatus)(textConfig.normal);
|
|
60
|
+
}
|
|
61
|
+
if (value === RefreshStatus.Reached) {
|
|
62
|
+
runOnJS(setRefreshTextByStatus)(textConfig.release);
|
|
63
|
+
}
|
|
64
|
+
if (value === RefreshStatus.Holding) {
|
|
65
|
+
runOnJS(setRefreshTextByStatus)(textConfig.refresing);
|
|
66
|
+
runOnJS(setLoading)(true);
|
|
67
|
+
}
|
|
68
|
+
if (value === RefreshStatus.Done) {
|
|
69
|
+
console.log('done');
|
|
70
|
+
runOnJS(setRefreshTextByStatus)(textConfig.done);
|
|
71
|
+
runOnJS(setLoading)(false);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const arrowStyle = useAnimatedStyle(() => {
|
|
77
|
+
degree.value = withTiming(transitionY.value >= triggleHeight ? 180 : 0, {
|
|
78
|
+
duration: 200,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
transform: [
|
|
83
|
+
{
|
|
84
|
+
rotateZ: `${degree.value}deg`,
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<View style={styles.container}>
|
|
92
|
+
{loading ? (
|
|
93
|
+
<Loading color={iconColor} />
|
|
94
|
+
) : (
|
|
95
|
+
<Animated.View style={arrowStyle}>
|
|
96
|
+
<Icon
|
|
97
|
+
name={position === 'top' ? 'arrow-line-down' : 'arrow-line-up'}
|
|
98
|
+
size={18}
|
|
99
|
+
color={arrowColor}
|
|
100
|
+
/>
|
|
101
|
+
</Animated.View>
|
|
102
|
+
)}
|
|
103
|
+
<Text style={[styles.textStyle, props.textStyle]}>{refreshText}</Text>
|
|
104
|
+
</View>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const styles = StyleSheet.create({
|
|
109
|
+
container: {
|
|
110
|
+
flexDirection: 'row',
|
|
111
|
+
alignItems: 'center'
|
|
112
|
+
},
|
|
113
|
+
textStyle: {
|
|
114
|
+
marginHorizontal: 10,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
export default NormalControl;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React, { createContext, useContext } from 'react';
|
|
2
|
+
import { StyleSheet, Dimensions } from 'react-native';
|
|
3
|
+
import Animated, {
|
|
4
|
+
interpolate,
|
|
5
|
+
useAnimatedStyle,
|
|
6
|
+
} from 'react-native-reanimated';
|
|
7
|
+
import type { SharedValue } from 'react-native-reanimated';
|
|
8
|
+
import { RefreshStatus } from './type';
|
|
9
|
+
|
|
10
|
+
const { width } = Dimensions.get('window');
|
|
11
|
+
|
|
12
|
+
interface RefreshContainerContextProps extends RefreshContainerProps {
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const RefreshContainerContext =
|
|
16
|
+
createContext<RefreshContainerContextProps>(
|
|
17
|
+
{} as RefreshContainerContextProps
|
|
18
|
+
);
|
|
19
|
+
export const useRefresh = () => useContext(RefreshContainerContext);
|
|
20
|
+
|
|
21
|
+
interface RefreshContainerProps {
|
|
22
|
+
transitionY: SharedValue<number>;
|
|
23
|
+
triggleHeight: number; // 当下拉距离超过该值,触发下拉刷新方法
|
|
24
|
+
refreshStatus: SharedValue<RefreshStatus>;
|
|
25
|
+
children: React.ReactNode;
|
|
26
|
+
offsetTop?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const RefreshContainer: React.FC<RefreshContainerProps> = (props) => {
|
|
30
|
+
const { children, transitionY, triggleHeight, refreshStatus } = props;
|
|
31
|
+
|
|
32
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
33
|
+
if (transitionY.value <= (0 + (props.offsetTop || 0))) {
|
|
34
|
+
return {
|
|
35
|
+
opacity: 0,
|
|
36
|
+
height: 0
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
height: transitionY.value,
|
|
41
|
+
opacity: interpolate(
|
|
42
|
+
transitionY.value,
|
|
43
|
+
[0, triggleHeight / 3, triggleHeight],
|
|
44
|
+
[0, 0, 1]
|
|
45
|
+
),
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<RefreshContainerContext.Provider
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
value={{
|
|
53
|
+
transitionY,
|
|
54
|
+
triggleHeight,
|
|
55
|
+
refreshStatus,
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
58
|
+
<Animated.View style={[styles.container, animatedStyle]}>
|
|
59
|
+
{children}
|
|
60
|
+
</Animated.View>
|
|
61
|
+
</RefreshContainerContext.Provider>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const styles = StyleSheet.create({
|
|
66
|
+
container: {
|
|
67
|
+
width,
|
|
68
|
+
alignItems: 'center',
|
|
69
|
+
justifyContent: 'center',
|
|
70
|
+
position: 'absolute',
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
export default RefreshContainer;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, {createContext, useContext, useState} from 'react';
|
|
2
|
+
|
|
3
|
+
// 定义上下文类型
|
|
4
|
+
interface RefreshContextType {
|
|
5
|
+
isRefreshing: boolean;
|
|
6
|
+
setIsRefreshing: (value: boolean) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// 创建上下文
|
|
10
|
+
const RefreshContext = createContext<RefreshContextType | undefined>(undefined);
|
|
11
|
+
|
|
12
|
+
// 提供上下文的 Provider 组件
|
|
13
|
+
export const RefreshProvider: React.FC = ({children}: any) => {
|
|
14
|
+
const [isRefreshing, setIsRefreshing] = useState<boolean>(false);
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<RefreshContext.Provider value={{isRefreshing, setIsRefreshing}}>
|
|
18
|
+
{children}
|
|
19
|
+
</RefreshContext.Provider>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// 自定义 Hook 用于消费上下文
|
|
24
|
+
export const useRefresh = (): RefreshContextType => {
|
|
25
|
+
const context = useContext(RefreshContext);
|
|
26
|
+
if (!context) {
|
|
27
|
+
throw new Error('useRefresh must be used within a RefreshProvider');
|
|
28
|
+
}
|
|
29
|
+
return context;
|
|
30
|
+
};
|