如何覆盖反应原生的活动指标?

我有一个几乎没有表单元素和一个按钮的视图(TouchableHighlight)。单击按钮时,活动指示符应显示为现有视图的覆盖图。活动指示器应该位于页面的中心,现有视图应该略微模糊,以显示重叠。我尝试了不同的选择,但不能让它工作。

render() {
const { username, password } = this.state;


return (
<View style={styles.container}>
<View style={styles.group}>
<Text style={styles.text}>Username:</Text>
<TextInput
style={styles.input}
onChangeText={this.handleUserNameChange.bind(this)}
value={username}
underlineColorAndroid="transparent"
/>
</View>
<View style={styles.group}>
<Text style={styles.text}>Password:</Text>
<TextInput
style={styles.input}
secureTextEntry={true}
onChangeText={this.handlePasswordChange.bind(this)}
value={password}
underlineColorAndroid="transparent"
/>
</View>
<TouchableHighlight
style={styles.button}
onPress={this.handleLogin.bind(this)}>
<Text style={styles.buttonText}>Logon</Text>
</TouchableHighlight>
</View>
);
}

现有款式:

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
backgroundColor: '#F5FCFF',
marginTop: 60
},
group: {
alignItems: 'flex-start',
padding: 10
},
input: {
width: 150,
padding: 2,
paddingLeft: 5,
borderColor: 'gray',
borderWidth: 1
},
text: {
padding: 0
},
button: {
width: 150,
backgroundColor: '#2299F2',
padding: 15,
marginTop: 20,
borderRadius: 5
},
buttonText: {
textAlign: 'center',
color: '#fff',
fontSize: 24
},
});

我需要一个活动指示器以上视图,覆盖视图,并居中的活动指示器。

75991 次浏览

为了实现这个功能,你需要将它定位为 absolute,然后将应该位于覆盖层下面的元素渲染为 之后:

  loading: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center'
}

然后根据加载状态有条件地将其组合到 render方法中。我假设 this.handleLogin已经设置了某种加载状态。

确保它是最后渲染的,这样它才有优先权。

...
{this.state.loading &&
<View style={styles.loading}>
<ActivityIndicator size='large' />
</View>
}

下面是一个使用 create response 本机应用程序的完整示例。

import React from 'react';
import {StyleSheet, ActivityIndicator, View} from "react-native";


export default class Example extends React.Component {


constructor(props) {
super(props);


this.state = {}


render() {
return (
<View
style=\{\{flex: 1}}
>
//Add other content here
{this.state.loading &&
<View style={styles.loading}>
<ActivityIndicator/>
</View>
}
</View>
);
}
}


showLoading() {
this.setState({loading: true})
}


hideLoading() {
this.setState({loading: false})
}


const styles = StyleSheet.create({
loading: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
opacity: 0.5,
backgroundColor: 'black',
justifyContent: 'center',
alignItems: 'center'
}
})

我认为你应该使用 Modal 来覆盖活动指标。下面是一个例子:

<Modal
transparent={true}
animationType={'none'}
visible={loading}
onRequestClose={() => {console.log('close modal')}}>
<View style={styles.modalBackground}>
<View style={styles.activityIndicatorWrapper}>
<ActivityIndicator
animating={loading} />
</View>
</View>
</Modal>

这个 反应-本机加载-旋转器覆盖有一个可用的库。 您可以简单地使用

npm install react-native-loading-spinner-overlay --save

并且可以使用

import Spinner from 'react-native-loading-spinner-overlay';

以下是使用方法

<Spinner
//visibility of Overlay Loading Spinner
visible={this.state.loading}
//Text with the Spinner
textContent={'Loading...'}
//Text style of the Spinner Text
textStyle={styles.spinnerTextStyle}
/>

enter image description here enter image description here

您可以使用活动指示器组件构建一个很好的覆盖层,方法是利用模态功能,就像 Sanaur 建议的那样。

例如,您可以使用下面的函数组件。你可以控制它的可见性通过 show道具,你可以绑定到一个状态在你的屏幕上。

一个你可以适应你需要的例子。

