如何在react-native中重叠ActivityIndi​​cator?

时间:2017-05-18 11:27:57

标签: react-native

我有一个包含少量表单元素和一个按钮的视图(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
    },
});

我需要在上面的View中使用ActivityIndi​​cator,覆盖视图,并使ActivityIndi​​cator居中。

9 个答案:

答案 0 :(得分:81)

为了实现这一点,您需要absolute定位它,并在应该位于叠加层下方的元素之后将其渲染为

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

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

确保它最后呈现,因此优先。

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

答案 1 :(得分:16)

以下是使用create react native app的完整示例。

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'
        }
    })

答案 2 :(得分:1)

您还可以利用活动指示器组件,还可以利用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)触发它的显示和道具。

答案 3 :(得分:1)

根据加载情况添加

setup.exe

答案 4 :(得分:1)

您可以使用StyleSheet.absoluteFill来缩短代码。 将此添加到渲染中:

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

改进:

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

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>

答案 5 :(得分:0)

我想您应该使用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>

答案 6 :(得分:0)

react-native-loading-spinner-overlay有一个可用的库。 您可以简单地使用

进行安装
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

答案 7 :(得分:0)

在“活动指标”视图中设置

位置:“绝对”, 左:0, 右:0, 上:0, 底部:0, alignItems:'中心', justifyContent:“中心”

答案 8 :(得分:0)

第 1 步: 为微调器创建组件:

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

第 2 步:

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

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

第 3 步:

为旋转组件设置初始状态:

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

第 4 步:

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

{showSpinner && <OverlaySpinner />}