const ModalActivityIndicator = props => {
const {
show = false,
color = "black",
backgroundColor = "white",
dimLights = 0.6,
loadingMessage = "Doing stuff ..."
} = props;
return (
<Modal transparent={true} animationType="none" visible={show}>
<View
style=\{\{
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: `rgba(0,0,0,${dimLights})`
}}
>
<View
style=\{\{
padding: 13,
backgroundColor: `${backgroundColor}`,
borderRadius: 13
}}
>
<ActivityIndicator animating={show} color={color} size="large" />
<Text style=\{\{ color: `${color}` }}>{loadingMessage}</Text>
</View>
</View>
</Modal>
);
};

在你的屏幕上,在渲染的返回中,把它作为一个子元素添加到那里(请忽略其余的代码,我把它放在那里作为上下文)。

return (
<TouchableWithoutFeedback
onPress={() => {
Keyboard.dismiss();
}}
>
<View style=\{\{ padding: 13, flex: 1}}>
<ModalActivityIndicator show={screenIsWaiting} />
<View
style=\{\{

例如,screenIsWaiting只是一个状态

  const [screenIsWaiting, setScreenIsWaiting] = useState(false);

为了测试它,你可以在某个地方添加一个按钮,

  <Button
title="TestButton"
onPress={async () => {
setScreenIsWaiting(true);
await sleep(5000);
setScreenIsWaiting(false);
...
}}
/>

其中睡眠是一个定义为

function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

我在另一篇文章中找到了关于 stackoverflow 的 sleep ()想法。

当然,您也可以定义

<ModalActivityIndicator show={screenIsWaiting} ... />

只有一次在您的应用程序的根组件,并触发它的显示和道具通过一个全局状态容器,如 redux。

从活动指标的角度设定

位置: “绝对”, 左: 0, 右: 0, 上: 0, 底部: 0, 对齐项: ‘ center’, 内容: ‘ center’

加载视图

    position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center'

您可以使用 StyleSheet.absoluteFill来缩短代码。 把这个添加到你的渲染中:

<View style={styles.container}>
//... other code here
{this.state.loading && <View
style=\{\{
...StyleSheet.absoluteFill,
justifyContent: 'center',
alignItems: 'center',
}}>
<ActivityIndicator />
</View>}
</View>

改进:

您还可以创建一个 Loading 组件:

正在加载 js

import React from 'react';
import {View, ActivityIndicator, StyleSheet} from 'react-native';


export const Loading = ({theme = 'white', size = 'large'}) => {
const color = theme === 'white' ? '#00bdcd' : '#fff';
return (
<View
style=\{\{
...StyleSheet.absoluteFill,
justifyContent: 'center',
alignItems: 'center',
}}>
<ActivityIndicator size={size} color={color} />
</View>
);
};

那就随便用

<View style={styles.container}>
//... other code here
// remember to import Loading component
{this.state.loading && <Loading />}
</View>

第一步: 为 spinner 创建组件:

export const OverlaySpinner = () => {
return (
<View style={styles.spinnerView}>
<ActivityIndicator size="large" color="#0000ff" />
</View>
);
};

第二步:

为 spinner 视图创建样式(使用 zIndex 对于确保视图覆盖屏幕上的所有内容非常重要) :

spinnerView: {
position: "absolute",
zIndex: 1,
left: 0,
right: 0,
top: 0,
bottom: 0,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#F5FCFF88",
},

第三步:

制作纺纱部件的初始状态:

const [showSpinner, setshowSpinner] = useState(true);

第四步:

使用组件并且不要忘记导入它(不要忘记在提交时关闭键盘)

{showSpinner && <OverlaySpinner />}

在这里,我的代码是一个功能性组件,适用于任何希望用本机基础作为设计系统来实现这一点的人。useColorScheme是我用来检测黑暗模式的另一个钩子。

import { Flex, Spinner } from "native-base"
import React from "react"
import useColorScheme from "../../hooks/useColorScheme"


export default function Loading() {
const colorScheme = useColorScheme()


return (
<Flex
position="absolute"
alignItems="center"
justifyContent="center"
top={0}
left={0}
right={0}
bottom={0}
backgroundColor={colorScheme === "dark" ? "coolBlack.500" : "white"}
>
<Spinner size="lg" color={colorScheme === "dark" ? "white" : "coolBlack.500"} />
</Flex>
)
}